X-Git-Url: http://git.sourceforge.jp/view?p=pf3gnuchains%2Fgcc-fork.git;a=blobdiff_plain;f=gcc%2Fcp%2Ftypeck.c;h=4aee8a638aa61a80d0b448ec82837c563c4553c6;hp=775e2c813181808edc0f8af2fb54f69ad3d0b7ac;hb=f85d646a3e067c12f99a5a79d5e17b0388ecd53f;hpb=596c0ae6118a3054ae58bd59c77dce66a296e8d0 diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 775e2c81318..4aee8a638aa 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -44,18 +44,17 @@ int mark_addressable PROTO((tree)); static tree convert_for_assignment PROTO((tree, tree, char*, tree, int)); /* static */ tree convert_for_initialization PROTO((tree, tree, tree, int, char*, tree, int)); extern tree shorten_compare (); -extern void binary_op_error (); static tree pointer_int_sum PROTO((enum tree_code, register tree, register tree)); static tree pointer_diff PROTO((register tree, register tree)); +static int comp_target_parms PROTO((tree, tree, int)); +static int comp_ptr_ttypes_const PROTO((tree, tree)); +static int comp_ptr_ttypes_reinterpret PROTO((tree, tree)); #if 0 static tree convert_sequence (); #endif /* static */ tree unary_complex_lvalue PROTO((enum tree_code, tree)); static tree get_delta_difference PROTO((tree, tree, int)); -extern rtx original_result_rtx; -extern int warn_synth; - /* Return the target type of TYPE, which meas return T for: T*, T&, T[], T (...), and otherwise, just T. */ @@ -83,7 +82,7 @@ require_complete_type (value) { tree type; - if (current_template_parms) + if (processing_template_decl) return value; type = TREE_TYPE (value); @@ -132,9 +131,12 @@ complete_type (type) else if (TREE_CODE (type) == ARRAY_TYPE && TYPE_DOMAIN (type)) { tree t = complete_type (TREE_TYPE (type)); - if (TYPE_SIZE (t) != NULL_TREE - && current_template_parms == NULL_TREE) + if (TYPE_SIZE (t) != NULL_TREE && ! processing_template_decl) layout_type (type); + TYPE_NEEDS_CONSTRUCTING (type) + = TYPE_NEEDS_CONSTRUCTING (TYPE_MAIN_VARIANT (t)); + TYPE_NEEDS_DESTRUCTOR (type) + = TYPE_NEEDS_DESTRUCTOR (TYPE_MAIN_VARIANT (t)); } else if (IS_AGGR_TYPE (type) && CLASSTYPE_TEMPLATE_INSTANTIATION (type)) instantiate_class_template (TYPE_MAIN_VARIANT (type)); @@ -771,7 +773,7 @@ comptypes (type1, type2, strict) { int rval; look_hard: - rval = t1 == t2 || UNIQUELY_DERIVED_FROM_P (t1, t2); + rval = t1 == t2 || DERIVED_FROM_P (t1, t2); if (rval) { @@ -780,7 +782,7 @@ comptypes (type1, type2, strict) } if (strict < 0) { - val = UNIQUELY_DERIVED_FROM_P (t2, t1); + val = DERIVED_FROM_P (t2, t1); break; } } @@ -939,7 +941,7 @@ comp_target_types (ttl, ttr, nptrs) If there is not a unique most-derived base type, this function returns ERROR_MARK_NODE. */ -tree +static tree common_base_type (tt1, tt2) tree tt1, tt2; { @@ -1046,7 +1048,7 @@ compparms (parms1, parms2, strict) /* This really wants return whether or not parameter type lists would make their owning functions assignment compatible or not. */ -int +static int comp_target_parms (parms1, parms2, strict) tree parms1, parms2; int strict; @@ -1207,7 +1209,8 @@ unsigned_type (type) return unsigned_intHI_type_node; if (type1 == intQI_type_node) return unsigned_intQI_type_node; - return type; + + return signed_or_unsigned_type (1, type); } /* Return a signed type the same as TYPE in other respects. */ @@ -1235,7 +1238,8 @@ signed_type (type) return intHI_type_node; if (type1 == unsigned_intQI_type_node) return intQI_type_node; - return type; + + return signed_or_unsigned_type (0, type); } /* Return a type the same as TYPE except unsigned or @@ -1246,8 +1250,10 @@ signed_or_unsigned_type (unsignedp, type) int unsignedp; tree type; { - if (! INTEGRAL_TYPE_P (type)) + if (! INTEGRAL_TYPE_P (type) + || TREE_UNSIGNED (type) == unsignedp) return type; + if (TYPE_PRECISION (type) == TYPE_PRECISION (signed_char_type_node)) return unsignedp ? unsigned_char_type_node : signed_char_type_node; if (TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node)) @@ -1271,7 +1277,7 @@ c_sizeof (type) enum tree_code code = TREE_CODE (type); tree t; - if (current_template_parms) + if (processing_template_decl) return build_min (SIZEOF_EXPR, sizetype, type); if (code == FUNCTION_TYPE) @@ -1337,7 +1343,7 @@ tree expr_sizeof (e) tree e; { - if (current_template_parms) + if (processing_template_decl) return build_min (SIZEOF_EXPR, sizetype, e); if (TREE_CODE (e) == COMPONENT_REF @@ -1442,6 +1448,12 @@ decay_conversion (exp) type = TREE_TYPE (type); code = TREE_CODE (type); + + if (type == unknown_type_node) + { + cp_pedwarn ("assuming & on overloaded member function"); + return build_unary_op (ADDR_EXPR, exp, 0); + } } if (code == REFERENCE_TYPE) @@ -1495,7 +1507,7 @@ decay_conversion (exp) inner = build1 (CONVERT_EXPR, build_pointer_type (TREE_TYPE (TREE_TYPE (inner))), inner); - TREE_REFERENCE_EXPR (inner) = 1; + TREE_CONSTANT (inner) = TREE_CONSTANT (TREE_OPERAND (inner, 0)); } return convert (build_pointer_type (TREE_TYPE (type)), inner); } @@ -1570,9 +1582,6 @@ default_conversion (exp) if (t != type) return convert (t, exp); } - if (flag_traditional - && TYPE_MAIN_VARIANT (type) == float_type_node) - return convert (double_type_node, exp); return exp; } @@ -1619,8 +1628,8 @@ build_object_ref (datum, basetype, field) { tree binfo = binfo_or_else (basetype, dtype); if (binfo) - return build_component_ref (build_scoped_ref (datum, basetype), - field, binfo, 1); + return build_x_component_ref (build_scoped_ref (datum, basetype), + field, binfo, 1); } return error_mark_node; } @@ -1705,7 +1714,7 @@ build_component_ref (datum, component, basetype_path, protect) register tree field = NULL; register tree ref; - if (current_template_parms) + if (processing_template_decl) return build_min_nt (COMPONENT_REF, datum, component); /* If DATUM is a COMPOUND_EXPR or COND_EXPR, move our reference @@ -1788,16 +1797,20 @@ build_component_ref (datum, component, basetype_path, protect) hierarchy, the compiler will abort (because vptr lookups are not supposed to be ambiguous. */ field = CLASSTYPE_VFIELD (basetype); - else if (TREE_CODE (component) == FIELD_DECL) + else if (TREE_CODE (component) == FIELD_DECL + || TREE_CODE (component) == TYPE_DECL) { field = component; } else { + tree name = component; + if (TREE_CODE (component) == VAR_DECL) + name = DECL_NAME (component); if (basetype_path == NULL_TREE) basetype_path = TYPE_BINFO (basetype); - field = lookup_field (basetype_path, component, - protect && ! VFIELD_NAME_P (component), 0); + field = lookup_field (basetype_path, name, + protect && !VFIELD_NAME_P (name), 0); if (field == error_mark_node) return error_mark_node; @@ -1806,7 +1819,7 @@ build_component_ref (datum, component, basetype_path, protect) /* Not found as a data field, look for it as a method. If found, then if this is the only possible one, return it, else report ambiguity error. */ - tree fndecls = lookup_fnfields (basetype_path, component, 1); + tree fndecls = lookup_fnfields (basetype_path, name, 1); if (fndecls == error_mark_node) return error_mark_node; if (fndecls) @@ -1826,10 +1839,13 @@ build_component_ref (datum, component, basetype_path, protect) && ! resolves_to_fixed_type_p (datum, 0)) { tree addr = build_unary_op (ADDR_EXPR, datum, 0); + tree fntype = TREE_TYPE (fndecl); + addr = convert_pointer_to (DECL_CONTEXT (fndecl), addr); datum = build_indirect_ref (addr, NULL_PTR); my_friendly_assert (datum != error_mark_node, 310); fndecl = build_vfn_ref (&addr, datum, DECL_VINDEX (fndecl)); + TREE_TYPE (fndecl) = build_pointer_type (fntype); } mark_used (fndecl); return build (OFFSET_REF, TREE_TYPE (fndecl), datum, fndecl); @@ -1853,7 +1869,7 @@ build_component_ref (datum, component, basetype_path, protect) } } - cp_error ("`%#T' has no member named `%D'", basetype, component); + cp_error ("`%#T' has no member named `%D'", basetype, name); return error_mark_node; } else if (TREE_TYPE (field) == error_mark_node) @@ -1932,6 +1948,22 @@ build_component_ref (datum, component, basetype_path, protect) return ref; } + +/* Variant of build_component_ref for use in expressions, which should + never have REFERENCE_TYPE. */ + +tree +build_x_component_ref (datum, component, basetype_path, protect) + tree datum, component, basetype_path; + int protect; +{ + tree t = build_component_ref (datum, component, basetype_path, protect); + + if (! processing_template_decl) + t = convert_from_reference (t); + + return t; +} /* Given an expression PTR for a pointer, return an expression for the value pointed to. @@ -1947,7 +1979,7 @@ build_x_indirect_ref (ptr, errorstring) { tree rval; - if (current_template_parms) + if (processing_template_decl) return build_min_nt (INDIRECT_REF, ptr); rval = build_opfncall (INDIRECT_REF, LOOKUP_NORMAL, ptr, NULL_TREE, NULL_TREE); @@ -1961,9 +1993,14 @@ build_indirect_ref (ptr, errorstring) tree ptr; char *errorstring; { - register tree pointer = (TREE_CODE (TREE_TYPE (ptr)) == REFERENCE_TYPE ? - ptr : default_conversion (ptr)); - register tree type = TREE_TYPE (pointer); + register tree pointer, type; + + if (ptr == error_mark_node) + return error_mark_node; + + pointer = (TREE_CODE (TREE_TYPE (ptr)) == REFERENCE_TYPE + ? ptr : default_conversion (ptr)); + type = TREE_TYPE (pointer); if (ptr == current_class_ptr) return current_class_ref; @@ -2033,16 +2070,6 @@ build_indirect_ref (ptr, errorstring) will inherit the type of the array, which will be some pointer type. */ tree -build_x_array_ref (array, idx) - tree array, idx; -{ - tree rval = build_opfncall (ARRAY_REF, LOOKUP_NORMAL, array, idx, NULL_TREE); - if (rval) - return rval; - return build_array_ref (array, idx); -} - -tree build_array_ref (array, idx) tree array, idx; { @@ -2203,7 +2230,7 @@ build_x_function_call (function, params, decl) if (function == error_mark_node) return error_mark_node; - if (current_template_parms) + if (processing_template_decl) return build_min_nt (CALL_EXPR, function, params, NULL_TREE); type = TREE_TYPE (function); @@ -2239,8 +2266,12 @@ build_x_function_call (function, params, decl) /* Handle methods, friends, and overloaded functions, respectively. */ if (is_method) { + tree basetype = NULL_TREE; + if (TREE_CODE (function) == FUNCTION_DECL) { + basetype = DECL_CLASS_CONTEXT (function); + if (DECL_NAME (function)) function = DECL_NAME (function); else @@ -2249,6 +2280,7 @@ build_x_function_call (function, params, decl) else if (TREE_CODE (function) == TREE_LIST) { my_friendly_assert (TREE_CODE (TREE_VALUE (function)) == FUNCTION_DECL, 312); + basetype = DECL_CLASS_CONTEXT (TREE_VALUE (function)); function = TREE_PURPOSE (function); } else if (TREE_CODE (function) != IDENTIFIER_NODE) @@ -2276,6 +2308,10 @@ build_x_function_call (function, params, decl) must go through here in case it is a virtual function. @@ Perhaps this could be optimized. */ + if (basetype && (! current_class_type + || ! DERIVED_FROM_P (basetype, current_class_type))) + return build_member_call (basetype, function, params); + if (decl == NULL_TREE) { if (current_class_type == NULL_TREE) @@ -2315,11 +2351,11 @@ build_x_function_call (function, params, decl) } else { -#ifdef NEW_OVER - return build_new_function_call (function, params, NULL_TREE); -#else tree val = TREE_VALUE (function); + if (flag_ansi_overloading) + return build_new_function_call (function, params, NULL_TREE); + if (TREE_CODE (val) == TEMPLATE_DECL) return build_overload_call_real (function, params, LOOKUP_COMPLAIN, (struct candidate *)0, 0); @@ -2328,7 +2364,6 @@ build_x_function_call (function, params, decl) (function, params, LOOKUP_COMPLAIN); else my_friendly_abort (360); -#endif } } @@ -2396,7 +2431,7 @@ build_x_function_call (function, params, decl) decl = convert_pointer_to (TREE_TYPE (ctypeptr), decl); } else - decl = build_c_cast (ctypeptr, decl, 0); + decl = build_c_cast (ctypeptr, decl); params = tree_cons (NULL_TREE, decl, params); } @@ -2433,8 +2468,8 @@ get_member_function_from_ptrfunc (instance_ptrptr, function) idx = save_expr (build_component_ref (function, index_identifier, NULL_TREE, 0)); - e1 = build (GT_EXPR, boolean_type_node, idx, - convert (delta_type_node, integer_zero_node)); + e1 = fold (build (GT_EXPR, boolean_type_node, idx, + convert (delta_type_node, integer_zero_node))); delta = convert (ptrdiff_type_node, build_component_ref (function, delta_identifier, NULL_TREE, 0)); delta2 = DELTA2_FROM_PTRMEMFUNC (function); @@ -2443,7 +2478,7 @@ get_member_function_from_ptrfunc (instance_ptrptr, function) instance = convert_pointer_to_real (TYPE_METHOD_BASETYPE (TREE_TYPE (fntype)), instance_ptr); - if (instance == error_mark_node) + if (instance == error_mark_node && instance_ptr != error_mark_node) return instance; vtbl = convert_pointer_to (ptr_type_node, instance); @@ -2473,7 +2508,14 @@ get_member_function_from_ptrfunc (instance_ptrptr, function) e3 = PFN_FROM_PTRMEMFUNC (function); TREE_TYPE (e2) = TREE_TYPE (e3); - function = build_conditional_expr (e1, e2, e3); + e1 = build_conditional_expr (e1, e2, e3); + + if (instance_ptr == error_mark_node + && TREE_CODE (e1) != ADDR_EXPR + && TREE_CODE (TREE_OPERAND (e1, 0)) != FUNCTION_DECL) + cp_error ("object missing in `%E'", function); + + function = e1; /* Make sure this doesn't get evaluated first inside one of the branches of the COND_EXPR. */ @@ -2533,15 +2575,7 @@ build_function_call_real (function, params, require_complete, flags) needs to be separately compiled). */ if (DECL_INLINE (function)) - { - /* Is it a synthesized method that needs to be synthesized? */ - if (DECL_ARTIFICIAL (function) && ! DECL_INITIAL (function) - /* Kludge: don't synthesize for default args. */ - && current_function_decl) - synthesize_method (function); - - function = inline_conversion (function); - } + function = inline_conversion (function); else function = build_addr_func (function); } @@ -2628,6 +2662,8 @@ build_function_call_real (function, params, require_complete, flags) 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); } } @@ -2675,6 +2711,9 @@ convert_arguments (return_loc, typelist, values, fndecl, flags) if (! flag_elide_constructors) return_loc = 0; + /* Argument passing is always copy-initialization. */ + flags |= LOOKUP_ONLYCONVERTING; + if (fndecl) { if (TREE_CODE (TREE_TYPE (fndecl)) == METHOD_TYPE) @@ -2781,9 +2820,9 @@ convert_arguments (return_loc, typelist, values, fndecl, flags) } else { - parmval = convert_for_initialization (return_loc, type, val, - flags|INDIRECT_BIND, - "argument passing", fndecl, i); + parmval = convert_for_initialization + (return_loc, type, val, flags, + "argument passing", fndecl, i); #ifdef PROMOTE_PROTOTYPES if ((TREE_CODE (type) == INTEGER_TYPE || TREE_CODE (type) == ENUMERAL_TYPE) @@ -2896,9 +2935,12 @@ build_x_binary_op (code, arg1, arg2) { tree rval; - if (current_template_parms) + if (processing_template_decl) return build_min_nt (code, arg1, arg2); + if (flag_ansi_overloading) + return build_new_op (code, LOOKUP_NORMAL, arg1, arg2, NULL_TREE); + rval = build_opfncall (code, LOOKUP_SPECULATIVELY, arg1, arg2, NULL_TREE); if (rval) @@ -3444,18 +3486,12 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code) else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE) { result_type = type0; - if (pedantic) - pedwarn ("ANSI C++ forbids comparison between pointer and integer"); - else if (! flag_traditional) - warning ("comparison between pointer and integer"); + pedwarn ("ANSI C++ forbids comparison between pointer and integer"); } else if (code0 == INTEGER_TYPE && code1 == POINTER_TYPE) { result_type = type1; - if (pedantic) - pedwarn ("ANSI C++ forbids comparison between pointer and integer"); - else if (! flag_traditional) - warning ("comparison between pointer and integer"); + pedwarn ("ANSI C++ forbids comparison between pointer and integer"); } break; } @@ -3943,7 +3979,7 @@ build_x_unary_op (code, xarg) enum tree_code code; tree xarg; { - if (current_template_parms) + if (processing_template_decl) return build_min_nt (code, xarg, NULL_TREE); /* & rec, on incomplete RECORD_TYPEs is the simple opr &, not an @@ -3955,11 +3991,23 @@ build_x_unary_op (code, xarg) /* don't look for a function */; else { - tree rval = build_opfncall (code, LOOKUP_SPECULATIVELY, xarg, - NULL_TREE, NULL_TREE); - if (rval) - return build_opfncall (code, LOOKUP_NORMAL, xarg, + tree rval; + + if (flag_ansi_overloading) + { + rval = build_new_op (code, LOOKUP_NORMAL, xarg, NULL_TREE, NULL_TREE); + if (rval || code != ADDR_EXPR) + return rval; + } + else + { + rval = build_opfncall (code, LOOKUP_SPECULATIVELY, xarg, + NULL_TREE, NULL_TREE); + if (rval) + return build_opfncall (code, LOOKUP_NORMAL, xarg, + NULL_TREE, NULL_TREE); + } } if (code == ADDR_EXPR) @@ -3978,7 +4026,7 @@ condition_conversion (expr) tree expr; { tree t; - if (current_template_parms) + if (processing_template_decl) return expr; t = convert (boolean_type_node, expr); t = fold (build1 (CLEANUP_POINT_EXPR, boolean_type_node, t)); @@ -4213,8 +4261,10 @@ build_unary_op (code, xarg, noconvert) argtype = TREE_TYPE (arg); if (TREE_CODE (argtype) == REFERENCE_TYPE) { - arg = build1 (CONVERT_EXPR, build_pointer_type (TREE_TYPE (TREE_TYPE (arg))), arg); - TREE_REFERENCE_EXPR (arg) = 1; + arg = build1 + (CONVERT_EXPR, + build_pointer_type (TREE_TYPE (TREE_TYPE (arg))), arg); + TREE_CONSTANT (arg) = TREE_CONSTANT (TREE_OPERAND (arg, 0)); return arg; } else if (pedantic @@ -4235,16 +4285,12 @@ build_unary_op (code, xarg, noconvert) if (arg == current_class_ref) return current_class_ptr; - /* Keep `default_conversion' from converting if - ARG is of REFERENCE_TYPE. */ arg = TREE_OPERAND (arg, 0); if (TREE_CODE (TREE_TYPE (arg)) == REFERENCE_TYPE) { - if (TREE_CODE (arg) == VAR_DECL && DECL_INITIAL (arg) - && !TREE_SIDE_EFFECTS (DECL_INITIAL (arg))) - arg = DECL_INITIAL (arg); - arg = build1 (CONVERT_EXPR, build_pointer_type (TREE_TYPE (TREE_TYPE (arg))), arg); - TREE_REFERENCE_EXPR (arg) = 1; + arg = build1 + (CONVERT_EXPR, + build_pointer_type (TREE_TYPE (TREE_TYPE (arg))), arg); TREE_CONSTANT (arg) = TREE_CONSTANT (TREE_OPERAND (arg, 0)); } else if (lvalue_p (arg)) @@ -4440,7 +4486,9 @@ unary_complex_lvalue (code, arg) || TREE_CODE (arg) == INIT_EXPR) { tree real_result = build_unary_op (code, TREE_OPERAND (arg, 0), 0); - return build (COMPOUND_EXPR, TREE_TYPE (real_result), arg, real_result); + arg = build (COMPOUND_EXPR, TREE_TYPE (real_result), arg, real_result); + TREE_NO_UNUSED_WARNING (arg) = 1; + return arg; } if (TREE_CODE (TREE_TYPE (arg)) == FUNCTION_TYPE @@ -4451,7 +4499,6 @@ unary_complex_lvalue (code, arg) is really the representation of a pointer to it. Here give the representation its true type. */ tree t; - tree offset; my_friendly_assert (TREE_CODE (arg) != SCOPE_REF, 313); @@ -4466,6 +4513,9 @@ unary_complex_lvalue (code, arg) return build_unary_op (ADDR_EXPR, t, 0); else { + tree type; + tree offset = integer_zero_node; + if (TREE_OPERAND (arg, 0) && (TREE_CODE (TREE_OPERAND (arg, 0)) != NOP_EXPR || TREE_OPERAND (TREE_OPERAND (arg, 0), 0) != error_mark_node)) @@ -4477,10 +4527,23 @@ unary_complex_lvalue (code, arg) return error_mark_node; } - /* Add in the offset to the right subobject. */ - offset = get_delta_difference (DECL_FIELD_CONTEXT (t), - TREE_TYPE (TREE_OPERAND (arg, 0)), - 0); + type = TREE_TYPE (TREE_OPERAND (arg, 0)); + + if (TREE_CODE (TREE_TYPE (arg)) == OFFSET_TYPE) + { + /* Add in the offset to the intermediate subobject, if any. */ + offset = get_delta_difference (TYPE_OFFSET_BASETYPE (TREE_TYPE (arg)), + type, + 0); + type = TYPE_OFFSET_BASETYPE (TREE_TYPE (arg)); + } + + /* Now in the offset to the final subobject. */ + offset = size_binop (PLUS_EXPR, + offset, + get_delta_difference (DECL_FIELD_CONTEXT (t), + type, + 0)); /* Add in the offset to the field. */ offset = size_binop (PLUS_EXPR, offset, @@ -4551,7 +4614,8 @@ mark_addressable (exp) case PARM_DECL: if (x == current_class_ptr) { - error ("address of `this' not available"); + if (! flag_this_is_variable) + error ("address of `this' not available"); TREE_ADDRESSABLE (x) = 1; /* so compiler doesn't die later */ put_var_into_stack (x); return 1; @@ -4584,8 +4648,10 @@ mark_addressable (exp) case CONST_DECL: case RESULT_DECL: - /* For C++, we don't warn about taking the address of a register - variable for CONST_DECLs; ARM p97 explicitly says it's okay. */ + if (DECL_REGISTER (x) && !TREE_ADDRESSABLE (x) + && !DECL_ARTIFICIAL (x) && extra_warnings) + cp_warning ("address requested for `%D', which is declared `register'", + x); put_var_into_stack (x); TREE_ADDRESSABLE (x) = 1; return 1; @@ -4613,6 +4679,11 @@ mark_addressable (exp) TREE_ADDRESSABLE (x) = 1; return 1; + case TARGET_EXPR: + TREE_ADDRESSABLE (x) = 1; + mark_addressable (TREE_OPERAND (x, 0)); + return 1; + default: return 1; } @@ -4626,9 +4697,12 @@ build_x_conditional_expr (ifexp, op1, op2) { tree rval = NULL_TREE; - if (current_template_parms) + if (processing_template_decl) return build_min_nt (COND_EXPR, ifexp, op1, op2); + if (flag_ansi_overloading) + return build_new_op (COND_EXPR, LOOKUP_NORMAL, ifexp, op1, op2); + /* See comments in `build_x_binary_op'. */ if (op1 != 0) rval = build_opfncall (COND_EXPR, LOOKUP_SPECULATIVELY, ifexp, op1, op2); @@ -4647,7 +4721,6 @@ build_conditional_expr (ifexp, op1, op2) register enum tree_code code1; register enum tree_code code2; register tree result_type = NULL_TREE; - tree orig_op1 = op1, orig_op2 = op2; /* If second operand is omitted, it is the same as the first one; make sure it is calculated only once. */ @@ -4723,6 +4796,15 @@ build_conditional_expr (ifexp, op1, op2) result = fold (build (COND_EXPR, type1, ifexp, op1, op2)); if (TREE_TYPE (result) != type1) result = build1 (NOP_EXPR, type1, result); + /* Expand both sides into the same slot, + hopefully the target of the ?: expression. */ + if (TREE_CODE (op1) == TARGET_EXPR && TREE_CODE (op2) == TARGET_EXPR) + { + tree slot = build (VAR_DECL, TREE_TYPE (result)); + layout_decl (slot, 0); + result = build (TARGET_EXPR, TREE_TYPE (result), + slot, result, NULL_TREE, NULL_TREE); + } return result; } @@ -4796,16 +4878,14 @@ build_conditional_expr (ifexp, op1, op2) pedwarn ("ANSI C++ forbids conditional expr with only one void side"); result_type = void_type_node; } + else if (code1 == POINTER_TYPE && null_ptr_cst_p (op2)) + result_type = qualify_type (type1, type2); + else if (code2 == POINTER_TYPE && null_ptr_cst_p (op1)) + result_type = qualify_type (type2, type1); else if (code1 == POINTER_TYPE && code2 == POINTER_TYPE) { if (comp_target_types (type1, type2, 1)) result_type = common_type (type1, type2); - else if (integer_zerop (op1) && TREE_TYPE (type1) == void_type_node - && TREE_CODE (orig_op1) != NOP_EXPR) - result_type = qualify_type (type2, type1); - else if (integer_zerop (op2) && TREE_TYPE (type2) == void_type_node - && TREE_CODE (orig_op2) != NOP_EXPR) - result_type = qualify_type (type1, type2); else if (TYPE_MAIN_VARIANT (TREE_TYPE (type1)) == void_type_node) { if (pedantic && TREE_CODE (type2) == FUNCTION_TYPE) @@ -4850,20 +4930,12 @@ build_conditional_expr (ifexp, op1, op2) } else if (code1 == POINTER_TYPE && code2 == INTEGER_TYPE) { - if (!integer_zerop (op2)) - pedwarn ("pointer/integer type mismatch in conditional expression"); - else - op2 = null_pointer_node; - + pedwarn ("pointer/integer type mismatch in conditional expression"); result_type = type1; } else if (code2 == POINTER_TYPE && code1 == INTEGER_TYPE) { - if (!integer_zerop (op1)) - pedwarn ("pointer/integer type mismatch in conditional expression"); - else - op1 = null_pointer_node; - + pedwarn ("pointer/integer type mismatch in conditional expression"); result_type = type2; } @@ -4959,7 +5031,7 @@ build_x_compound_expr (list) tree rest = TREE_CHAIN (list); tree result; - if (current_template_parms) + if (processing_template_decl) return build_min_nt (COMPOUND_EXPR, list, NULL_TREE); if (rest == NULL_TREE) @@ -5030,139 +5102,247 @@ tree build_static_cast (type, expr) tree type, expr; { - if (current_template_parms) + tree intype, binfo; + int ok; + + if (type == error_mark_node || expr == error_mark_node) + return error_mark_node; + + if (TREE_CODE (expr) == OFFSET_REF) + expr = resolve_offset_ref (expr); + + if (processing_template_decl) { tree t = build_min (STATIC_CAST_EXPR, type, expr); return t; } - return build_c_cast (type, expr, 0); + /* build_c_cast puts on a NOP_EXPR to make the result not an lvalue. + Strip such NOP_EXPRs if VALUE is being used in non-lvalue context. */ + if (TREE_CODE (type) != REFERENCE_TYPE + && TREE_CODE (expr) == NOP_EXPR + && TREE_TYPE (expr) == TREE_TYPE (TREE_OPERAND (expr, 0))) + expr = TREE_OPERAND (expr, 0); + + if (TREE_CODE (type) == VOID_TYPE) + return build1 (CONVERT_EXPR, type, expr); + + if (type_unknown_p (expr)) + { + expr = instantiate_type (type, expr, 1); + if (expr == error_mark_node) + return error_mark_node; + } + + if (TREE_CODE (type) == REFERENCE_TYPE) + return (convert_from_reference + (convert_to_reference (type, expr, CONV_STATIC|CONV_IMPLICIT, + LOOKUP_COMPLAIN, NULL_TREE))); + + if (IS_AGGR_TYPE (type)) + return build_cplus_new + (type, (build_method_call + (NULL_TREE, ctor_identifier, build_tree_list (NULL_TREE, expr), + TYPE_BINFO (type), LOOKUP_NORMAL))); + + expr = decay_conversion (expr); + intype = TREE_TYPE (expr); + + /* FIXME handle casting to array type. */ + + ok = 0; + if (can_convert_arg (type, intype, expr)) + ok = 1; + else if (TYPE_PTROB_P (type) && TYPE_PTROB_P (intype)) + { + tree binfo; + if (IS_AGGR_TYPE (TREE_TYPE (type)) && IS_AGGR_TYPE (TREE_TYPE (intype)) + && (TYPE_READONLY (TREE_TYPE (type)) + >= TYPE_READONLY (TREE_TYPE (intype))) + && (TYPE_VOLATILE (TREE_TYPE (type)) + >= TYPE_VOLATILE (TREE_TYPE (intype))) + && (binfo = get_binfo (TREE_TYPE (intype), TREE_TYPE (type), 0)) + && ! TREE_VIA_VIRTUAL (binfo)) + ok = 1; + } + else if (TYPE_PTRMEM_P (type) && TYPE_PTRMEM_P (intype)) + { + if (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (type))), + TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (intype))), 1) + && (TYPE_READONLY (TREE_TYPE (TREE_TYPE (type))) + >= TYPE_READONLY (TREE_TYPE (TREE_TYPE (intype)))) + && (TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (type))) + >= TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (intype)))) + && (binfo = get_binfo (TYPE_OFFSET_BASETYPE (intype), + TYPE_OFFSET_BASETYPE (type), 0)) + && ! TREE_VIA_VIRTUAL (binfo)) + ok = 1; + } + else if (TREE_CODE (intype) != BOOLEAN_TYPE + && TREE_CODE (type) != ARRAY_TYPE + && TREE_CODE (type) != FUNCTION_TYPE + && can_convert (intype, type)) + ok = 1; + + if (ok) + return build_c_cast (type, expr); + + cp_error ("static_cast from `%T' to `%T'", intype, type); + return error_mark_node; } tree build_reinterpret_cast (type, expr) tree type, expr; { - tree intype = TREE_TYPE (expr); + tree intype; - if (current_template_parms) + if (type == error_mark_node || expr == error_mark_node) + return error_mark_node; + + if (TREE_CODE (expr) == OFFSET_REF) + expr = resolve_offset_ref (expr); + + if (processing_template_decl) { tree t = build_min (REINTERPRET_CAST_EXPR, type, expr); return t; } - if (TYPE_PTRMEMFUNC_P (type)) - if (TYPE_PTRMEMFUNC_P (intype)) - return build1 (NOP_EXPR, type, expr); + if (TREE_CODE (type) != REFERENCE_TYPE) + { + expr = decay_conversion (expr); + + /* build_c_cast puts on a NOP_EXPR to make the result not an lvalue. + Strip such NOP_EXPRs if VALUE is being used in non-lvalue context. */ + if (TREE_CODE (expr) == NOP_EXPR + && TREE_TYPE (expr) == TREE_TYPE (TREE_OPERAND (expr, 0))) + expr = TREE_OPERAND (expr, 0); + } + + if (type_unknown_p (expr)) + { + expr = instantiate_type (type, expr, 1); + if (expr == error_mark_node) + return error_mark_node; + } - if (TYPE_PTRMEMFUNC_P (type)) - type = TYPE_PTRMEMFUNC_FN_TYPE (type); + intype = TREE_TYPE (expr); - if (TYPE_PTRMEMFUNC_P (intype)) - intype = TYPE_PTRMEMFUNC_FN_TYPE (intype); + if (TREE_CODE (type) == REFERENCE_TYPE) + { + if (! real_lvalue_p (expr)) + { + cp_error ("reinterpret_cast from `%T' rvalue to `%T'", intype, type); + return error_mark_node; + } + expr = build_unary_op (ADDR_EXPR, expr, 0); + if (expr != error_mark_node) + expr = build_reinterpret_cast + (build_pointer_type (TREE_TYPE (type)), expr); + if (expr != error_mark_node) + expr = build_indirect_ref (expr, 0); + return expr; + } + else if (comptypes (TYPE_MAIN_VARIANT (intype), TYPE_MAIN_VARIANT (type), 1)) + return build_static_cast (type, expr); - if (! POINTER_TYPE_P (type) && ! TREE_CODE (type) == INTEGER_TYPE) + if (TYPE_PTR_P (type) && (TREE_CODE (intype) == INTEGER_TYPE + || TREE_CODE (intype) == ENUMERAL_TYPE)) + /* OK */; + else if (TREE_CODE (type) == INTEGER_TYPE && TYPE_PTR_P (intype)) { - cp_error ("reinterpret_cast cannot convert to type `%T'", type); - return error_mark_node; + if (TYPE_PRECISION (type) < TYPE_PRECISION (intype)) + cp_pedwarn ("reinterpret_cast from `%T' to `%T' loses precision", + intype, type); } - if (! POINTER_TYPE_P (intype) && ! TREE_CODE (intype) == INTEGER_TYPE) + else if ((TYPE_PTRFN_P (type) && TYPE_PTRFN_P (intype)) + || (TYPE_PTRMEMFUNC_P (type) && TYPE_PTRMEMFUNC_P (intype))) { - cp_error ("reinterpret_cast cannot convert from type `%T'", type); - return error_mark_node; + if (TREE_READONLY_DECL_P (expr)) + expr = decl_constant_value (expr); + return fold (build1 (NOP_EXPR, type, expr)); } - if (TREE_CODE (type) == INTEGER_TYPE && TREE_CODE (intype) != POINTER_TYPE) + else if ((TYPE_PTRMEM_P (type) && TYPE_PTRMEM_P (intype)) + || (TYPE_PTROBV_P (type) && TYPE_PTROBV_P (intype))) { - cp_error ("reinterpret_cast cannot convert non-pointer type `%T' to `%T'", - intype, type); - return error_mark_node; + if (! comp_ptr_ttypes_reinterpret (TREE_TYPE (type), TREE_TYPE (intype))) + cp_pedwarn ("reinterpret_cast from `%T' to `%T' casts away const (or volatile)", + intype, type); + + if (TREE_READONLY_DECL_P (expr)) + expr = decl_constant_value (expr); + return fold (build1 (NOP_EXPR, type, expr)); } - if (TREE_CODE (intype) == INTEGER_TYPE && TREE_CODE (type) != POINTER_TYPE) + else { - cp_error ("reinterpret_cast cannot convert `%T' to non-pointer type `%T'", - intype, type); + cp_error ("reinterpret_cast from `%T' to `%T'", intype, type); return error_mark_node; } - - if (TREE_CODE (type) == POINTER_TYPE && TREE_CODE (intype) == POINTER_TYPE) - expr = convert (ptr_type_node, expr); - - return build_c_cast (type, expr, 0); + + return convert (type, expr); } tree build_const_cast (type, expr) tree type, expr; { - tree intype = TREE_TYPE (expr); - tree t1, t2; + tree intype; if (type == error_mark_node || expr == error_mark_node) return error_mark_node; - if (current_template_parms) + if (TREE_CODE (expr) == OFFSET_REF) + expr = resolve_offset_ref (expr); + + if (processing_template_decl) { tree t = build_min (CONST_CAST_EXPR, type, expr); return t; } - if (TYPE_PTRMEMFUNC_P (type)) - type = TYPE_PTRMEMFUNC_FN_TYPE (type); - if (TYPE_PTRMEMFUNC_P (intype)) - intype = TYPE_PTRMEMFUNC_FN_TYPE (intype); - - if (! POINTER_TYPE_P (type)) - { - cp_error ("const_cast cannot convert to non-pointer type `%T'", type); - return error_mark_node; - } - if (TREE_CODE (type) == REFERENCE_TYPE && ! real_lvalue_p (expr)) - { - cp_error ("const_cast cannot convert rvalue to type `%T'", type); - return error_mark_node; - } - if (TREE_CODE (type) == POINTER_TYPE && TREE_CODE (intype) != POINTER_TYPE) + if (TREE_CODE (type) != REFERENCE_TYPE) { - cp_error ("const_cast cannot convert non-pointer type `%T' to type `%T'", - intype, type); - return error_mark_node; + expr = decay_conversion (expr); + + /* build_c_cast puts on a NOP_EXPR to make the result not an lvalue. + Strip such NOP_EXPRs if VALUE is being used in non-lvalue context. */ + if (TREE_CODE (expr) == NOP_EXPR + && TREE_TYPE (expr) == TREE_TYPE (TREE_OPERAND (expr, 0))) + expr = TREE_OPERAND (expr, 0); } - if (TREE_CODE (type) == REFERENCE_TYPE) + if (type_unknown_p (expr)) { - t1 = TREE_TYPE (type); - t2 = intype; + expr = instantiate_type (type, expr, 1); + if (expr == error_mark_node) + return error_mark_node; } - else - { - t1 = TREE_TYPE (type); - t2 = TREE_TYPE (intype); - for (; TREE_CODE (t1) == POINTER_TYPE && TREE_CODE (t2) == POINTER_TYPE; - t1 = TREE_TYPE (t1), t2 = TREE_TYPE (t2)) - ; - } + intype = TREE_TYPE (expr); - if (TREE_CODE (t1) == OFFSET_TYPE && TREE_CODE (t2) == OFFSET_TYPE) + if (comptypes (TYPE_MAIN_VARIANT (intype), TYPE_MAIN_VARIANT (type), 1)) + return build_static_cast (type, expr); + else if (TREE_CODE (type) == REFERENCE_TYPE) { - if (TYPE_OFFSET_BASETYPE (t1) != TYPE_OFFSET_BASETYPE (t2)) + if (! real_lvalue_p (expr)) { - cp_error ("const_cast cannot convert between pointers to members of different types `%T' and `%T'", - TYPE_OFFSET_BASETYPE (t2), TYPE_OFFSET_BASETYPE (t1)); + cp_error ("const_cast from `%T' rvalue to `%T'", intype, type); return error_mark_node; } - t1 = TREE_TYPE (t1); - t2 = TREE_TYPE (t2); - } - if (TYPE_MAIN_VARIANT (t1) != TYPE_MAIN_VARIANT (t2)) - { - cp_error ("const_cast cannot convert unrelated type `%T' to `%T'", - t2, t1); - return error_mark_node; + if (comp_ptr_ttypes_const (TREE_TYPE (type), intype)) + return (convert_from_reference + (convert_to_reference (type, expr, CONV_CONST|CONV_IMPLICIT, + LOOKUP_COMPLAIN, NULL_TREE))); } + else if (TREE_CODE (type) == POINTER_TYPE + && TREE_CODE (intype) == POINTER_TYPE + && comp_ptr_ttypes_const (TREE_TYPE (type), TREE_TYPE (intype))) + return convert (type, expr); - return build_c_cast (type, expr, 0); + cp_error ("const_cast from `%T' to `%T'", intype, type); + return error_mark_node; } /* Build an expression representing a cast to type TYPE of expression EXPR. @@ -5171,10 +5351,8 @@ build_const_cast (type, expr) when doing the cast. */ tree -build_c_cast (type, expr, allow_nonconverting) - register tree type; - tree expr; - int allow_nonconverting; +build_c_cast (type, expr) + tree type, expr; { register tree value = expr; @@ -5224,7 +5402,7 @@ build_c_cast (type, expr, allow_nonconverting) return error_mark_node; } - if (current_template_parms) + if (processing_template_decl) { tree t = build_min (CAST_EXPR, type, min_tree_cons (NULL_TREE, value, NULL_TREE)); @@ -5244,13 +5422,16 @@ build_c_cast (type, expr, allow_nonconverting) else { tree otype; - int flag; /* Convert functions and arrays to pointers and convert references to their expanded types, but don't convert any other types. */ if (TREE_CODE (TREE_TYPE (value)) == FUNCTION_TYPE - || TREE_CODE (TREE_TYPE (value)) == METHOD_TYPE + || (TREE_CODE (TREE_TYPE (value)) == METHOD_TYPE + /* Don't do the default conversion if we want a + pointer to a function. */ + && TREE_CODE (type) != POINTER_TYPE + && TREE_CODE (TREE_TYPE (type)) != FUNCTION_TYPE) || TREE_CODE (TREE_TYPE (value)) == ARRAY_TYPE || TREE_CODE (TREE_TYPE (value)) == REFERENCE_TYPE) value = default_conversion (value); @@ -5298,11 +5479,9 @@ build_c_cast (type, expr, allow_nonconverting) warning ("cast to pointer from integer of different size"); #endif - flag = allow_nonconverting ? CONV_NONCONVERTING : 0; - if (TREE_CODE (type) == REFERENCE_TYPE) value = (convert_from_reference - (convert_to_reference (type, value, CONV_OLD_CONVERT|flag, + (convert_to_reference (type, value, CONV_C_CAST, LOOKUP_COMPLAIN, NULL_TREE))); else { @@ -5312,7 +5491,7 @@ build_c_cast (type, expr, allow_nonconverting) value = decl_constant_value (value); ovalue = value; - value = convert_force (type, value, flag); + value = convert_force (type, value, CONV_C_CAST); /* Ignore any integer overflow caused by the cast. */ if (TREE_CODE (value) == INTEGER_CST) @@ -5324,15 +5503,9 @@ build_c_cast (type, expr, allow_nonconverting) } /* Always produce some operator for an explicit cast, - so we can tell (for -pedantic) that the cast is no lvalue. - Also, pedantically, don't let (void *) (FOO *) 0 be a null - pointer constant. */ - if (TREE_CODE (type) != REFERENCE_TYPE - && (value == expr - || (pedantic - && TREE_CODE (value) == INTEGER_CST - && TREE_CODE (expr) == INTEGER_CST - && TREE_CODE (TREE_TYPE (expr)) != INTEGER_TYPE))) + so we can tell (for -pedantic) that the cast is no lvalue. */ + if (TREE_CODE (type) != REFERENCE_TYPE && value == expr + && real_lvalue_p (value)) value = non_lvalue (value); return value; @@ -5392,7 +5565,7 @@ build_modify_expr (lhs, modifycode, rhs) tree olhs = lhs; /* Avoid duplicate error messages from operands that had errors. */ - if (TREE_CODE (lhs) == ERROR_MARK || TREE_CODE (rhs) == ERROR_MARK) + if (lhs == error_mark_node || rhs == error_mark_node) return error_mark_node; /* Types that aren't fully specified cannot be used in assignments. */ @@ -5428,14 +5601,14 @@ build_modify_expr (lhs, modifycode, rhs) case COMPOUND_EXPR: newrhs = build_modify_expr (TREE_OPERAND (lhs, 1), modifycode, rhs); - if (TREE_CODE (newrhs) == ERROR_MARK) + if (newrhs == error_mark_node) return error_mark_node; return build (COMPOUND_EXPR, lhstype, TREE_OPERAND (lhs, 0), newrhs); case MODIFY_EXPR: newrhs = build_modify_expr (TREE_OPERAND (lhs, 0), modifycode, rhs); - if (TREE_CODE (newrhs) == ERROR_MARK) + if (newrhs == error_mark_node) return error_mark_node; return build (COMPOUND_EXPR, lhstype, lhs, newrhs); @@ -5452,7 +5625,7 @@ build_modify_expr (lhs, modifycode, rhs) modifycode, rhs), build_modify_expr (convert (TREE_TYPE (lhs), TREE_OPERAND (lhs, 2)), modifycode, rhs)); - if (TREE_CODE (cond) == ERROR_MARK) + if (cond == error_mark_node) return cond; /* Make sure the code to compute the rhs comes out before the split. */ @@ -5599,13 +5772,16 @@ build_modify_expr (lhs, modifycode, rhs) { tree inner_lhs = TREE_OPERAND (lhs, 0); tree result; - if (! lvalue_p (lhs) && pedantic) - pedwarn ("cast to non-reference type used as lvalue"); + + /* WP 5.4.1: The result is an lvalue if T is a reference type, + otherwise the result is an rvalue. */ + if (! lvalue_p (lhs)) + pedwarn ("ANSI C++ forbids cast to non-reference type used as lvalue"); result = build_modify_expr (inner_lhs, NOP_EXPR, convert (TREE_TYPE (inner_lhs), convert (lhstype, newrhs))); - if (TREE_CODE (result) == ERROR_MARK) + if (result == error_mark_node) return result; return convert (TREE_TYPE (lhs), result); } @@ -5792,7 +5968,7 @@ build_modify_expr (lhs, modifycode, rhs) TREE_OPERAND (newrhs, 0)); } - if (TREE_CODE (newrhs) == ERROR_MARK) + if (newrhs == error_mark_node) return error_mark_node; if (TREE_CODE (newrhs) == COND_EXPR) @@ -5862,7 +6038,7 @@ build_x_modify_expr (lhs, modifycode, rhs) enum tree_code modifycode; tree rhs; { - if (current_template_parms) + if (processing_template_decl) return build_min_nt (MODOP_EXPR, lhs, build_min_nt (modifycode, NULL_TREE, NULL_TREE), rhs); @@ -5909,7 +6085,7 @@ get_delta_difference (from, to, force) binfo = get_binfo (from, to, 1); if (binfo == error_mark_node) { - error (" in pointer to member function conversion"); + error (" in pointer to member function conversiona"); return delta; } if (binfo == 0) @@ -5917,18 +6093,20 @@ get_delta_difference (from, to, force) if (!force) { error_not_base_type (from, to); - error (" in pointer to member function conversion"); + error (" in pointer to member conversion"); return delta; } binfo = get_binfo (to, from, 1); if (binfo == error_mark_node) { - error (" in pointer to member function conversion"); + if (!force) + error (" in pointer to member conversion"); return delta; } if (binfo == 0) { - cp_error ("cannot convert pointer to member of type %T to unrelated pointer to member of type %T", from, to); + if (!force) + cp_error ("cannot convert pointer to member of type %T to unrelated pointer to member of type %T", from, to); return delta; } if (TREE_VIA_VIRTUAL (binfo)) @@ -6045,12 +6223,11 @@ build_ptrmemfunc (type, pfn, force) tree delta2 = integer_zero_node; tree vfield_offset; tree npfn = NULL_TREE; - tree u; /* Handle multiple conversions of pointer to member functions. */ if (TYPE_PTRMEMFUNC_P (TREE_TYPE (pfn))) { - tree ndelta, ndelta2, nindex; + tree ndelta, ndelta2; tree e1, e2, e3, n; /* Is is already the right type? */ @@ -6084,7 +6261,7 @@ build_ptrmemfunc (type, pfn, force) /* Handle null pointer to member function conversions. */ if (integer_zerop (pfn)) { - pfn = build_c_cast (type, integer_zero_node, 0); + pfn = build_c_cast (type, integer_zero_node); return build_ptrmemfunc1 (TYPE_GET_PTRMEMFUNC_TYPE (type), integer_zero_node, integer_zero_node, pfn, NULL_TREE); @@ -6093,12 +6270,7 @@ build_ptrmemfunc (type, pfn, force) if (TREE_CODE (pfn) == TREE_LIST || (TREE_CODE (pfn) == ADDR_EXPR && TREE_CODE (TREE_OPERAND (pfn, 0)) == TREE_LIST)) - { - pfn = instantiate_type (type, pfn, 1); - if (pfn == error_mark_node) - return error_mark_node; - pfn = build_addr_func (pfn); - } + return instantiate_type (type, pfn, 1); /* Allow pointer to member conversions here. */ delta = get_delta_difference (TYPE_METHOD_BASETYPE (TREE_TYPE (TREE_TYPE (pfn))), @@ -6348,13 +6520,13 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum) return error_mark_node; } - if (ctt < 0) + if (ctt < 0 && TYPE_MAIN_VARIANT (ttl) != TYPE_MAIN_VARIANT (ttr)) cp_pedwarn ("converting `%T' to `%T' is a contravariance violation", rhstype, type); if (TYPE_MAIN_VARIANT (ttl) != void_type_node && TYPE_MAIN_VARIANT (ttr) == void_type_node - && rhs != null_pointer_node) + && ! null_ptr_cst_p (rhs)) { if (coder == RECORD_TYPE) cp_pedwarn ("implicit conversion of signature pointer to type `%T'", @@ -6405,31 +6577,6 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum) } } } - else if (TREE_CODE (ttr) == OFFSET_TYPE - && TREE_CODE (ttl) != OFFSET_TYPE) - { - /* Normally, pointers to different type codes (other - than void) are not compatible, but we perform - some type instantiation if that resolves the - ambiguity of (X Y::*) and (X *). */ - - if (current_class_ptr) - { - if (TREE_CODE (rhs) == INTEGER_CST) - { - rhs = build (PLUS_EXPR, build_pointer_type (TREE_TYPE (ttr)), - current_class_ptr, rhs); - return convert_for_assignment (type, rhs, - errtype, fndecl, parmnum); - } - } - if (TREE_CODE (ttl) == METHOD_TYPE) - error ("%s between pointer-to-method and pointer-to-member types", - errtype); - else - error ("%s between pointer and pointer-to-member types", errtype); - return error_mark_node; - } else { int add_quals = 0, const_parity = 0, volatile_parity = 0; @@ -6545,9 +6692,8 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum) else cp_pedwarn ("%s to `%T' from `%T' lacks a cast", errtype, type, rhstype); - return convert (type, rhs); } - return null_pointer_node; + return convert (type, rhs); } else if (codel == INTEGER_TYPE && (coder == POINTER_TYPE @@ -6609,6 +6755,13 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum) } else if (TYPE_HAS_CONSTRUCTOR (type) || IS_AGGR_TYPE (TREE_TYPE (rhs))) return convert (type, rhs); + /* Handle anachronistic conversions from (::*)() to cv void* or (*)(). */ + else if (TREE_CODE (type) == POINTER_TYPE + && (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE + || TYPE_MAIN_VARIANT (TREE_TYPE (type)) == void_type_node) + && TREE_TYPE (rhs) + && TYPE_PTRMEMFUNC_P (TREE_TYPE (rhs))) + return convert (type, rhs); cp_error ("%s to `%T' from `%T'", errtype, type, rhstype); return error_mark_node; @@ -6727,6 +6880,9 @@ convert_for_initialization (exp, type, rhs, flags, errtype, fndecl, parmnum) if (IS_AGGR_TYPE (type) && (TYPE_NEEDS_CONSTRUCTING (type) || TREE_HAS_CONSTRUCTOR (rhs))) { + if (flag_ansi_overloading) + return cp_convert (type, rhs, CONV_IMPLICIT|CONV_FORCE_TEMP, flags); + if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (rhstype)) { /* This is sufficient to perform initialization. No need, @@ -6886,7 +7042,6 @@ c_expand_return (retval) extern tree dtor_label, ctor_label; tree result = DECL_RESULT (current_function_decl); tree valtype = TREE_TYPE (result); - int returns_value = 1; if (TREE_THIS_VOLATILE (current_function_decl)) warning ("function declared `noreturn' has a `return' statement"); @@ -6897,7 +7052,7 @@ c_expand_return (retval) return; } - if (current_template_parms) + if (processing_template_decl) { add_tree (build_min_nt (RETURN_STMT, retval)); return; @@ -6942,20 +7097,27 @@ c_expand_return (retval) else if (DECL_CONSTRUCTOR_P (current_function_decl) && retval != current_class_ptr) { - error ("return from a constructor: use `this = ...' instead"); + if (flag_this_is_variable) + error ("return from a constructor: use `this = ...' instead"); + else + error ("return from a constructor"); retval = current_class_ptr; } + /* Effective C++ rule 15. See also start_function. */ + if (warn_ecpp + && DECL_NAME (current_function_decl) == ansi_opname[(int) MODIFY_EXPR] + && retval != current_class_ref) + cp_warning ("`operator=' should return a reference to `*this'"); + if (valtype == NULL_TREE || TREE_CODE (valtype) == VOID_TYPE) { current_function_returns_null = 1; - /* We do this here so we'll avoid a warning about how the function - "may or may not return a value" in finish_function. */ - returns_value = 0; - - if (retval) + if ((pedantic && ! DECL_ARTIFICIAL (current_function_decl)) + || TREE_CODE (TREE_TYPE (retval)) != VOID_TYPE) pedwarn ("`return' with a value, in function returning void"); expand_return (retval); + return; } /* Add some useful error checking for C++. */ else if (TREE_CODE (valtype) == REFERENCE_TYPE) @@ -6972,9 +7134,9 @@ c_expand_return (retval) /* convert to reference now, so we can give error if we return an reference to a non-lvalue. */ - retval = convert_for_initialization (tmp_result, valtype, retval, - LOOKUP_NORMAL, "return", - NULL_TREE, 0); + retval = convert_for_initialization + (tmp_result, valtype, retval, LOOKUP_NORMAL|LOOKUP_ONLYCONVERTING, + "return", NULL_TREE, 0); /* Sort through common things to see what it is we are returning. */ @@ -6985,6 +7147,8 @@ c_expand_return (retval) if (TREE_CODE (whats_returned) == ADDR_EXPR) whats_returned = TREE_OPERAND (whats_returned, 0); } + if (TREE_CODE (whats_returned) == CONVERT_EXPR) + whats_returned = TREE_OPERAND (whats_returned, 0); if (TREE_CODE (whats_returned) == ADDR_EXPR) { whats_returned = TREE_OPERAND (whats_returned, 0); @@ -7036,143 +7200,56 @@ c_expand_return (retval) (3) If an X(X&) constructor is defined, the return value must be returned via that. */ - /* If we're returning in a register, we can't initialize the - return value from a TARGET_EXPR. */ - if (TREE_CODE (retval) == TARGET_EXPR - && TYPE_MAIN_VARIANT (TREE_TYPE (retval)) == TYPE_MAIN_VARIANT (valtype) - && ! current_function_returns_struct) - retval = expand_target_expr (retval); - if (retval == result - /* Watch out for constructors, which "return" aggregates - via initialization, but which otherwise "return" a pointer. */ || DECL_CONSTRUCTOR_P (current_function_decl)) + /* It's already done for us. */; + else if (TREE_TYPE (retval) == void_type_node) { - /* This is just an error--it's already been reported. */ - if (TYPE_SIZE (valtype) == NULL_TREE) - return; - - if (TYPE_MODE (valtype) != BLKmode - && any_pending_cleanups (1)) - retval = get_temp_regvar (valtype, retval); - } - else if (IS_AGGR_TYPE (valtype) && current_function_returns_struct) - { - expand_aggr_init (result, retval, 0, LOOKUP_ONLYCONVERTING); - expand_cleanups_to (NULL_TREE); - DECL_INITIAL (result) = NULL_TREE; + pedwarn ("return of void value in function returning non-void"); + expand_expr_stmt (retval); retval = 0; } else { - if (TYPE_MODE (valtype) == VOIDmode) - { - if (TYPE_MODE (TREE_TYPE (result)) != VOIDmode - && warn_return_type) - warning ("return of void value in function returning non-void"); - expand_expr_stmt (retval); - retval = 0; - result = 0; - } - else if (TYPE_MODE (valtype) != BLKmode - && any_pending_cleanups (1)) - { - retval = get_temp_regvar (valtype, retval); - expand_cleanups_to (NULL_TREE); - result = 0; - } - else + /* We already did this above for refs, don't do it again. */ + if (TREE_CODE (valtype) != REFERENCE_TYPE) + retval = convert_for_initialization + (NULL_TREE, valtype, retval, LOOKUP_NORMAL|LOOKUP_ONLYCONVERTING, + "return", NULL_TREE, 0); + + /* We can't initialize a register from a NEW_EXPR. */ + if (! current_function_returns_struct + && TREE_CODE (retval) == TARGET_EXPR + && TREE_CODE (TREE_OPERAND (retval, 1)) == NEW_EXPR) + retval = build (COMPOUND_EXPR, TREE_TYPE (retval), retval, + TREE_OPERAND (retval, 0)); + + if (retval == error_mark_node) { - /* We already did this above, don't do it again. */ - if (TREE_CODE (valtype) != REFERENCE_TYPE) - retval = convert_for_initialization (result, valtype, retval, - LOOKUP_NORMAL, - "return", NULL_TREE, 0); - DECL_INITIAL (result) = NULL_TREE; + /* Avoid warning about control reaching end of function. */ + expand_null_return (); + return; } - if (retval == error_mark_node) - return; } - emit_queue (); - if (retval != NULL_TREE && TREE_CODE_CLASS (TREE_CODE (retval)) == 'd' && cond_stack == 0 && loop_stack == 0 && case_stack == 0) current_function_return_value = retval; - if (result) + if (ctor_label && TREE_CODE (ctor_label) != ERROR_MARK) { - /* Everything's great--RETVAL is in RESULT. */ - if (original_result_rtx) - { - store_expr (result, original_result_rtx, 0); - expand_cleanups_to (NULL_TREE); - use_variable (DECL_RTL (result)); - if (ctor_label && TREE_CODE (ctor_label) != ERROR_MARK) - expand_goto (ctor_label); - else - expand_null_return (); - } - else if (retval && retval != result) - { - /* Clear this out so the later call to decl_function_context - won't end up bombing on us. */ - if (DECL_CONTEXT (result) == error_mark_node) - DECL_CONTEXT (result) = NULL_TREE; - /* Here is where we finally get RETVAL into RESULT. - `expand_return' does the magic of protecting - RESULT from cleanups. */ - retval = fold (build1 (CLEANUP_POINT_EXPR, TREE_TYPE (result), - retval)); - /* This part _must_ come second, because expand_return looks for - the INIT_EXPR as the toplevel node only. :-( */ - retval = build (INIT_EXPR, TREE_TYPE (result), result, retval); - TREE_SIDE_EFFECTS (retval) = 1; - expand_return (retval); - } - else - expand_return (result); + /* Here RETVAL is CURRENT_CLASS_PTR, so there's nothing to do. */ + expand_goto (ctor_label); } - else + + if (retval && retval != result) { - /* We may still need to put RETVAL into RESULT. */ - result = DECL_RESULT (current_function_decl); - if (original_result_rtx) - { - /* Here we have a named return value that went - into memory. We can compute RETVAL into that. */ - if (retval) - expand_assignment (result, retval, 0, 0); - else - store_expr (result, original_result_rtx, 0); - result = make_tree (TREE_TYPE (result), original_result_rtx); - } - else if (ctor_label && TREE_CODE (ctor_label) != ERROR_MARK) - { - /* Here RETVAL is CURRENT_CLASS_PTR, so there's nothing to do. */ - expand_goto (ctor_label); - } - else if (retval) - { - /* Here is where we finally get RETVAL into RESULT. - `expand_return' does the magic of protecting - RESULT from cleanups. */ - result = build (INIT_EXPR, TREE_TYPE (result), result, retval); - TREE_SIDE_EFFECTS (result) = 1; - expand_return (result); - } - else if (TYPE_MODE (TREE_TYPE (result)) != VOIDmode) - expand_return (result); + result = build (INIT_EXPR, TREE_TYPE (result), result, retval); + TREE_SIDE_EFFECTS (result) = 1; } - - current_function_returns_value = returns_value; - - /* One way to clear out cleanups that EXPR might - generate. Note that this code will really be - dead code, but that is ok--cleanups that were - needed were handled by the magic of `return'. */ - expand_cleanups_to (NULL_TREE); + expand_return (result); + current_function_returns_value = 1; } /* Start a C switch statement, testing expression EXP. @@ -7232,7 +7309,7 @@ c_expand_start_case (exp) /* CONSTP remembers whether or not all the intervening pointers in the `to' type have been const. */ -int +static int comp_ptr_ttypes_real (to, from, constp) tree to, from; int constp; @@ -7242,6 +7319,11 @@ comp_ptr_ttypes_real (to, from, constp) if (TREE_CODE (to) != TREE_CODE (from)) return 0; + if (TREE_CODE (from) == OFFSET_TYPE + && comptypes (TYPE_OFFSET_BASETYPE (from), + TYPE_OFFSET_BASETYPE (to), 1)) + continue; + /* Const and volatile mean something different for function types, so the usual checks are not appropriate. */ if (TREE_CODE (to) != FUNCTION_TYPE && TREE_CODE (to) != METHOD_TYPE) @@ -7272,3 +7354,85 @@ comp_ptr_ttypes (to, from) { return comp_ptr_ttypes_real (to, from, 1); } + +/* Returns 1 if to and from are (possibly multi-level) pointers to the same + type or inheritance-related types, regardless of cv-quals. */ + +int +ptr_reasonably_similar (to, from) + tree to, from; +{ + for (; ; to = TREE_TYPE (to), from = TREE_TYPE (from)) + { + if (TREE_CODE (to) != TREE_CODE (from)) + return 0; + + if (TREE_CODE (from) == OFFSET_TYPE + && comptypes (TYPE_OFFSET_BASETYPE (to), + TYPE_OFFSET_BASETYPE (from), -1)) + continue; + + if (TREE_CODE (to) != POINTER_TYPE) + return comptypes + (TYPE_MAIN_VARIANT (to), TYPE_MAIN_VARIANT (from), -1); + } +} + +/* Like comp_ptr_ttypes, for const_cast. */ + +static int +comp_ptr_ttypes_const (to, from) + tree to, from; +{ + for (; ; to = TREE_TYPE (to), from = TREE_TYPE (from)) + { + if (TREE_CODE (to) != TREE_CODE (from)) + return 0; + + if (TREE_CODE (from) == OFFSET_TYPE + && comptypes (TYPE_OFFSET_BASETYPE (from), + TYPE_OFFSET_BASETYPE (to), 1)) + continue; + + if (TREE_CODE (to) != POINTER_TYPE) + return comptypes (TYPE_MAIN_VARIANT (to), TYPE_MAIN_VARIANT (from), 1); + } +} + +/* Like comp_ptr_ttypes, for reinterpret_cast. */ + +static int +comp_ptr_ttypes_reinterpret (to, from) + tree to, from; +{ + int constp = 1; + + for (; ; to = TREE_TYPE (to), from = TREE_TYPE (from)) + { + if (TREE_CODE (from) == OFFSET_TYPE) + from = TREE_TYPE (from); + if (TREE_CODE (to) == OFFSET_TYPE) + to = TREE_TYPE (to); + + if (TREE_CODE (to) != TREE_CODE (from)) + return 1; + + /* Const and volatile mean something different for function types, + so the usual checks are not appropriate. */ + if (TREE_CODE (to) != FUNCTION_TYPE && TREE_CODE (to) != METHOD_TYPE) + { + if (TYPE_READONLY (from) > TYPE_READONLY (to) + || TYPE_VOLATILE (from) > TYPE_VOLATILE (to)) + return 0; + + if (! constp + && (TYPE_READONLY (to) > TYPE_READONLY (from) + || TYPE_VOLATILE (to) > TYPE_READONLY (from))) + return 0; + constp &= TYPE_READONLY (to); + } + + if (TREE_CODE (to) != POINTER_TYPE) + return 1; + } +}