--- gcc/cp/cvt.c 2018/04/24 18:20:21 1.1 +++ gcc/cp/cvt.c 2018/04/24 18:27:04 1.1.1.2 @@ -1,5 +1,5 @@ /* Language-level data type conversion for GNU C++. - Copyright (C) 1987, 1988, 1992, 1993 Free Software Foundation, Inc. + Copyright (C) 1987, 88, 92, 93, 94, 1995 Free Software Foundation, Inc. Hacked by Michael Tiemann (tiemann@cygnus.com) This file is part of GNU CC. @@ -16,7 +16,8 @@ GNU General Public License for more deta You should have received a copy of the GNU General Public License along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ /* This file contains the functions for converting C expressions @@ -81,23 +82,29 @@ static tree convert_fn_ptr (type, expr) tree type, expr; { - tree binfo = get_binfo (TYPE_METHOD_BASETYPE (TREE_TYPE (TREE_TYPE (expr))), - TYPE_METHOD_BASETYPE (TREE_TYPE (type)), - 1); - if (binfo == error_mark_node) + if (flag_vtable_thunks) { - error (" in pointer to member conversion"); - return error_mark_node; - } - if (binfo == NULL_TREE) - { - /* ARM 4.8 restriction. */ - error ("invalid pointer to member conversion"); - return error_mark_node; + tree intype = TREE_TYPE (expr); + tree binfo = get_binfo (TYPE_METHOD_BASETYPE (TREE_TYPE (intype)), + TYPE_METHOD_BASETYPE (TREE_TYPE (type)), 1); + if (binfo == error_mark_node) + { + error (" in pointer to member conversion"); + return error_mark_node; + } + if (binfo == NULL_TREE) + { + /* ARM 4.8 restriction. */ + error ("invalid pointer to member conversion"); + return error_mark_node; + } + + if (BINFO_OFFSET_ZEROP (binfo)) + return build1 (NOP_EXPR, type, expr); + return build1 (NOP_EXPR, type, build_thunk (BINFO_OFFSET (binfo), expr)); } - if (BINFO_OFFSET_ZEROP (binfo)) - return build1 (NOP_EXPR, type, expr); - return build1 (NOP_EXPR, type, build_thunk (BINFO_OFFSET (binfo), expr)); + else + return build_ptrmemfunc (type, expr, 1); } /* if converting pointer to pointer @@ -111,9 +118,16 @@ cp_convert_to_pointer (type, expr) tree type, expr; { register tree intype = TREE_TYPE (expr); - register enum tree_code form = TREE_CODE (intype); - - if (form == POINTER_TYPE) + register enum tree_code form; + + if (TYPE_PTRMEMFUNC_P (type)) + type = TYPE_PTRMEMFUNC_FN_TYPE (type); + if (TYPE_PTRMEMFUNC_P (intype)) + intype = TYPE_PTRMEMFUNC_FN_TYPE (intype); + + form = TREE_CODE (intype); + + if (form == POINTER_TYPE || form == REFERENCE_TYPE) { intype = TYPE_MAIN_VARIANT (intype); @@ -149,12 +163,32 @@ cp_convert_to_pointer (type, expr) } } } - if (TYPE_MAIN_VARIANT (type) != intype - && TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE + if (TREE_CODE (TREE_TYPE (intype)) == METHOD_TYPE && TREE_CODE (type) == POINTER_TYPE - && TREE_CODE (TREE_TYPE (intype)) == METHOD_TYPE) + && TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE) return convert_fn_ptr (type, expr); + if (TREE_CODE (TREE_TYPE (type)) == OFFSET_TYPE + && TREE_CODE (TREE_TYPE (intype)) == OFFSET_TYPE) + { + tree b1 = TYPE_OFFSET_BASETYPE (TREE_TYPE (type)); + tree b2 = TYPE_OFFSET_BASETYPE (TREE_TYPE (intype)); + tree binfo = get_binfo (b1, b2, 1); + if (binfo == NULL_TREE) + binfo = get_binfo (b2, b1, 1); + if (binfo == error_mark_node) + return error_mark_node; + } + + if (TREE_CODE (TREE_TYPE (intype)) == METHOD_TYPE + || (TREE_CODE (type) == POINTER_TYPE + && TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE)) + { + cp_error ("cannot convert `%E' from type `%T' to type `%T'", + expr, intype, type); + return error_mark_node; + } + return build1 (NOP_EXPR, type, expr); } @@ -309,6 +343,10 @@ build_up_reference (type, arg, flags, ch targ = arg; if (TREE_CODE (targ) == SAVE_EXPR) targ = TREE_OPERAND (targ, 0); + while (TREE_CODE (targ) == NOP_EXPR + && (TYPE_MAIN_VARIANT (argtype) + == TYPE_MAIN_VARIANT (TREE_TYPE (TREE_OPERAND (targ, 0))))) + targ = TREE_OPERAND (targ, 0); switch (TREE_CODE (targ)) { @@ -514,6 +552,18 @@ build_up_reference (type, arg, flags, ch build_up_reference (type, TREE_OPERAND (targ, 2), LOOKUP_PROTECT, checkconst)); + /* Undo the folding... */ + case MIN_EXPR: + case MAX_EXPR: + return build (COND_EXPR, type, + build (TREE_CODE (targ) == MIN_EXPR ? LT_EXPR : GT_EXPR, + boolean_type_node, TREE_OPERAND (targ, 0), + TREE_OPERAND (targ, 1)), + build_up_reference (type, TREE_OPERAND (targ, 0), + LOOKUP_PROTECT, checkconst), + build_up_reference (type, TREE_OPERAND (targ, 1), + LOOKUP_PROTECT, checkconst)); + case WITH_CLEANUP_EXPR: return build (WITH_CLEANUP_EXPR, type, build_up_reference (type, TREE_OPERAND (targ, 0), @@ -553,12 +603,12 @@ build_up_reference (type, arg, flags, ch else { temp = get_temp_name (argtype, 0); - if (global_bindings_p ()) + if (toplevel_bindings_p ()) { /* Give this new temp some rtl and initialize it. */ DECL_INITIAL (temp) = targ; TREE_STATIC (temp) = 1; - finish_decl (temp, targ, NULL_TREE, 0); + cp_finish_decl (temp, targ, NULL_TREE, 0, LOOKUP_ONLYCONVERTING); /* Do this after declaring it static. */ rval = build_unary_op (ADDR_EXPR, temp, 0); TREE_TYPE (rval) = type; @@ -593,6 +643,9 @@ build_up_reference (type, arg, flags, ch rval = convert_to_pointer_force (build_pointer_type (target_type), rval); TREE_TYPE (rval) = type; + if (TREE_CODE (rval) == PLUS_EXPR || TREE_CODE (rval) == MINUS_EXPR) + TREE_TYPE (TREE_OPERAND (rval, 0)) + = TREE_TYPE (TREE_OPERAND (rval, 1)) = type; } TREE_CONSTANT (rval) = literal_flag; return rval; @@ -605,8 +658,6 @@ build_up_reference (type, arg, flags, ch initialized. It can be error_mark_node if we don't know the _DECL but we know it's an initialization. */ -tree cp_convert PROTO((tree, tree, int, int)); - tree convert_to_reference (reftype, expr, convtype, flags, decl) tree reftype, expr; @@ -615,31 +666,49 @@ convert_to_reference (reftype, expr, con { register tree type = TYPE_MAIN_VARIANT (TREE_TYPE (reftype)); register tree intype = TREE_TYPE (expr); - register enum tree_code form = TREE_CODE (intype); tree rval = NULL_TREE; + tree rval_as_conversion = NULL_TREE; + int i; + + if (TREE_CODE (intype) == REFERENCE_TYPE) + my_friendly_abort (364); - if (form == REFERENCE_TYPE) - intype = TREE_TYPE (intype); intype = TYPE_MAIN_VARIANT (intype); - if (((convtype & CONV_STATIC) && comptypes (type, intype, -1)) - || ((convtype & CONV_IMPLICIT) && comptypes (type, intype, 0))) + i = comp_target_types (type, intype, 0); + + if (i <= 0 && (convtype & CONV_IMPLICIT) && IS_AGGR_TYPE (intype) + && ! (flags & LOOKUP_NO_CONVERSION)) + { + /* Look for a user-defined conversion to lvalue that we can use. */ + + rval_as_conversion = build_type_conversion (CONVERT_EXPR, type, expr, 1); + + if (rval_as_conversion && rval_as_conversion != error_mark_node + && real_lvalue_p (rval_as_conversion)) + { + expr = rval_as_conversion; + rval_as_conversion = NULL_TREE; + intype = type; + i = 1; + } + } + + if (((convtype & CONV_STATIC) && i == -1) + || ((convtype & CONV_IMPLICIT) && i == 1)) { if (flags & LOOKUP_COMPLAIN) { tree ttl = TREE_TYPE (reftype); tree ttr; - if (form == REFERENCE_TYPE) - ttr = TREE_TYPE (TREE_TYPE (expr)); - else - { - int r = TREE_READONLY (expr); - int v = TREE_THIS_VOLATILE (expr); - ttr = cp_build_type_variant (TREE_TYPE (expr), r, v); - } + { + int r = TREE_READONLY (expr); + int v = TREE_THIS_VOLATILE (expr); + ttr = cp_build_type_variant (TREE_TYPE (expr), r, v); + } - if (! lvalue_p (expr) && + if (! real_lvalue_p (expr) && (decl == NULL_TREE || ! TYPE_READONLY (ttl))) { if (decl) @@ -661,32 +730,9 @@ convert_to_reference (reftype, expr, con } } - if (form == REFERENCE_TYPE) - { - tree type = TREE_TYPE (expr); - tree tmp = copy_node (expr); - TREE_TYPE (tmp) = build_pointer_type (TREE_TYPE (TREE_TYPE (expr))); - rval = cp_convert (build_pointer_type (TREE_TYPE (reftype)), tmp, - convtype, flags); - TREE_TYPE (tmp) = type; - TREE_TYPE (rval) = reftype; - return rval; - } - return build_up_reference (reftype, expr, flags, ! (convtype & CONV_CONST)); } - - if ((convtype & CONV_IMPLICIT) - && IS_AGGR_TYPE (intype) - && ! (flags & LOOKUP_NO_CONVERSION) - && (rval = build_type_conversion (CONVERT_EXPR, reftype, expr, 1))) - { - if (rval == error_mark_node) - cp_error ("conversion from `%T' to `%T' is ambiguous", - intype, reftype); - return rval; - } else if ((convtype & CONV_REINTERPRET) && lvalue_p (expr)) { /* When casting an lvalue to a reference type, just convert into @@ -694,31 +740,33 @@ convert_to_reference (reftype, expr, con by San Diego WP section 5.2.9 paragraph 12, though perhaps it should be done directly (jason). (int &)ri ---> *(int*)&ri */ - /* B* bp; A& ar = (A&)bp; is legal, but it's probably not what they + /* B* bp; A& ar = (A&)bp; is valid, but it's probably not what they meant. */ - if (form == POINTER_TYPE + if (TREE_CODE (intype) == POINTER_TYPE && (comptypes (TREE_TYPE (intype), type, -1))) cp_warning ("casting `%T' to `%T' does not dereference pointer", intype, reftype); rval = build_unary_op (ADDR_EXPR, expr, 0); if (rval != error_mark_node) - rval = convert_force (build_pointer_type (TREE_TYPE (reftype)), rval); + rval = convert_force (build_pointer_type (TREE_TYPE (reftype)), rval, 0); if (rval != error_mark_node) rval = build1 (NOP_EXPR, reftype, rval); } else if (decl) { - tree rval_as_conversion = NULL_TREE; tree rval_as_ctor = NULL_TREE; - if (IS_AGGR_TYPE (intype) - && (rval = build_type_conversion (CONVERT_EXPR, type, expr, 1))) + if (rval_as_conversion) { - if (rval == error_mark_node) - return rval; - - rval_as_conversion = build_up_reference (reftype, rval, flags, 1); + if (rval_as_conversion == error_mark_node) + { + cp_error ("conversion from `%T' to `%T' is ambiguous", + intype, reftype); + return error_mark_node; + } + rval_as_conversion = build_up_reference (reftype, rval_as_conversion, + flags, 1); } /* Definitely need to go through a constructor here. */ @@ -727,18 +775,20 @@ convert_to_reference (reftype, expr, con && (rval = build_method_call (NULL_TREE, constructor_name_full (type), build_tree_list (NULL_TREE, expr), TYPE_BINFO (type), - LOOKUP_NO_CONVERSION|LOOKUP_SPECULATIVELY))) + LOOKUP_NO_CONVERSION|LOOKUP_SPECULATIVELY + | LOOKUP_ONLYCONVERTING))) { tree init; - if (global_bindings_p ()) + if (toplevel_bindings_p ()) { extern tree static_aggregates; - tree t = get_temp_name (type, global_bindings_p ()); + tree t = get_temp_name (type, toplevel_bindings_p ()); init = build_method_call (t, constructor_name_full (type), build_tree_list (NULL_TREE, expr), TYPE_BINFO (type), - LOOKUP_NORMAL|LOOKUP_NO_CONVERSION); + LOOKUP_NORMAL|LOOKUP_NO_CONVERSION + | LOOKUP_ONLYCONVERTING); if (init == error_mark_node) return error_mark_node; @@ -752,7 +802,8 @@ convert_to_reference (reftype, expr, con init = build_method_call (NULL_TREE, constructor_name_full (type), build_tree_list (NULL_TREE, expr), TYPE_BINFO (type), - LOOKUP_NORMAL|LOOKUP_NO_CONVERSION); + LOOKUP_NORMAL|LOOKUP_NO_CONVERSION + |LOOKUP_ONLYCONVERTING); if (init == error_mark_node) return error_mark_node; @@ -793,14 +844,14 @@ convert_to_reference (reftype, expr, con return rval; } - my_friendly_assert (form != OFFSET_TYPE, 189); + my_friendly_assert (TREE_CODE (intype) != OFFSET_TYPE, 189); + + if (flags & LOOKUP_COMPLAIN) + cp_error ("cannot convert type `%T' to type `%T'", intype, reftype); if (flags & LOOKUP_SPECULATIVELY) return NULL_TREE; - else if (flags & LOOKUP_COMPLAIN) - cp_error ("cannot convert type `%T' to type `%T'", intype, reftype); - return error_mark_node; } @@ -814,30 +865,8 @@ convert_from_reference (val) if (TREE_CODE (type) == OFFSET_TYPE) type = TREE_TYPE (type); - if (TREE_CODE (type) == REFERENCE_TYPE) - { - tree target_type = TREE_TYPE (type); - tree nval; - - /* This can happen if we cast to a reference type. */ - if (TREE_CODE (val) == ADDR_EXPR) - { - nval = build1 (NOP_EXPR, build_pointer_type (target_type), val); - nval = build_indirect_ref (nval, NULL_PTR); - /* The below was missing, are other important flags missing too? */ - TREE_SIDE_EFFECTS (nval) = TREE_SIDE_EFFECTS (val); - return nval; - } - - nval = build1 (INDIRECT_REF, target_type, val); - - TREE_THIS_VOLATILE (nval) = TYPE_VOLATILE (target_type); - TREE_SIDE_EFFECTS (nval) = TYPE_VOLATILE (target_type); - TREE_READONLY (nval) = TYPE_READONLY (target_type); - /* The below was missing, are other important flags missing too? */ - TREE_SIDE_EFFECTS (nval) |= TREE_SIDE_EFFECTS (val); - return nval; - } + if (TREE_CODE (type) == REFERENCE_TYPE) + return build_indirect_ref (val, NULL_PTR); return val; } @@ -884,8 +913,9 @@ convert_to_aggr (type, expr, msgp, prote /* The type of the first argument will be filled in inside the loop. */ parmlist = tree_cons (NULL_TREE, integer_zero_node, parmlist); - parmtypes = tree_cons (NULL_TREE, TYPE_POINTER_TO (basetype), parmtypes); + parmtypes = tree_cons (NULL_TREE, build_pointer_type (basetype), parmtypes); +#if 0 method_name = build_decl_overload (name, parmtypes, 1); /* constructors are up front. */ @@ -919,6 +949,7 @@ convert_to_aggr (type, expr, msgp, prote } fndecl = DECL_CHAIN (fndecl); } +#endif /* No exact conversion was found. See if an approximate one will do. */ @@ -1047,10 +1078,7 @@ convert_to_aggr (type, expr, msgp, prote return NULL_TREE; fntype = TREE_TYPE (function); - if (DECL_INLINE (function) && TREE_CODE (function) == FUNCTION_DECL) - function = build1 (ADDR_EXPR, build_pointer_type (fntype), function); - else - function = default_conversion (function); + function = default_conversion (function); result = build_nt (CALL_EXPR, function, convert_arguments (NULL_TREE, TYPE_ARG_TYPES (fntype), @@ -1058,7 +1086,6 @@ convert_to_aggr (type, expr, msgp, prote NULL_TREE); TREE_TYPE (result) = TREE_TYPE (fntype); TREE_SIDE_EFFECTS (result) = 1; - TREE_RAISES (result) = !! TYPE_RAISES_EXCEPTIONS (fntype); return result; } @@ -1146,34 +1173,12 @@ convert_pointer_to (binfo, expr) type = binfo; return convert_pointer_to_real (type, expr); } + +/* Conversion... -/* Same as above, but don't abort if we get an "ambiguous" baseclass. - There's only one virtual baseclass we are looking for, and once - we find one such virtual baseclass, we have found them all. */ + FLAGS indicates how we should behave. */ tree -convert_pointer_to_vbase (binfo, expr) - tree binfo; - tree expr; -{ - tree intype = TREE_TYPE (TREE_TYPE (expr)); - tree binfos = TYPE_BINFO_BASETYPES (intype); - int i; - - for (i = TREE_VEC_LENGTH (binfos)-1; i >= 0; i--) - { - tree basetype = BINFO_TYPE (TREE_VEC_ELT (binfos, i)); - if (BINFO_TYPE (binfo) == basetype) - return convert_pointer_to (binfo, expr); - if (binfo_member (BINFO_TYPE (binfo), CLASSTYPE_VBASECLASSES (basetype))) - return convert_pointer_to_vbase (binfo, convert_pointer_to (basetype, expr)); - } - my_friendly_abort (6); - /* NOTREACHED */ - return NULL_TREE; -} - -tree cp_convert (type, expr, convtype, flags) tree type, expr; int convtype, flags; @@ -1181,14 +1186,14 @@ cp_convert (type, expr, convtype, flags) register tree e = expr; register enum tree_code code = TREE_CODE (type); - if (type == TREE_TYPE (e) - || TREE_CODE (e) == ERROR_MARK) - return e; - if (TREE_CODE (TREE_TYPE (e)) == ERROR_MARK) + if (TREE_CODE (e) == ERROR_MARK + || TREE_CODE (TREE_TYPE (e)) == ERROR_MARK) return error_mark_node; - /* Trivial conversion: cv-qualifiers do not matter on rvalues. */ - if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (e))) + if (IS_AGGR_TYPE (type) && (convtype & CONV_FORCE_TEMP)) + /* We need a new temporary; don't take this shortcut. */; + else if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (e))) + /* Trivial conversion: cv-qualifiers do not matter on rvalues. */ return fold (build1 (NOP_EXPR, type, e)); if (code == VOID_TYPE && (convtype & CONV_STATIC)) @@ -1208,10 +1213,12 @@ cp_convert (type, expr, convtype, flags) code = TREE_CODE (type); } +#if 0 if (code == REFERENCE_TYPE) return fold (convert_to_reference (type, e, convtype, flags, NULL_TREE)); else if (TREE_CODE (TREE_TYPE (e)) == REFERENCE_TYPE) e = convert_from_reference (e); +#endif if (TREE_CODE (e) == OFFSET_REF) e = resolve_offset_ref (e); @@ -1226,7 +1233,8 @@ cp_convert (type, expr, convtype, flags) /* enum = enum, enum = int, enum = float are all errors. */ if (flag_int_enum_equivalence == 0 && TREE_CODE (type) == ENUMERAL_TYPE - && ARITHMETIC_TYPE_P (intype)) + && ARITHMETIC_TYPE_P (intype) + && ! (convtype & CONV_STATIC)) { cp_pedwarn ("conversion from `%#T' to `%#T'", intype, type); @@ -1239,30 +1247,18 @@ cp_convert (type, expr, convtype, flags) rval = build_type_conversion (CONVERT_EXPR, type, e, 1); if (rval) return rval; - cp_error ("`%#T' used where a `%T' was expected", intype, type); + if (flags & LOOKUP_COMPLAIN) + cp_error ("`%#T' used where a `%T' was expected", intype, type); + if (flags & LOOKUP_SPECULATIVELY) + return NULL_TREE; return error_mark_node; } if (code == BOOLEAN_TYPE) - { - tree newe = truthvalue_conversion (e); - /* Avoid stupid (infinite) recursion from backend. */ - if (TREE_CODE (newe) != NOP_EXPR || e != TREE_OPERAND (newe, 0)) - e = newe; - if (TREE_TYPE (e) == bool_type_node) - return e; - else if (TREE_CODE (e) == INTEGER_CST) - { - if (e == integer_zero_node) - e = false_node; - else - e = true_node; - } - else - return build1 (NOP_EXPR, bool_type_node, e); - } + return truthvalue_conversion (e); return fold (convert_to_integer (type, e)); } - if (code == POINTER_TYPE) + if (code == POINTER_TYPE || code == REFERENCE_TYPE + || TYPE_PTRMEMFUNC_P (type)) return fold (cp_convert_to_pointer (type, e)); if (code == REAL_TYPE) { @@ -1273,8 +1269,9 @@ cp_convert (type, expr, convtype, flags) if (rval) return rval; else - cp_error ("`%#T' used where a floating point value was expected", - TREE_TYPE (e)); + if (flags & LOOKUP_COMPLAIN) + cp_error ("`%#T' used where a floating point value was expected", + TREE_TYPE (e)); } return fold (convert_to_real (type, e)); } @@ -1306,7 +1303,7 @@ cp_convert (type, expr, convtype, flags) sig_ptr = get_temp_name (type, 1); DECL_INITIAL (sig_ptr) = constructor; CLEAR_SIGNATURE (sig_ty); - finish_decl (sig_ptr, constructor, 0, 0); + cp_finish_decl (sig_ptr, constructor, NULL_TREE, 0, 0); SET_SIGNATURE (sig_ty); TREE_READONLY (sig_ptr) = 1; @@ -1326,7 +1323,8 @@ cp_convert (type, expr, convtype, flags) if (conversion == error_mark_node) { - error ("ambiguous pointer conversion"); + if (flags & LOOKUP_COMPLAIN) + error ("ambiguous pointer conversion"); return conversion; } @@ -1334,62 +1332,32 @@ cp_convert (type, expr, convtype, flags) ctor = build_method_call (NULL_TREE, constructor_name_full (type), build_tree_list (NULL_TREE, e), TYPE_BINFO (type), - LOOKUP_NORMAL | LOOKUP_SPECULATIVELY + (flags & LOOKUP_NORMAL) | LOOKUP_SPECULATIVELY + | (convtype&CONV_NONCONVERTING ? 0 : LOOKUP_ONLYCONVERTING) | (conversion ? LOOKUP_NO_CONVERSION : 0)); if (ctor == error_mark_node) { - cp_error ("in conversion to type `%T'", type); + if (flags & LOOKUP_COMPLAIN) + cp_error ("in conversion to type `%T'", type); + if (flags & LOOKUP_SPECULATIVELY) + return NULL_TREE; return error_mark_node; } if (conversion && ctor) { - error ("both constructor and type conversion operator apply"); + if (flags & LOOKUP_COMPLAIN) + error ("both constructor and type conversion operator apply"); + if (flags & LOOKUP_SPECULATIVELY) + return NULL_TREE; return error_mark_node; } else if (conversion) return conversion; else if (ctor) { - if (current_function_decl) - /* We can't pass 1 to the with_cleanup_p arg here, because that - screws up passing classes by value. */ - ctor = build_cplus_new (type, ctor, 0); - else - { - register tree parm = TREE_OPERAND (ctor, 1); - - /* Initializers for static variables and parameters - have to handle doing the initialization and - cleanup themselves. */ - my_friendly_assert (TREE_CODE (ctor) == CALL_EXPR, 322); -#if 0 - /* The following assertion fails in cases where we - are initializing a static member variable of a - particular instance of a template class with a - call to a constructor of the given instance, as - in: - - TMPL object = TMPL(); - - Curiously, the assertion does not fail if we do - the same thing for a static member of a - non-template class, as in: - - T object = T(); - - I can't see why we should care here whether or not - the initializer expression involves a call to - `new', so for the time being, it seems best to - just avoid doing this assertion. */ - my_friendly_assert (TREE_CALLS_NEW (TREE_VALUE (parm)), - 323); -#endif - TREE_VALUE (parm) = NULL_TREE; - ctor = build_indirect_ref (ctor, NULL_PTR); - TREE_HAS_CONSTRUCTOR (ctor) = 1; - } + ctor = build_cplus_new (type, ctor, 0); return ctor; } } @@ -1402,8 +1370,11 @@ cp_convert (type, expr, convtype, flags) && index_type_equal (TYPE_DOMAIN (TREE_TYPE (e)), TYPE_DOMAIN (type))) return e; - cp_error ("conversion from `%T' to non-scalar type `%T' requested", - TREE_TYPE (expr), type); + if (flags & LOOKUP_COMPLAIN) + cp_error ("conversion from `%T' to non-scalar type `%T' requested", + TREE_TYPE (expr), type); + if (flags & LOOKUP_SPECULATIVELY) + return NULL_TREE; return error_mark_node; } @@ -1417,16 +1388,17 @@ tree convert (type, expr) tree type, expr; { - return cp_convert (type, expr, CONV_OLD_CONVERT, 0); + return cp_convert (type, expr, CONV_OLD_CONVERT, LOOKUP_NORMAL); } /* Like convert, except permit conversions to take place which are not normally allowed due to access restrictions (such as conversion from sub-type to private super-type). */ tree -convert_force (type, expr) +convert_force (type, expr, convtype) tree type; tree expr; + int convtype; { register tree e = expr; register enum tree_code code = TREE_CODE (type); @@ -1451,13 +1423,8 @@ convert_force (type, expr) /* compatible pointer to member functions. */ return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), e, 1); } - { - int old_equiv = flag_int_enum_equivalence; - flag_int_enum_equivalence = 1; - e = convert (type, e); - flag_int_enum_equivalence = old_equiv; - } - return e; + + return cp_convert (type, e, CONV_C_CAST|convtype, LOOKUP_NORMAL); } /* Subroutine of build_type_conversion. */ @@ -1472,9 +1439,9 @@ build_type_conversion_1 (xtype, basetype int flags; if (for_sure == 0) - flags = LOOKUP_PROTECT; + flags = LOOKUP_PROTECT|LOOKUP_ONLYCONVERTING; else - flags = LOOKUP_NORMAL; + flags = LOOKUP_NORMAL|LOOKUP_ONLYCONVERTING; rval = build_method_call (expr, typename, NULL_TREE, NULL_TREE, flags); if (rval == error_mark_node) @@ -1483,9 +1450,9 @@ build_type_conversion_1 (xtype, basetype return NULL_TREE; return error_mark_node; } - if (TREE_CODE (TREE_TYPE (rval)) == REFERENCE_TYPE - && TREE_CODE (xtype) != REFERENCE_TYPE) - rval = default_conversion (rval); + + if (IS_AGGR_TYPE (TREE_TYPE (rval))) + return rval; if (warn_cast_qual && TREE_TYPE (xtype) @@ -1505,12 +1472,13 @@ build_type_conversion_1 (xtype, basetype to take place immediately. Otherwise, we build a SAVE_EXPR which can be evaluated if the results are ever needed. - If FOR_SURE >= 2, then we only look for exact conversions. + Changes to this functions should be mirrored in user_harshness. + + FIXME: Ambiguity checking is wrong. Should choose one by the implicit + object parameter, or by the second standard conversion sequence if + that doesn't do it. This will probably wait for an overloading rewrite. + (jason 8/9/95) */ - TYPE may be a reference type, in which case we first look - for something that will convert to a reference type. If - that fails, we will try to look for something of the - reference's target type, and then return a reference to that. */ tree build_type_conversion (code, xtype, expr, for_sure) enum tree_code code; @@ -1518,14 +1486,10 @@ build_type_conversion (code, xtype, expr int for_sure; { /* C++: check to see if we can convert this aggregate type - into the required scalar type. */ - tree type, type_default; - tree typename = build_typename_overload (xtype), *typenames; - int n_variants = 0; - tree basetype, save_basetype; - tree rval; - int exact_conversion = for_sure >= 2; - for_sure &= 1; + into the required type. */ + tree basetype; + tree conv; + tree winner = NULL_TREE; if (expr == error_mark_node) return error_mark_node; @@ -1534,313 +1498,144 @@ build_type_conversion (code, xtype, expr if (TREE_CODE (basetype) == REFERENCE_TYPE) basetype = TREE_TYPE (basetype); - if (TYPE_PTRMEMFUNC_P (basetype) && TREE_CODE (xtype) == BOOLEAN_TYPE) - { - /* We convert a pointer to member function into a boolean, - by just checking the index value, for == 0, we want false, for - != 0, we want true. */ - return convert (xtype, build_component_ref (expr, index_identifier, 0, 0)); - } - basetype = TYPE_MAIN_VARIANT (basetype); if (! TYPE_LANG_SPECIFIC (basetype) || ! TYPE_HAS_CONVERSION (basetype)) return NULL_TREE; - if (TREE_CODE (xtype) == POINTER_TYPE - || TREE_CODE (xtype) == REFERENCE_TYPE) - { - /* Prepare to match a variant of this type. */ - type = TYPE_MAIN_VARIANT (TREE_TYPE (xtype)); - for (n_variants = 0; type; type = TYPE_NEXT_VARIANT (type)) - n_variants++; - typenames = (tree *)alloca (n_variants * sizeof (tree)); - for (n_variants = 0, type = TYPE_MAIN_VARIANT (TREE_TYPE (xtype)); - type; n_variants++, type = TYPE_NEXT_VARIANT (type)) - { - if (type == TREE_TYPE (xtype)) - typenames[n_variants] = typename; - else if (TREE_CODE (xtype) == POINTER_TYPE) - typenames[n_variants] = build_typename_overload (build_pointer_type (type)); - else - typenames[n_variants] = build_typename_overload (build_reference_type (type)); - } - } - - save_basetype = basetype; - type = xtype; - - while (TYPE_HAS_CONVERSION (basetype)) - { - int i; - if (lookup_fnfields (TYPE_BINFO (basetype), typename, 0)) - return build_type_conversion_1 (xtype, basetype, expr, typename, for_sure); - for (i = 0; i < n_variants; i++) - if (typenames[i] != typename - && lookup_fnfields (TYPE_BINFO (basetype), typenames[i], 0)) - return build_type_conversion_1 (xtype, basetype, expr, typenames[i], for_sure); - - if (TYPE_BINFO_BASETYPES (basetype)) - basetype = TYPE_BINFO_BASETYPE (basetype, 0); - else - break; - } + /* Do we have an exact match? */ + { + tree typename = build_typename_overload (xtype); + if (lookup_fnfields (TYPE_BINFO (basetype), typename, 0)) + return build_type_conversion_1 (xtype, basetype, expr, typename, + for_sure); + } - if (TREE_CODE (type) == REFERENCE_TYPE) + /* Nope; try looking for others. */ + for (conv = lookup_conversions (basetype); conv; conv = TREE_CHAIN (conv)) { -#if 0 - /* Only reference variable initializations can use a temporary; this - must be handled elsewhere (like convert_to_reference and - compute_conversion_costs). */ - - type = TYPE_MAIN_VARIANT (TREE_TYPE (type)); - typename = build_typename_overload (type); - basetype = save_basetype; + if (winner && TREE_PURPOSE (winner) == TREE_PURPOSE (conv)) + continue; - /* May need to build a temporary for this. */ - while (TYPE_HAS_CONVERSION (basetype)) + if (can_convert (xtype, TREE_VALUE (conv))) { - if (lookup_fnfields (TYPE_BINFO (basetype), typename, 0)) + if (winner) { - int flags; - - if (for_sure == 0) - flags = LOOKUP_PROTECT; - else - flags = LOOKUP_NORMAL; - rval = build_method_call (expr, - constructor_name_full (typename), - NULL_TREE, NULL_TREE, flags); - if (rval == error_mark_node) + if (for_sure) { - if (for_sure == 0) - return NULL_TREE; - return error_mark_node; + cp_error ("ambiguous conversion from `%T' to `%T'", basetype, + xtype); + cp_error (" candidate conversions include `%T' and `%T'", + TREE_VALUE (winner), TREE_VALUE (conv)); } - - return convert (xtype, rval); + return NULL_TREE; } - if (TYPE_BINFO_BASETYPES (basetype)) - basetype = TYPE_BINFO_BASETYPE (basetype, 0); else - break; + winner = conv; } -#endif - /* No free conversions for reference types, right?. */ - return NULL_TREE; } - if (exact_conversion) - return NULL_TREE; - - if (TREE_CODE (type) == BOOLEAN_TYPE) - { - tree as_int = build_type_conversion (code, long_long_unsigned_type_node, expr, 0); - tree as_ptr = build_type_conversion (code, ptr_type_node, expr, 0); - /* We are missing the conversion to pointer to member type. */ - /* We are missing the conversion to floating type. */ - if (as_int && as_ptr && for_sure) - { - cp_error ("ambiguous conversion from `%T' to `bool', can convert to integral type or pointer", TREE_TYPE (expr)); - return error_mark_node; - } - if (as_int) - { - as_int = build_type_conversion (code, long_long_unsigned_type_node, expr, for_sure+exact_conversion*2); - return convert (xtype, as_int); - } - if (as_ptr) - { - as_ptr = build_type_conversion (code, ptr_type_node, expr, for_sure+exact_conversion*2); - return convert (xtype, as_ptr); - } - return NULL_TREE; - } + if (winner) + return build_type_conversion_1 (xtype, basetype, expr, + TREE_PURPOSE (winner), for_sure); - /* No perfect match found, try default. */ -#if 0 /* This is wrong; there is no standard conversion from void* to - anything. -jason */ - if (code == CONVERT_EXPR && TREE_CODE (type) == POINTER_TYPE) - type_default = ptr_type_node; - else -#endif - if (type == void_type_node) - return NULL_TREE; - else - { - tree tmp = default_conversion (build1 (NOP_EXPR, type, integer_zero_node)); - if (tmp == error_mark_node) - return NULL_TREE; - type_default = TREE_TYPE (tmp); - } + return NULL_TREE; +} - basetype = save_basetype; +/* Convert the given EXPR to one of a group of types suitable for use in an + expression. DESIRES is a combination of various WANT_* flags (q.v.) + which indicates which types are suitable. If COMPLAIN is 1, complain + about ambiguity; otherwise, the caller will deal with it. */ - if (type_default != type) - { - type = type_default; - typename = build_typename_overload (type); +tree +build_expr_type_conversion (desires, expr, complain) + int desires; + tree expr; + int complain; +{ + tree basetype = TREE_TYPE (expr); + tree conv; + tree winner = NULL_TREE; + + if (TREE_CODE (basetype) == OFFSET_TYPE) + expr = resolve_offset_ref (expr); + expr = convert_from_reference (expr); + basetype = TREE_TYPE (expr); - while (TYPE_HAS_CONVERSION (basetype)) - { - if (lookup_fnfields (TYPE_BINFO (basetype), typename, 0)) - return build_type_conversion_1 (xtype, basetype, expr, typename, for_sure); - if (TYPE_BINFO_BASETYPES (basetype)) - basetype = TYPE_BINFO_BASETYPE (basetype, 0); - else - break; - } - } + if (! IS_AGGR_TYPE (basetype)) + switch (TREE_CODE (basetype)) + { + case INTEGER_TYPE: + if ((desires & WANT_NULL) && TREE_CODE (expr) == INTEGER_CST + && integer_zerop (expr)) + return expr; + /* else fall through... */ + + case BOOLEAN_TYPE: + return (desires & WANT_INT) ? expr : NULL_TREE; + case ENUMERAL_TYPE: + return (desires & WANT_ENUM) ? expr : NULL_TREE; + case REAL_TYPE: + return (desires & WANT_FLOAT) ? expr : NULL_TREE; + case POINTER_TYPE: + return (desires & WANT_POINTER) ? expr : NULL_TREE; + + case FUNCTION_TYPE: + case ARRAY_TYPE: + return (desires & WANT_POINTER) ? default_conversion (expr) + : NULL_TREE; + default: + return NULL_TREE; + } - if (TREE_CODE (type) == POINTER_TYPE && TYPE_READONLY (TREE_TYPE (type))) - { - /* Try converting to some other const pointer type and then using - standard conversions. */ + if (! TYPE_HAS_CONVERSION (basetype)) + return NULL_TREE; - while (TYPE_HAS_CONVERSION (basetype)) - { - if (CLASSTYPE_CONVERSION (basetype, constptr_conv) != 0) - { - if (CLASSTYPE_CONVERSION (basetype, constptr_conv) == error_mark_node) - return error_mark_node; - typename = DECL_NAME (CLASSTYPE_CONVERSION (basetype, constptr_conv)); - return build_type_conversion_1 (xtype, basetype, expr, typename, for_sure); - } - if (TYPE_BINFO_BASETYPES (basetype)) - basetype = TYPE_BINFO_BASETYPE (basetype, 0); - else - break; - } - } - if (TREE_CODE (type) == POINTER_TYPE) + for (conv = lookup_conversions (basetype); conv; conv = TREE_CHAIN (conv)) { - /* Try converting to some other pointer type and then using standard - conversions. */ + int win = 0; + tree candidate; - while (TYPE_HAS_CONVERSION (basetype)) - { - if (CLASSTYPE_CONVERSION (basetype, ptr_conv) != 0) - { - if (CLASSTYPE_CONVERSION (basetype, ptr_conv) == error_mark_node) - return error_mark_node; - typename = DECL_NAME (CLASSTYPE_CONVERSION (basetype, ptr_conv)); - return build_type_conversion_1 (xtype, basetype, expr, typename, for_sure); - } - if (TYPE_BINFO_BASETYPES (basetype)) - basetype = TYPE_BINFO_BASETYPE (basetype, 0); - else - break; - } - } + if (winner && TREE_PURPOSE (winner) == TREE_PURPOSE (conv)) + continue; - /* Use the longer or shorter conversion that is appropriate. Have - to check against 0 because the conversion may come from a baseclass. */ - if (TREE_CODE (type) == INTEGER_TYPE - && TYPE_HAS_INT_CONVERSION (basetype) - && CLASSTYPE_CONVERSION (basetype, int_conv) != 0 - && CLASSTYPE_CONVERSION (basetype, int_conv) != error_mark_node) - { - typename = DECL_NAME (CLASSTYPE_CONVERSION (basetype, int_conv)); - return build_type_conversion_1 (xtype, basetype, expr, typename, for_sure); - } + candidate = TREE_VALUE (conv); + if (TREE_CODE (candidate) == REFERENCE_TYPE) + candidate = TREE_TYPE (candidate); - if (TREE_CODE (type) == REAL_TYPE - && TYPE_HAS_REAL_CONVERSION (basetype) - && CLASSTYPE_CONVERSION (basetype, real_conv) != 0 - && CLASSTYPE_CONVERSION (basetype, real_conv) != error_mark_node) - { - /* Only accept using an operator double() if there isn't a conflicting - operator int(). */ - if (TYPE_HAS_INT_CONVERSION (basetype)) + switch (TREE_CODE (candidate)) { - if (for_sure) - { - cp_error ("two possible conversions for type `%T'", type); - return error_mark_node; - } - else - return NULL_TREE; + case BOOLEAN_TYPE: + case INTEGER_TYPE: + win = (desires & WANT_INT); break; + case ENUMERAL_TYPE: + win = (desires & WANT_ENUM); break; + case REAL_TYPE: + win = (desires & WANT_FLOAT); break; + case POINTER_TYPE: + win = (desires & WANT_POINTER); break; } - typename = DECL_NAME (CLASSTYPE_CONVERSION (basetype, real_conv)); - return build_type_conversion_1 (xtype, basetype, expr, typename, for_sure); - } - - /* THESE ARE TOTAL KLUDGES. */ - /* Default promotion yields no new alternatives, try - conversions which are anti-default, such as - - double -> float or int -> unsigned or unsigned -> long - - */ - if (type_default == type - && (INTEGRAL_TYPE_P (type) || TREE_CODE (type) == REAL_TYPE)) - { - int not_again = 0; - - if (type == double_type_node) - typename = build_typename_overload (float_type_node); - else if (type == integer_type_node) - typename = build_typename_overload (unsigned_type_node); - else if (type == unsigned_type_node) - typename = build_typename_overload (long_integer_type_node); - - again: - basetype = save_basetype; - while (TYPE_HAS_CONVERSION (basetype)) - { - if (lookup_fnfields (TYPE_BINFO (basetype), typename, 0)) - return build_type_conversion_1 (xtype, basetype, expr, typename, for_sure); - if (TYPE_BINFO_BASETYPES (basetype)) - basetype = TYPE_BINFO_BASETYPE (basetype, 0); - else - break; - } - if (! not_again) + if (win) { - if (type == integer_type_node) + if (winner) { - typename = build_typename_overload (long_integer_type_node); - not_again = 1; - goto again; + if (complain) + { + cp_error ("ambiguous default type conversion from `%T'", + basetype); + cp_error (" candidate conversions include `%T' and `%T'", + TREE_VALUE (winner), TREE_VALUE (conv)); + } + return error_mark_node; } else - { - typename = build_typename_overload (integer_type_node); - not_again = 1; - goto again; - } + winner = conv; } } - /* Now, try C promotions... - - float -> int - int -> float */ - - basetype = save_basetype; - if (TREE_CODE (type) == REAL_TYPE) - type = integer_type_node; - else if (TREE_CODE (type) == INTEGER_TYPE) - if (TYPE_HAS_REAL_CONVERSION (basetype)) - type = double_type_node; - else - return NULL_TREE; - else - return NULL_TREE; - - typename = build_typename_overload (type); - while (TYPE_HAS_CONVERSION (basetype)) - { - if (lookup_fnfields (TYPE_BINFO (basetype), typename, 0)) - { - rval = build_type_conversion_1 (xtype, basetype, expr, typename, for_sure); - return rval; - } - if (TYPE_BINFO_BASETYPES (basetype)) - basetype = TYPE_BINFO_BASETYPE (basetype, 0); - else - break; - } + if (winner) + return build_type_conversion_1 (TREE_VALUE (winner), basetype, expr, + TREE_PURPOSE (winner), 1); return NULL_TREE; } @@ -1856,143 +1651,122 @@ build_default_binary_type_conversion (co enum tree_code code; tree *arg1, *arg2; { - tree type1 = TREE_TYPE (*arg1); - tree type2 = TREE_TYPE (*arg2); - - if (TREE_CODE (type1) == REFERENCE_TYPE - || TREE_CODE (type1) == POINTER_TYPE) - type1 = TREE_TYPE (type1); - if (TREE_CODE (type2) == REFERENCE_TYPE - || TREE_CODE (type2) == POINTER_TYPE) - type2 = TREE_TYPE (type2); - - if (TREE_CODE (TYPE_NAME (type1)) != TYPE_DECL) - { - tree decl = typedecl_for_tag (type1); - if (decl) - error ("type conversion nonexistent for type `%s'", - IDENTIFIER_POINTER (DECL_NAME (decl))); - else - error ("type conversion nonexistent for non-C++ type"); - return 0; - } - if (TREE_CODE (TYPE_NAME (type2)) != TYPE_DECL) + switch (code) { - tree decl = typedecl_for_tag (type2); - if (decl) - error ("type conversion nonexistent for type `%s'", - IDENTIFIER_POINTER (decl)); - else - error ("type conversion nonexistent for non-C++ type"); - return 0; - } + case MULT_EXPR: + case TRUNC_DIV_EXPR: + case CEIL_DIV_EXPR: + case FLOOR_DIV_EXPR: + case ROUND_DIV_EXPR: + case EXACT_DIV_EXPR: + *arg1 = build_expr_type_conversion (WANT_ARITH | WANT_ENUM, *arg1, 0); + *arg2 = build_expr_type_conversion (WANT_ARITH | WANT_ENUM, *arg2, 0); + break; - if (!IS_AGGR_TYPE (type1) || !TYPE_HAS_CONVERSION (type1)) - { - if (!IS_AGGR_TYPE (type2) || !TYPE_HAS_CONVERSION (type2)) - cp_error ("no conversion from `%T' and `%T' to types with default `%O' ", - type1, type2, code); - else - cp_error ("no conversion from `%T' to type with default `%O'", - type1, code); - return 0; - } - else if (!IS_AGGR_TYPE (type2) || !TYPE_HAS_CONVERSION (type2)) - { - cp_error ("no conversion from `%T' to type with default `%O'", - type2, code); - return 0; - } + case TRUNC_MOD_EXPR: + case FLOOR_MOD_EXPR: + case LSHIFT_EXPR: + case RSHIFT_EXPR: + case BIT_AND_EXPR: + case BIT_XOR_EXPR: + case BIT_IOR_EXPR: + *arg1 = build_expr_type_conversion (WANT_INT | WANT_ENUM, *arg1, 0); + *arg2 = build_expr_type_conversion (WANT_INT | WANT_ENUM, *arg2, 0); + break; - if (code == TRUTH_ANDIF_EXPR - || code == TRUTH_ORIF_EXPR) - { - *arg1 = convert (bool_type_node, *arg1); - *arg2 = convert (bool_type_node, *arg2); - } - else if (TYPE_HAS_INT_CONVERSION (type1)) - { - if (TYPE_HAS_REAL_CONVERSION (type1)) - cp_pedwarn ("ambiguous type conversion for type `%T', defaulting to int", - type1); - *arg1 = build_type_conversion (code, integer_type_node, *arg1, 1); - *arg2 = build_type_conversion (code, integer_type_node, *arg2, 1); - } - else if (TYPE_HAS_REAL_CONVERSION (type1)) - { - *arg1 = build_type_conversion (code, double_type_node, *arg1, 1); - *arg2 = build_type_conversion (code, double_type_node, *arg2, 1); - } - else - { - *arg1 = build_type_conversion (code, ptr_type_node, *arg1, 1); - if (*arg1 == error_mark_node) - error ("ambiguous pointer conversion"); - *arg2 = build_type_conversion (code, ptr_type_node, *arg2, 1); - if (*arg1 != error_mark_node && *arg2 == error_mark_node) - error ("ambiguous pointer conversion"); - } - if (*arg1 == 0) - { - if (*arg2 == 0 && type1 != type2) - cp_error ("default type conversion for types `%T' and `%T' failed", - type1, type2); - else - cp_error ("default type conversion for type `%T' failed", type1); - return 0; - } - else if (*arg2 == 0) - { - cp_error ("default type conversion for type `%T' failed", type2); - return 0; - } - return 1; -} + case PLUS_EXPR: + { + tree a1, a2, p1, p2; + int wins; -/* Must convert an aggregate type to non-aggregate type. - Attempts to find a non-ambiguous, "best" type conversion. + a1 = build_expr_type_conversion (WANT_ARITH | WANT_ENUM, *arg1, 0); + a2 = build_expr_type_conversion (WANT_ARITH | WANT_ENUM, *arg2, 0); + p1 = build_expr_type_conversion (WANT_POINTER, *arg1, 0); + p2 = build_expr_type_conversion (WANT_POINTER, *arg2, 0); + + wins = (a1 && a2) + (a1 && p2) + (p1 && a2); + + if (wins > 1) + error ("ambiguous default type conversion for `operator +'"); + + if (a1 && a2) + *arg1 = a1, *arg2 = a2; + else if (a1 && p2) + *arg1 = a1, *arg2 = p2; + else + *arg1 = p1, *arg2 = a2; + break; + } - Return 1 on success, 0 on failure. + case MINUS_EXPR: + { + tree a1, a2, p1, p2; + int wins; - The type of the argument is expected to be of aggregate type here. + a1 = build_expr_type_conversion (WANT_ARITH | WANT_ENUM, *arg1, 0); + a2 = build_expr_type_conversion (WANT_ARITH | WANT_ENUM, *arg2, 0); + p1 = build_expr_type_conversion (WANT_POINTER, *arg1, 0); + p2 = build_expr_type_conversion (WANT_POINTER, *arg2, 0); + + wins = (a1 && a2) + (p1 && p2) + (p1 && a2); + + if (wins > 1) + error ("ambiguous default type conversion for `operator -'"); + + if (a1 && a2) + *arg1 = a1, *arg2 = a2; + else if (p1 && p2) + *arg1 = p1, *arg2 = p2; + else + *arg1 = p1, *arg2 = a2; + break; + } - @@ What are the real semantics of this supposed to be??? */ -int -build_default_unary_type_conversion (code, arg) - enum tree_code code; - tree *arg; -{ - tree type = TREE_TYPE (*arg); + case GT_EXPR: + case LT_EXPR: + case GE_EXPR: + case LE_EXPR: + case EQ_EXPR: + case NE_EXPR: + { + tree a1, a2, p1, p2; + int wins; - if (! TYPE_HAS_CONVERSION (type)) - { - cp_error ("type conversion required for type `%T'", type); - return 0; - } + a1 = build_expr_type_conversion (WANT_ARITH | WANT_ENUM, *arg1, 0); + a2 = build_expr_type_conversion (WANT_ARITH | WANT_ENUM, *arg2, 0); + p1 = build_expr_type_conversion (WANT_POINTER | WANT_NULL, *arg1, 0); + p2 = build_expr_type_conversion (WANT_POINTER | WANT_NULL, *arg2, 0); - if (code == TRUTH_NOT_EXPR) - *arg = convert (bool_type_node, *arg); - else if (TYPE_HAS_INT_CONVERSION (type)) - { - if (TYPE_HAS_REAL_CONVERSION (type)) - cp_pedwarn ("ambiguous type conversion for type `%T', defaulting to int", - type); - *arg = build_type_conversion (code, integer_type_node, *arg, 1); - } - else if (TYPE_HAS_REAL_CONVERSION (type)) - *arg = build_type_conversion (code, double_type_node, *arg, 1); - else - { - *arg = build_type_conversion (code, ptr_type_node, *arg, 1); - if (*arg == error_mark_node) - error ("ambiguous pointer conversion"); - } - if (*arg == NULL_TREE) - { - cp_error ("default type conversion for type `%T' failed", type); - return 0; + wins = (a1 && a2) + (p1 && p2); + + if (wins > 1) + cp_error ("ambiguous default type conversion for `%O'", code); + + if (a1 && a2) + *arg1 = a1, *arg2 = a2; + else + *arg1 = p1, *arg2 = p2; + break; + } + + case TRUTH_ANDIF_EXPR: + case TRUTH_ORIF_EXPR: + *arg1 = convert (boolean_type_node, *arg1); + *arg2 = convert (boolean_type_node, *arg2); + break; + + default: + *arg1 = NULL_TREE; + *arg2 = NULL_TREE; } - return 1; + + if (*arg1 == error_mark_node || *arg2 == error_mark_node) + cp_error ("ambiguous default type conversion for `%O'", code); + + if (*arg1 && *arg2) + return 1; + + return 0; } /* Implements integral promotion (4.1) and float->double promotion. */ @@ -2000,13 +1774,18 @@ tree type_promotes_to (type) tree type; { - int constp = TYPE_READONLY (type); - int volatilep = TYPE_VOLATILE (type); + int constp, volatilep; + + if (type == error_mark_node) + return error_mark_node; + + constp = TYPE_READONLY (type); + volatilep = TYPE_VOLATILE (type); type = TYPE_MAIN_VARIANT (type); /* bool always promotes to int (not unsigned), even if it's the same size. */ - if (type == bool_type_node) + if (type == boolean_type_node) type = integer_type_node; /* Normally convert enums to int, but convert wide enums to something