diff options
Diffstat (limited to 'gcc/cp/typeck.c')
-rw-r--r-- | gcc/cp/typeck.c | 445 |
1 files changed, 267 insertions, 178 deletions
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 85eef41c2e0..98da207a922 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -909,10 +909,8 @@ comptypes (t1, t2, strict) if (t1 == t2) return 1; - /* This should never happen. */ - my_friendly_assert (t1 != error_mark_node, 307); - - if (t2 == error_mark_node) + /* Suppress errors caused by previously reported errors */ + if (t1 == error_mark_node || t2 == error_mark_node) return 0; /* If either type is the internal version of sizetype, return the @@ -1405,7 +1403,7 @@ compparms (parms1, parms2) they fail to match. */ if (t1 == 0 || t2 == 0) return 0; - if (!same_type_p (TREE_VALUE (t2), TREE_VALUE (t1))) + if (!same_type_p (TREE_VALUE (t1), TREE_VALUE (t2))) return 0; t1 = TREE_CHAIN (t1); @@ -1940,7 +1938,8 @@ build_class_member_access_expr (tree object, tree member, && integer_zerop (TREE_OPERAND (object, 0))); /* Convert OBJECT to the type of MEMBER. */ - if (!same_type_p (object_type, member_scope)) + if (!same_type_p (TYPE_MAIN_VARIANT (object_type), + TYPE_MAIN_VARIANT (member_scope))) { tree binfo; base_kind kind; @@ -1950,7 +1949,7 @@ build_class_member_access_expr (tree object, tree member, if (binfo == error_mark_node) return error_mark_node; - /* It is invalid to use to try to get to a virtual base of a + /* It is invalid to try to get to a virtual base of a NULL object. The most common cause is invalid use of offsetof macro. */ if (null_object_p && kind == bk_via_virtual) @@ -1985,7 +1984,15 @@ build_class_member_access_expr (tree object, tree member, OBJECT so that it refers to the class containing the anonymous union. Generate a reference to the anonymous union itself, and recur to find MEMBER. */ - if (ANON_AGGR_TYPE_P (DECL_CONTEXT (member))) + if (ANON_AGGR_TYPE_P (DECL_CONTEXT (member)) + /* When this code is called from build_field_call, the + object already has the type of the anonymous union. + That is because the COMPONENT_REF was already + constructed, and was then disassembled before calling + build_field_call. After the function-call code is + cleaned up, this waste can be eliminated. */ + && (!same_type_ignoring_top_level_qualifiers_p + (TREE_TYPE (object), DECL_CONTEXT (member)))) { tree anonymous_union; @@ -2165,8 +2172,13 @@ finish_class_member_access_expr (tree object, tree name) /* Find the base of OBJECT_TYPE corresponding to SCOPE. */ access_path = lookup_base (object_type, scope, ba_check, NULL); - if (!access_path || access_path == error_mark_node) + if (access_path == error_mark_node) return error_mark_node; + if (!access_path) + { + error ("`%T' is not a base of `%T'", scope, object_type); + return error_mark_node; + } /* Look up the member. */ member = lookup_member (access_path, name, /*protect=*/1, @@ -2632,12 +2644,11 @@ get_member_function_from_ptrfunc (instance_ptrptr, function) } tree -build_function_call_real (function, params, require_complete, flags) +build_function_call_real (function, params, flags) tree function, params; - int require_complete, flags; + int flags; { register tree fntype, fndecl; - register tree value_type; register tree coerced_params; tree result; tree name = NULL_TREE, assembler_name = NULL_TREE; @@ -2742,27 +2753,14 @@ build_function_call_real (function, params, require_complete, flags) return result; } - /* Some built-in function calls will be evaluated at - compile-time in fold (). */ - result = fold (build_call (function, coerced_params)); - value_type = TREE_TYPE (result); - - if (require_complete) - { - if (TREE_CODE (value_type) == VOID_TYPE) - return result; - result = require_complete_type (result); - } - if (IS_AGGR_TYPE (value_type)) - result = build_cplus_new (value_type, result); - return convert_from_reference (result); + return build_cxx_call (function, params, coerced_params); } tree build_function_call (function, params) tree function, params; { - return build_function_call_real (function, params, 1, LOOKUP_NORMAL); + return build_function_call_real (function, params, LOOKUP_NORMAL); } /* Convert the actual parameter expressions in the list VALUES @@ -3888,7 +3886,45 @@ condition_conversion (expr) t = fold (build1 (CLEANUP_POINT_EXPR, boolean_type_node, t)); return t; } - + +/* Return an ADDR_EXPR giving the address of T. This function + attempts no optimizations or simplifications; it is a low-level + primitive. */ + +tree +build_address (tree t) +{ + tree addr; + + if (error_operand_p (t) || !cxx_mark_addressable (t)) + return error_mark_node; + + addr = build1 (ADDR_EXPR, + build_pointer_type (TREE_TYPE (t)), + t); + if (staticp (t)) + TREE_CONSTANT (addr) = 1; + + return addr; +} + +/* Return a NOP_EXPR converting EXPR to TYPE. */ + +tree +build_nop (tree type, tree expr) +{ + tree nop; + + if (type == error_mark_node || error_operand_p (expr)) + return expr; + + nop = build1 (NOP_EXPR, type, expr); + if (TREE_CONSTANT (expr)) + TREE_CONSTANT (nop) = 1; + + return nop; +} + /* C++: Must handle pointers to members. Perhaps type instantiation should be extended to handle conversion @@ -4278,25 +4314,22 @@ build_unary_op (code, xarg, noconvert) if (argtype != error_mark_node) argtype = build_pointer_type (argtype); - if (!cxx_mark_addressable (arg)) - return error_mark_node; - { tree addr; - if (TREE_CODE (arg) == COMPONENT_REF - && DECL_C_BIT_FIELD (TREE_OPERAND (arg, 1))) + if (TREE_CODE (arg) != COMPONENT_REF) + addr = build_address (arg); + else if (DECL_C_BIT_FIELD (TREE_OPERAND (arg, 1))) { error ("attempt to take address of bit-field structure member `%D'", TREE_OPERAND (arg, 1)); return error_mark_node; } - else if (TREE_CODE (arg) == COMPONENT_REF - && TREE_CODE (TREE_OPERAND (arg, 0)) == INDIRECT_REF - && (TREE_CODE (TREE_OPERAND (TREE_OPERAND (arg, 0), 0)) - == INTEGER_CST)) + else { - /* offsetof idiom, fold it. */ + /* Unfortunately we cannot just build an address + expression here, because we would not handle + address-constant-expressions or offsetof correctly. */ tree field = TREE_OPERAND (arg, 1); tree rval = build_unary_op (ADDR_EXPR, TREE_OPERAND (arg, 0), 0); tree binfo = lookup_base (TREE_TYPE (TREE_TYPE (rval)), @@ -4309,13 +4342,6 @@ build_unary_op (code, xarg, noconvert) addr = fold (build (PLUS_EXPR, argtype, rval, cp_convert (argtype, byte_position (field)))); } - else - addr = build1 (ADDR_EXPR, argtype, arg); - - /* Address of a static or external variable or - function counts as a constant */ - if (staticp (arg)) - TREE_CONSTANT (addr) = 1; if (TREE_CODE (argtype) == POINTER_TYPE && TREE_CODE (TREE_TYPE (argtype)) == METHOD_TYPE) @@ -4529,7 +4555,7 @@ cxx_mark_addressable (exp) warning ("address requested for `%D', which is declared `register'", x); TREE_ADDRESSABLE (x) = 1; - put_var_into_stack (x); + put_var_into_stack (x, /*rescan=*/true); return true; case FUNCTION_DECL: @@ -4646,12 +4672,25 @@ build_compound_expr (list) return build (COMPOUND_EXPR, TREE_TYPE (rest), first, rest); } +/* Issue an error message if casting from SRC_TYPE to DEST_TYPE casts + away constness. */ + +static void +check_for_casting_away_constness (tree src_type, tree dest_type) +{ + if (casts_away_constness (src_type, dest_type)) + error ("static_cast from type `%T' to type `%T' casts away constness", + src_type, dest_type); +} + +/* Return an expression representing static_cast<TYPE>(EXPR). */ + tree build_static_cast (type, expr) tree type, expr; { tree intype; - int ok; + tree result; if (type == error_mark_node || expr == error_mark_node) return error_mark_node; @@ -4672,89 +4711,163 @@ build_static_cast (type, expr) && TREE_TYPE (expr) == TREE_TYPE (TREE_OPERAND (expr, 0))) expr = TREE_OPERAND (expr, 0); - if (TREE_CODE (type) == VOID_TYPE) - { - expr = convert_to_void (expr, /*implicit=*/NULL); - return expr; + intype = TREE_TYPE (expr); + + /* [expr.static.cast] + + An lvalue of type "cv1 B", where B is a class type, can be cast + to type "reference to cv2 D", where D is a class derived (clause + _class.derived_) from B, if a valid standard conversion from + "pointer to D" to "pointer to B" exists (_conv.ptr_), cv2 is the + same cv-qualification as, or greater cv-qualification than, cv1, + and B is not a virtual base class of D. */ + /* We check this case before checking the validity of "TYPE t = + EXPR;" below because for this case: + + struct B {}; + struct D : public B { D(const B&); }; + extern B& b; + void f() { static_cast<const D&>(b); } + + we want to avoid constructing a new D. The standard is not + completely clear about this issue, but our interpretation is + consistent with other compilers. */ + if (TREE_CODE (type) == REFERENCE_TYPE + && CLASS_TYPE_P (TREE_TYPE (type)) + && CLASS_TYPE_P (intype) + && real_non_cast_lvalue_p (expr) + && DERIVED_FROM_P (intype, TREE_TYPE (type)) + && can_convert (build_pointer_type (TYPE_MAIN_VARIANT (intype)), + build_pointer_type (TYPE_MAIN_VARIANT + (TREE_TYPE (type)))) + && at_least_as_qualified_p (TREE_TYPE (type), intype)) + { + /* There is a standard conversion from "D*" to "B*" even if "B" + is ambiguous or inaccessible. Therefore, we ask lookup_base + to check these conditions. */ + tree base = lookup_base (TREE_TYPE (type), intype, ba_check, NULL); + + /* Convert from "B*" to "D*". This function will check that "B" + is not a virtual base of "D". */ + expr = build_base_path (MINUS_EXPR, build_address (expr), + base, /*nonnull=*/false); + /* Convert the pointer to a reference -- but then remember that + there are no expressions with reference type in C++. */ + return convert_from_reference (build_nop (type, expr)); } - if (TREE_CODE (type) == REFERENCE_TYPE) - return (convert_from_reference - (convert_to_reference (type, expr, CONV_STATIC|CONV_IMPLICIT, - LOOKUP_COMPLAIN, NULL_TREE))); + /* [expr.static.cast] - if (IS_AGGR_TYPE (type)) - return build_cplus_new (type, (build_special_member_call - (NULL_TREE, complete_ctor_identifier, - build_tree_list (NULL_TREE, expr), - TYPE_BINFO (type), LOOKUP_NORMAL))); + An expression e can be explicitly converted to a type T using a + static_cast of the form static_cast<T>(e) if the declaration T + t(e);" is well-formed, for some invented temporary variable + t. */ + result = perform_direct_initialization_if_possible (type, expr); + if (result) + return convert_from_reference (result); - intype = TREE_TYPE (expr); + /* [expr.static.cast] - /* FIXME handle casting to array type. */ + Any expression can be explicitly converted to type cv void. */ + if (TREE_CODE (type) == VOID_TYPE) + return convert_to_void (expr, /*implicit=*/NULL); - ok = 0; - if (IS_AGGR_TYPE (intype) - ? can_convert_arg (type, intype, expr) - : can_convert_arg (strip_all_pointer_quals (type), - strip_all_pointer_quals (intype), expr)) - /* This is a standard conversion. */ - ok = 1; - else if (TYPE_PTROB_P (type) && TYPE_PTROB_P (intype)) - { - /* They're pointers to objects. They must be aggregates that - are related non-virtually. */ - base_kind kind; - - if (IS_AGGR_TYPE (TREE_TYPE (type)) && IS_AGGR_TYPE (TREE_TYPE (intype)) - && lookup_base (TREE_TYPE (type), TREE_TYPE (intype), - ba_ignore | ba_quiet, &kind) - && kind != bk_via_virtual) - ok = 1; - } - else if (TYPE_PTRMEM_P (type) && TYPE_PTRMEM_P (intype)) - { - /* They're pointers to members. The pointed to objects must be - the same (ignoring CV qualifiers), and the containing classes - must be related non-virtually. */ - base_kind kind; - - if (same_type_p - (strip_all_pointer_quals (TREE_TYPE (TREE_TYPE (type))), - strip_all_pointer_quals (TREE_TYPE (TREE_TYPE (intype)))) - && (lookup_base (TYPE_OFFSET_BASETYPE (TREE_TYPE (intype)), - TYPE_OFFSET_BASETYPE (TREE_TYPE (type)), - ba_ignore | ba_quiet, &kind)) - && kind != bk_via_virtual) - ok = 1; - } - else if (TREE_CODE (intype) != BOOLEAN_TYPE - && TREE_CODE (type) != ARRAY_TYPE - && TREE_CODE (type) != FUNCTION_TYPE - && can_convert (intype, strip_all_pointer_quals (type))) - ok = 1; - else if (TREE_CODE (intype) == ENUMERAL_TYPE - && TREE_CODE (type) == ENUMERAL_TYPE) - /* DR 128: "A value of integral _or enumeration_ type can be explicitly - converted to an enumeration type." - The integral to enumeration will be accepted by the previous clause. - We need to explicitly check for enumeration to enumeration. */ - ok = 1; + /* [expr.static.cast] + The inverse of any standard conversion sequence (clause _conv_), + other than the lvalue-to-rvalue (_conv.lval_), array-to-pointer + (_conv.array_), function-to-pointer (_conv.func_), and boolean + (_conv.bool_) conversions, can be performed explicitly using + static_cast subject to the restriction that the explicit + conversion does not cast away constness (_expr.const.cast_), and + the following additional rules for specific cases: */ + /* For reference, the conversions not excluded are: integral + promotions, floating point promotion, integral conversions, + floating point conversions, floating-integral conversions, + pointer conversions, and pointer to member conversions. */ + if ((ARITHMETIC_TYPE_P (type) && ARITHMETIC_TYPE_P (intype)) + /* DR 128 + + A value of integral _or enumeration_ type can be explicitly + converted to an enumeration type. */ + || (INTEGRAL_OR_ENUMERATION_TYPE_P (type) + && INTEGRAL_OR_ENUMERATION_TYPE_P (intype))) + /* Really, build_c_cast should defer to this function rather + than the other way around. */ + return build_c_cast (type, expr); + if (TYPE_PTR_P (type) && TYPE_PTR_P (intype) + && CLASS_TYPE_P (TREE_TYPE (type)) + && CLASS_TYPE_P (TREE_TYPE (intype)) + && can_convert (build_pointer_type (TYPE_MAIN_VARIANT + (TREE_TYPE (intype))), + build_pointer_type (TYPE_MAIN_VARIANT + (TREE_TYPE (type))))) + { + tree base; + + check_for_casting_away_constness (intype, type); + base = lookup_base (TREE_TYPE (type), TREE_TYPE (intype), + ba_check, NULL); + return build_base_path (MINUS_EXPR, expr, base, /*nonnull=*/false); + } + if ((TYPE_PTRMEM_P (type) && TYPE_PTRMEM_P (intype)) + || (TYPE_PTRMEMFUNC_P (type) && TYPE_PTRMEMFUNC_P (intype))) + { + tree c1; + tree c2; + tree t1; + tree t2; + + c1 = TYPE_PTRMEM_CLASS_TYPE (intype); + c2 = TYPE_PTRMEM_CLASS_TYPE (type); + + if (TYPE_PTRMEM_P (type)) + { + t1 = (build_ptrmem_type + (c1, + TYPE_MAIN_VARIANT (TYPE_PTRMEM_POINTED_TO_TYPE (intype)))); + t2 = (build_ptrmem_type + (c2, + TYPE_MAIN_VARIANT (TYPE_PTRMEM_POINTED_TO_TYPE (type)))); + } + else + { + t1 = intype; + t2 = type; + } + if (can_convert (t1, t2)) + { + check_for_casting_away_constness (intype, type); + if (TYPE_PTRMEM_P (type)) + { + if (TREE_CODE (expr) == PTRMEM_CST) + expr = cplus_expand_constant (expr); + expr = cp_build_binary_op (PLUS_EXPR, + cp_convert (ptrdiff_type_node, expr), + get_delta_difference (c1, c2, + /*force=*/1)); + return build_nop (type, expr); + } + else + return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), expr, + /*force=*/1); + } + } + /* [expr.static.cast] - The static_cast operator shall not be used to cast away - constness. */ - if (ok && casts_away_constness (intype, type)) + An rvalue of type "pointer to cv void" can be explicitly + converted to a pointer to object type. A value of type pointer + to object converted to "pointer to cv void" and back to the + original pointer type will have its original value. */ + if (TREE_CODE (intype) == POINTER_TYPE + && VOID_TYPE_P (TREE_TYPE (intype)) + && TYPE_PTROB_P (type)) { - error ("static_cast from type `%T' to type `%T' casts away constness", - intype, type); - return error_mark_node; + check_for_casting_away_constness (intype, type); + return build_nop (type, expr); } - if (ok) - return build_c_cast (type, expr); - error ("invalid static_cast from type `%T' to type `%T'", intype, type); return error_mark_node; } @@ -4978,6 +5091,10 @@ build_c_cast (type, expr) value = convert_to_void (value, /*implicit=*/NULL); return value; } + + if (!complete_type_or_else (type, NULL_TREE)) + return error_mark_node; + /* Convert functions and arrays to pointers and convert references to their expanded types, but don't convert any other types. If, however, we are @@ -5093,7 +5210,7 @@ build_modify_expr (lhs, modifycode, rhs) tree newrhs = rhs; tree lhstype = TREE_TYPE (lhs); tree olhstype = lhstype; - tree olhs = lhs; + tree olhs = NULL_TREE; /* Avoid duplicate error messages from operands that had errors. */ if (lhs == error_mark_node || rhs == error_mark_node) @@ -5124,6 +5241,10 @@ build_modify_expr (lhs, modifycode, rhs) TREE_OPERAND (lhs, 0), newrhs); case MODIFY_EXPR: + if (TREE_SIDE_EFFECTS (TREE_OPERAND (lhs, 0))) + lhs = build (TREE_CODE (lhs), TREE_TYPE (lhs), + stabilize_reference (TREE_OPERAND (lhs, 0)), + TREE_OPERAND (lhs, 1)); newrhs = build_modify_expr (TREE_OPERAND (lhs, 0), modifycode, rhs); if (newrhs == error_mark_node) return error_mark_node; @@ -5175,8 +5296,9 @@ build_modify_expr (lhs, modifycode, rhs) { if (TREE_CODE (rhs) == CONSTRUCTOR) { - my_friendly_assert (same_type_p (TREE_TYPE (rhs), lhstype), - 20011220); + if (! same_type_p (TREE_TYPE (rhs), lhstype)) + /* Call convert to generate an error; see PR 11063. */ + rhs = convert (lhstype, rhs); result = build (INIT_EXPR, lhstype, lhs, rhs); TREE_SIDE_EFFECTS (result) = 1; return result; @@ -5324,19 +5446,20 @@ build_modify_expr (lhs, modifycode, rhs) if (lhstype != TREE_TYPE (lhs)) { + /* Avoid warnings converting integral types back into enums for + enum bit fields. */ + if (TREE_CODE (lhstype) == INTEGER_TYPE + && TREE_CODE (olhstype) == ENUMERAL_TYPE) + { + if (TREE_SIDE_EFFECTS (lhs)) + lhs = stabilize_reference (lhs); + olhs = lhs; + } lhs = copy_node (lhs); TREE_TYPE (lhs) = lhstype; } } - if (TREE_CODE (lhstype) != REFERENCE_TYPE) - { - if (TREE_SIDE_EFFECTS (lhs)) - lhs = stabilize_reference (lhs); - if (TREE_SIDE_EFFECTS (newrhs)) - newrhs = stabilize_reference (newrhs); - } - /* Convert new value to destination type. */ if (TREE_CODE (lhstype) == ARRAY_TYPE) @@ -5357,7 +5480,7 @@ build_modify_expr (lhs, modifycode, rhs) from_array = TREE_CODE (TREE_TYPE (newrhs)) == ARRAY_TYPE ? 1 + (modifycode != INIT_EXPR): 0; - return build_vec_init (lhs, newrhs, from_array); + return build_vec_init (lhs, NULL_TREE, newrhs, from_array); } if (modifycode == INIT_EXPR) @@ -5392,44 +5515,8 @@ build_modify_expr (lhs, modifycode, rhs) if (newrhs == error_mark_node) return error_mark_node; - if (TREE_CODE (newrhs) == COND_EXPR) - { - tree lhs1; - tree cond = TREE_OPERAND (newrhs, 0); - - if (TREE_SIDE_EFFECTS (lhs)) - cond = build_compound_expr (tree_cons - (NULL_TREE, lhs, - build_tree_list (NULL_TREE, cond))); - - /* Cannot have two identical lhs on this one tree (result) as preexpand - calls will rip them out and fill in RTL for them, but when the - rtl is generated, the calls will only be in the first side of the - condition, not on both, or before the conditional jump! (mrs) */ - lhs1 = break_out_calls (lhs); - - if (lhs == lhs1) - /* If there's no change, the COND_EXPR behaves like any other rhs. */ - result = build (modifycode == NOP_EXPR ? MODIFY_EXPR : INIT_EXPR, - lhstype, lhs, newrhs); - else - { - tree result_type = TREE_TYPE (newrhs); - /* We have to convert each arm to the proper type because the - types may have been munged by constant folding. */ - result - = build (COND_EXPR, result_type, cond, - build_modify_expr (lhs, modifycode, - cp_convert (result_type, - TREE_OPERAND (newrhs, 1))), - build_modify_expr (lhs1, modifycode, - cp_convert (result_type, - TREE_OPERAND (newrhs, 2)))); - } - } - else - result = build (modifycode == NOP_EXPR ? MODIFY_EXPR : INIT_EXPR, - lhstype, lhs, newrhs); + result = build (modifycode == NOP_EXPR ? MODIFY_EXPR : INIT_EXPR, + lhstype, lhs, newrhs); TREE_SIDE_EFFECTS (result) = 1; @@ -5440,10 +5527,7 @@ build_modify_expr (lhs, modifycode, rhs) if (olhstype == TREE_TYPE (result)) return result; - /* Avoid warnings converting integral types back into enums - for enum bit fields. */ - if (TREE_CODE (TREE_TYPE (result)) == INTEGER_TYPE - && TREE_CODE (olhstype) == ENUMERAL_TYPE) + if (olhs) { result = build (COMPOUND_EXPR, olhstype, result, olhs); TREE_NO_UNUSED_WARNING (result) = 1; @@ -5596,11 +5680,17 @@ build_ptrmemfunc (type, pfn, force) int force; { tree fn; - tree pfn_type = TREE_TYPE (pfn); - tree to_type = build_ptrmemfunc_type (type); + tree pfn_type; + tree to_type; + + if (error_operand_p (pfn)) + return error_mark_node; + + pfn_type = TREE_TYPE (pfn); + to_type = build_ptrmemfunc_type (type); /* Handle multiple conversions of pointer to member functions. */ - if (TYPE_PTRMEMFUNC_P (TREE_TYPE (pfn))) + if (TYPE_PTRMEMFUNC_P (pfn_type)) { tree delta = NULL_TREE; tree npfn = NULL_TREE; @@ -5847,8 +5937,6 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum) if (TREE_CODE (rhs) == TREE_LIST && TREE_VALUE (rhs) == error_mark_node) return error_mark_node; - rhs = dubious_conversion_warnings (type, rhs, errtype, fndecl, parmnum); - /* The RHS of an assignment cannot have void type. */ if (coder == VOID_TYPE) { @@ -5981,7 +6069,8 @@ convert_for_initialization (exp, type, rhs, flags, errtype, fndecl, parmnum) if (fndecl) savew = warningcount, savee = errorcount; - rhs = initialize_reference (type, rhs); + rhs = initialize_reference (type, rhs, /*decl=*/NULL_TREE, + /*cleanup=*/NULL); if (fndecl) { if (warningcount > savew) |