--- gcc/cp/call.c 2018/04/24 18:20:21 1.1 +++ gcc/cp/call.c 2018/04/24 18:27:08 1.1.1.2 @@ -1,5 +1,5 @@ /* Functions related to invoking methods and overloaded functions. - Copyright (C) 1987, 1992, 1993 Free Software Foundation, Inc. + Copyright (C) 1987, 1992, 1993, 1994, 1995 Free Software Foundation, Inc. Contributed by Michael Tiemann (tiemann@cygnus.com) and hacked by Brendan Kehoe (brendan@cygnus.com). @@ -17,7 +17,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. */ /* High-level class interface. */ @@ -27,6 +28,7 @@ the Free Software Foundation, 675 Mass A #include #include "cp-tree.h" #include "class.h" +#include "output.h" #include "flags.h" #include "obstack.h" @@ -47,6 +49,7 @@ extern tree unary_complex_lvalue (); static struct harshness_code convert_harshness (); #define EVIL_RETURN(ARG) ((ARG).code = EVIL_CODE, (ARG)) +#define STD_RETURN(ARG) ((ARG).code = STD_CODE, (ARG)) #define QUAL_RETURN(ARG) ((ARG).code = QUAL_CODE, (ARG)) #define TRIVIAL_RETURN(ARG) ((ARG).code = TRIVIAL_CODE, (ARG)) #define ZERO_RETURN(ARG) ((ARG).code = 0, (ARG)) @@ -117,6 +120,7 @@ convert_harshness (type, parmtype, parm) struct harshness_code h; register enum tree_code codel; register enum tree_code coder; + int lvalue; h.code = 0; h.distance = 0; @@ -126,17 +130,22 @@ convert_harshness (type, parmtype, parm) n_convert_harshness++; #endif - if (TYPE_PTRMEMFUNC_P (type)) - type = TYPE_PTRMEMFUNC_FN_TYPE (type); - if (TYPE_PTRMEMFUNC_P (parmtype)) - parmtype = TYPE_PTRMEMFUNC_FN_TYPE (parmtype); - if (TREE_CODE (parmtype) == REFERENCE_TYPE) { if (parm) parm = convert_from_reference (parm); parmtype = TREE_TYPE (parmtype); + lvalue = 1; } + else if (parm) + lvalue = lvalue_p (parm); + else + lvalue = 0; + + if (TYPE_PTRMEMFUNC_P (type)) + type = TYPE_PTRMEMFUNC_FN_TYPE (type); + if (TYPE_PTRMEMFUNC_P (parmtype)) + parmtype = TYPE_PTRMEMFUNC_FN_TYPE (parmtype); codel = TREE_CODE (type); coder = TREE_CODE (parmtype); @@ -147,6 +156,60 @@ convert_harshness (type, parmtype, parm) if (coder == ERROR_MARK) return EVIL_RETURN (h); + if (codel == REFERENCE_TYPE) + { + tree ttl, ttr; + int constp = parm ? TREE_READONLY (parm) : TYPE_READONLY (parmtype); + int volatilep = (parm ? TREE_THIS_VOLATILE (parm) + : TYPE_VOLATILE (parmtype)); + register tree intype = TYPE_MAIN_VARIANT (parmtype); + register enum tree_code form = TREE_CODE (intype); + int penalty = 0; + + ttl = TREE_TYPE (type); + + /* Only allow const reference binding if we were given a parm to deal + with, since it isn't really a conversion. This is a hack to + prevent build_type_conversion from finding this conversion, but + still allow overloading to find it. */ + if (! lvalue && ! (parm && TYPE_READONLY (ttl))) + return EVIL_RETURN (h); + + if (TYPE_READONLY (ttl) < constp + || TYPE_VOLATILE (ttl) < volatilep) + return EVIL_RETURN (h); + + /* When passing a non-const argument into a const reference, dig it a + little, so a non-const reference is preferred over this one. */ + penalty = ((TYPE_READONLY (ttl) > constp) + + (TYPE_VOLATILE (ttl) > volatilep)); + + ttl = TYPE_MAIN_VARIANT (ttl); + + if (form == OFFSET_TYPE) + { + intype = TREE_TYPE (intype); + form = TREE_CODE (intype); + } + + ttr = intype; + + if (TREE_CODE (ttl) == ARRAY_TYPE && TREE_CODE (ttr) == ARRAY_TYPE) + { + if (comptypes (ttl, ttr, 1)) + return ZERO_RETURN (h); + return EVIL_RETURN (h); + } + + h = convert_harshness (ttl, ttr, NULL_TREE); + if (penalty && h.code == 0) + { + h.code = QUAL_CODE; + h.int_penalty = penalty; + } + return h; + } + if (codel == POINTER_TYPE && fntype_p (parmtype)) { tree p1, p2; @@ -164,10 +227,36 @@ convert_harshness (type, parmtype, parm) if (coder != TREE_CODE (type)) return EVIL_RETURN (h); + if (type != parmtype && coder == METHOD_TYPE) + { + tree ttl = TYPE_METHOD_BASETYPE (type); + tree ttr = TYPE_METHOD_BASETYPE (parmtype); + + int b_or_d = get_base_distance (ttr, ttl, 0, 0); + if (b_or_d < 0) + { + b_or_d = get_base_distance (ttl, ttr, 0, 0); + if (b_or_d < 0) + return EVIL_RETURN (h); + h.distance = -b_or_d; + } + else + h.distance = b_or_d; + h.code = STD_CODE; + + type = build_function_type + (TREE_TYPE (type), TREE_CHAIN (TYPE_ARG_TYPES (type))); + parmtype = build_function_type + (TREE_TYPE (parmtype), TREE_CHAIN (TYPE_ARG_TYPES (parmtype))); + } + /* We allow the default conversion between function type and pointer-to-function type for free. */ - if (type == parmtype) - return ZERO_RETURN (h); + if (comptypes (type, parmtype, 1)) + return h; + + if (pedantic) + return EVIL_RETURN (h); /* Compare return types. */ p1 = TREE_TYPE (type); @@ -200,14 +289,16 @@ convert_harshness (type, parmtype, parm) if (! BINFO_OFFSET_ZEROP (binfo)) { +#if 0 static int explained = 0; if (h2.distance < 0) - message_2_types (sorry, "cannot cast `%d' to `%d' at function call site", p2, p1); + message_2_types (sorry, "cannot cast `%s' to `%s' at function call site", p2, p1); else - message_2_types (sorry, "cannot cast `%d' to `%d' at function call site", p1, p2); + message_2_types (sorry, "cannot cast `%s' to `%s' at function call site", p1, p2); if (! explained++) sorry ("(because pointer values change during conversion)"); +#endif return EVIL_RETURN (h); } } @@ -259,28 +350,34 @@ convert_harshness (type, parmtype, parm) } else if (codel == POINTER_TYPE && coder == OFFSET_TYPE) { + tree ttl, ttr; + /* Get to the OFFSET_TYPE that this might be. */ type = TREE_TYPE (type); if (coder != TREE_CODE (type)) return EVIL_RETURN (h); - if (TYPE_OFFSET_BASETYPE (type) == TYPE_OFFSET_BASETYPE (parmtype)) + ttl = TYPE_OFFSET_BASETYPE (type); + ttr = TYPE_OFFSET_BASETYPE (parmtype); + + if (ttl == ttr) h.code = 0; - else if (UNIQUELY_DERIVED_FROM_P (TYPE_OFFSET_BASETYPE (type), - TYPE_OFFSET_BASETYPE (parmtype))) - { - h.code = STD_CODE; - h.distance = 1; - } - else if (UNIQUELY_DERIVED_FROM_P (TYPE_OFFSET_BASETYPE (parmtype), - TYPE_OFFSET_BASETYPE (type))) + else { + int b_or_d = get_base_distance (ttr, ttl, 0, 0); + if (b_or_d < 0) + { + b_or_d = get_base_distance (ttl, ttr, 0, 0); + if (b_or_d < 0) + return EVIL_RETURN (h); + h.distance = -b_or_d; + } + else + h.distance = b_or_d; h.code = STD_CODE; - h.distance = -1; } - else - return EVIL_RETURN (h); + /* Now test the OFFSET_TYPE's target compatibility. */ type = TREE_TYPE (type); parmtype = TREE_TYPE (parmtype); @@ -300,6 +397,21 @@ convert_harshness (type, parmtype, parm) if (coder == VOID_TYPE) return EVIL_RETURN (h); + if (codel == BOOLEAN_TYPE) + { + if (INTEGRAL_CODE_P (coder) || coder == REAL_TYPE) + return STD_RETURN (h); + else if (coder == POINTER_TYPE || coder == OFFSET_TYPE) + { + /* Make this worse than any conversion to another pointer. + FIXME this is how I think the language should work, but it may not + end up being how the language is standardized (jason 1/30/95). */ + h.distance = 32767; + return STD_RETURN (h); + } + return EVIL_RETURN (h); + } + if (INTEGRAL_CODE_P (codel)) { /* Control equivalence of ints an enums. */ @@ -363,10 +475,21 @@ convert_harshness (type, parmtype, parm) } /* Convert arrays which have not previously been converted. */ +#if 0 if (codel == ARRAY_TYPE) codel = POINTER_TYPE; +#endif if (coder == ARRAY_TYPE) - coder = POINTER_TYPE; + { + coder = POINTER_TYPE; + if (parm) + { + parm = decay_conversion (parm); + parmtype = TREE_TYPE (parm); + } + else + parmtype = build_pointer_type (TREE_TYPE (parmtype)); + } /* Conversions among pointers */ if (codel == POINTER_TYPE && coder == POINTER_TYPE) @@ -375,11 +498,10 @@ convert_harshness (type, parmtype, parm) register tree ttr = TYPE_MAIN_VARIANT (TREE_TYPE (parmtype)); int penalty = 4 * (ttl != ttr); - /* Anything converts to void *. void * converts to anything. - Since these may be `const void *' (etc.) use VOID_TYPE - instead of void_type_node. Otherwise, the targets must be the same, - except that we do allow (at some cost) conversion between signed and - unsigned pointer types. */ + /* Anything converts to void *. Since this may be `const void *' + (etc.) use VOID_TYPE instead of void_type_node. Otherwise, the + targets must be the same, except that we do allow (at some cost) + conversion between signed and unsigned pointer types. */ if ((TREE_CODE (ttl) == METHOD_TYPE || TREE_CODE (ttl) == FUNCTION_TYPE) @@ -396,7 +518,8 @@ convert_harshness (type, parmtype, parm) } #if 1 - if (TREE_CODE (ttl) != VOID_TYPE && TREE_CODE (ttr) != VOID_TYPE) + if (TREE_CODE (ttl) != VOID_TYPE + && (TREE_CODE (ttr) != VOID_TYPE || !parm || !integer_zerop (parm))) { if (TREE_UNSIGNED (ttl) != TREE_UNSIGNED (ttr)) { @@ -404,7 +527,7 @@ convert_harshness (type, parmtype, parm) ttr = unsigned_type (ttr); penalty = 10; } - if (! comp_target_types (ttl, ttr, 0)) + if (comp_target_types (type, parmtype, 1) <= 0) return EVIL_RETURN (h); } #else @@ -414,7 +537,7 @@ convert_harshness (type, parmtype, parm) && (ttl = unsigned_type (ttl), ttr = unsigned_type (ttr), penalty = 10, 0)) - || (comp_target_types (ttl, ttr, 0)))) + || (comp_target_types (ttl, ttr, 0) > 0))) return EVIL_RETURN (h); #endif @@ -465,7 +588,17 @@ convert_harshness (type, parmtype, parm) h.distance = CLASSTYPE_MAX_DEPTH (ttr)+1; return h; } + h.code = penalty ? STD_CODE : PROMO_CODE; + /* Catch things like `const char *' -> `const void *' + vs `const char *' -> `void *'. */ + if (ttl != ttr) + { + tree tmp1 = TREE_TYPE (type), tmp2 = TREE_TYPE (parmtype); + if ((TYPE_READONLY (tmp1) != TREE_READONLY (tmp2)) + || (TYPE_VOLATILE (tmp1) != TYPE_VOLATILE (tmp2))) + h.code |= QUAL_CODE; + } return h; } @@ -491,128 +624,6 @@ convert_harshness (type, parmtype, parm) && IS_SIGNATURE_POINTER (type) && IS_SIGNATURE (TREE_TYPE (parmtype))) return ZERO_RETURN (h); - if (codel == REFERENCE_TYPE) - { - tree ttl, ttr; - int constp = parm ? TREE_READONLY (parm) : TYPE_READONLY (parmtype); - int volatilep = (parm ? TREE_THIS_VOLATILE (parm) - : TYPE_VOLATILE (parmtype)); - register tree intype = TYPE_MAIN_VARIANT (parmtype); - register enum tree_code form = TREE_CODE (intype); - int penalty = 0; - - ttl = TREE_TYPE (type); - - /* When passing a non-const argument into a const reference (or vice - versa), dig it a little, so a non-const reference is preferred - over this one. (mrs) */ - if (TYPE_READONLY (ttl) != constp - || TYPE_VOLATILE (ttl) != volatilep) - penalty = 2; - else - penalty = 0; - - ttl = TYPE_MAIN_VARIANT (ttl); - - if (form == OFFSET_TYPE) - { - intype = TREE_TYPE (intype); - form = TREE_CODE (intype); - } - - if (ttl == intype && penalty == 0) - return ZERO_RETURN (h); - else - penalty = 2; - - ttr = intype; - - /* If the initializer is not an lvalue, then it does not - matter if we make life easier for the programmer - by creating a temporary variable with which to - hold the result. */ - if (parm && (INTEGRAL_CODE_P (coder) - || coder == REAL_TYPE) - && ! lvalue_p (parm)) - { - h = convert_harshness (ttl, ttr, NULL_TREE); - if (penalty > 2 || h.code != 0) - h.code |= STD_CODE; - else - h.code |= TRIVIAL_CODE; - h.distance = 0; - return h; - } - - if (TREE_UNSIGNED (ttl) ^ TREE_UNSIGNED (intype)) - { - ttl = unsigned_type (ttl); - ttr = intype = unsigned_type (intype); - penalty += 2; - } - - if (ttl == ttr) - { - if (penalty > 2) - { - h.code = STD_CODE; - h.distance = 0; - } - else - { - h.code = TRIVIAL_CODE; - /* We set this here so that build_overload_call_real will be - able to see the penalty we found, rather than just looking - at a TRIVIAL_CODE with no other information. */ - h.int_penalty = penalty; - } - return h; - } - - /* Pointers to voids always convert for pointers. But - make them less natural than more specific matches. */ - if (TREE_CODE (ttl) == POINTER_TYPE && TREE_CODE (ttr) == POINTER_TYPE) - { - if (TREE_TYPE (ttl) == void_type_node - || TREE_TYPE (ttr) == void_type_node) - { - h.code = STD_CODE; - h.distance = 0; - return h; - } - } - - /* Here it does matter. If this conversion is from derived to base, - allow it. Otherwise, types must be compatible in the strong sense. */ - if (TREE_CODE (ttl) == RECORD_TYPE && TREE_CODE (ttr) == RECORD_TYPE) - { - int b_or_d = get_base_distance (ttl, ttr, 0, 0); - if (b_or_d < 0) - { - b_or_d = get_base_distance (ttr, ttl, 0, 0); - if (b_or_d < 0) - return EVIL_RETURN (h); - h.distance = -b_or_d; - } - /* Say that this conversion is relatively painless. - If it turns out that there is a user-defined X(X&) - constructor, then that will be invoked, but that's - preferable to dealing with other user-defined conversions - that may produce surprising results. */ - else - h.distance = b_or_d; - h.code = STD_CODE; - return h; - } - - if (comp_target_types (ttl, intype, 1)) - { - if (penalty) - h.code = STD_CODE; - h.distance = 0; - return h; - } - } if (codel == RECORD_TYPE && coder == RECORD_TYPE) { int b_or_d = get_base_distance (type, parmtype, 0, 0); @@ -631,6 +642,68 @@ convert_harshness (type, parmtype, parm) return EVIL_RETURN (h); } +/* A clone of build_type_conversion for checking user-defined conversions in + overload resolution. */ + +int +user_harshness (type, parmtype, parm) + register tree type, parmtype; + tree parm; +{ + tree conv; + tree winner = NULL_TREE; + int code; + + { + tree typename = build_typename_overload (type); + if (lookup_fnfields (TYPE_BINFO (parmtype), typename, 0)) + return 0; + } + + for (conv = lookup_conversions (parmtype); conv; conv = TREE_CHAIN (conv)) + { + struct harshness_code tmp; + + if (winner && TREE_PURPOSE (winner) == TREE_PURPOSE (conv)) + continue; + + if (tmp = convert_harshness (type, TREE_VALUE (conv), NULL_TREE), + tmp.code < USER_CODE && tmp.distance >= 0) + { + if (winner) + return EVIL_CODE; + else + { + winner = conv; + code = tmp.code; + } + } + } + + if (winner) + return code; + + return -1; +} + +int +can_convert (to, from) + tree to, from; +{ + struct harshness_code h; + h = convert_harshness (to, from, NULL_TREE); + return h.code < USER_CODE && h.distance >= 0; +} + +int +can_convert_arg (to, from, arg) + tree to, from, arg; +{ + struct harshness_code h; + h = convert_harshness (to, from, arg); + return h.code < USER_CODE && h.distance >= 0; +} + #ifdef DEBUG_MATCHING static char * print_harshness (h) @@ -912,43 +985,14 @@ compute_conversion_costs (function, tta_ if (TYPE_LANG_SPECIFIC (actual_type) && TYPE_HAS_CONVERSION (actual_type)) { - tree conv; - /* Don't issue warnings since we're only groping - around for the right answer, we haven't yet - committed to going with this solution. */ - int old_inhibit_warnings = inhibit_warnings; - - inhibit_warnings = 1; - conv = build_type_conversion - (CALL_EXPR, TREE_VALUE (ttf), TREE_VALUE (tta), 0); - inhibit_warnings = old_inhibit_warnings; + int extra = user_harshness (formal_type, actual_type); - if (conv) - { - if (conv == error_mark_node) - win += 2; - else - { - win++; - if (TREE_CODE (conv) != CALL_EXPR) - extra_conversions = 1; - } - } - else if (TREE_CODE (TREE_VALUE (ttf)) == REFERENCE_TYPE) + if (extra == EVIL_CODE) + win += 2; + else if (extra >= 0) { - conv = build_type_conversion (CALL_EXPR, formal_type, - TREE_VALUE (tta), 0); - if (conv) - { - if (conv == error_mark_node) - win += 2; - else - { - win++; - if (TREE_CODE (conv) != CALL_EXPR) - extra_conversions = 1; - } - } + win++; + extra_conversions = extra; } } } @@ -1367,6 +1411,7 @@ resolve_scope_to_name (outer_type, inner if (outer_type == NULL_TREE) { + tree x; /* If we have something that's already a type by itself, use that. */ if (IDENTIFIER_HAS_TYPE_VALUE (inner_name)) @@ -1376,6 +1421,14 @@ resolve_scope_to_name (outer_type, inner inner_type); return inner_name; } + + x = lookup_name (inner_name, 0); + + if (x && TREE_CODE (x) == NAMESPACE_DECL) + { + x = lookup_namespace_name (x, inner_type); + return x; + } return NULL_TREE; } @@ -1597,8 +1650,8 @@ build_method_call (instance, name, parms result = build_method_call (instance, name, parms, basetype_path, (LOOKUP_SPECULATIVELY|flags) &~LOOKUP_COMPLAIN); - /* If it works, return it. */ - if (result && result != error_mark_node) + /* If it finds a match, return it. */ + if (result) return build_method_call (instance, name, parms, basetype_path, flags); /* If it doesn't work, two argument delete must work */ TREE_CHAIN (parms) = save_last; @@ -1725,10 +1778,24 @@ build_method_call (instance, name, parms need_vtbl = (dtor_label || ctor_label) ? unneeded : maybe_needed; - instance = C_C_D; - instance_ptr = current_class_decl; - result = build_field_call (TYPE_BINFO (current_class_type), - instance_ptr, name, parms); + /* If `this' is a signature pointer and `name' is not a constructor, + we are calling a signature member function. In that case, set the + `basetype' to the signature type and dereference the `optr' field. */ + if (IS_SIGNATURE_POINTER (basetype) + && TYPE_IDENTIFIER (basetype) != name) + { + basetype = SIGNATURE_TYPE (basetype); + instance_ptr = build_optr_ref (instance); + instance_ptr = convert (build_pointer_type (basetype), instance_ptr); + basetype_path = TYPE_BINFO (basetype); + } + else + { + instance = C_C_D; + instance_ptr = current_class_decl; + basetype_path = TYPE_BINFO (current_class_type); + } + result = build_field_call (basetype_path, instance_ptr, name, parms); if (result) return result; @@ -1741,7 +1808,7 @@ build_method_call (instance, name, parms within the scope of this function. */ if (!(flags & LOOKUP_NONVIRTUAL) && TYPE_VIRTUAL_P (basetype)) need_vtbl = maybe_needed; - instance_ptr = build1 (ADDR_EXPR, TYPE_POINTER_TO (basetype), instance); + instance_ptr = build1 (ADDR_EXPR, build_pointer_type (basetype), instance); } else { @@ -1772,7 +1839,10 @@ build_method_call (instance, name, parms } else { - if (! IS_AGGR_TYPE (basetype)) + if (! IS_AGGR_TYPE (basetype) + && ! (TYPE_LANG_SPECIFIC (basetype) + && (IS_SIGNATURE_POINTER (basetype) + || IS_SIGNATURE_REFERENCE (basetype)))) goto non_aggr_error; /* If `instance' is a signature pointer/reference and `name' is @@ -1784,7 +1854,7 @@ build_method_call (instance, name, parms basetype = SIGNATURE_TYPE (basetype); if ((IS_SIGNATURE (basetype) - && (instance_ptr = build_optr_ref (instance))) + && (instance_ptr = instance)) || (lvalue_p (instance) && (instance_ptr = build_unary_op (ADDR_EXPR, instance, 0))) || (instance_ptr = unary_complex_lvalue (ADDR_EXPR, instance))) @@ -1802,7 +1872,7 @@ build_method_call (instance, name, parms we can manage. */ tree temp = get_temp_name (TREE_TYPE (instance), 0); if (IS_AGGR_TYPE (TREE_TYPE (instance))) - expand_aggr_init (temp, instance, 0); + expand_aggr_init (temp, instance, 0, flags); else { store_init_value (temp, instance); @@ -1813,11 +1883,7 @@ build_method_call (instance, name, parms } else { - if (TREE_CODE (instance) != CALL_EXPR -#ifdef PCC_STATIC_STRUCT_RETURN - && TREE_CODE (instance) != RTL_EXPR -#endif - ) + if (TREE_CODE (instance) != CALL_EXPR) my_friendly_abort (125); if (TYPE_NEEDS_CONSTRUCTING (basetype)) instance = build_cplus_new (basetype, instance, 0); @@ -1829,12 +1895,15 @@ build_method_call (instance, name, parms instance_ptr = build_unary_op (ADDR_EXPR, instance, 0); } /* @@ Should we call comp_target_types here? */ - inst_ptr_basetype = TREE_TYPE (TREE_TYPE (instance_ptr)); + if (IS_SIGNATURE (basetype)) + inst_ptr_basetype = basetype; + else + inst_ptr_basetype = TREE_TYPE (TREE_TYPE (instance_ptr)); if (TYPE_MAIN_VARIANT (basetype) == TYPE_MAIN_VARIANT (inst_ptr_basetype)) basetype = inst_ptr_basetype; else { - instance_ptr = convert (TYPE_POINTER_TO (basetype), instance_ptr); + instance_ptr = convert (build_pointer_type (basetype), instance_ptr); if (instance_ptr == error_mark_node) return error_mark_node; } @@ -1924,7 +1993,15 @@ build_method_call (instance, name, parms parmtypes = chainon (parmtypes, last); } - if (instance) + if (instance && IS_SIGNATURE (basetype)) + { + /* @@ Should this be the constp/volatilep flags for the optr field + of the signature pointer? */ + constp = TYPE_READONLY (basetype); + volatilep = TYPE_VOLATILE (basetype); + parms = tree_cons (NULL_TREE, instance_ptr, parms); + } + else if (instance) { /* TREE_READONLY (instance) fails for references. */ constp = TYPE_READONLY (TREE_TYPE (TREE_TYPE (instance_ptr))); @@ -1942,40 +2019,11 @@ build_method_call (instance, name, parms parmtypes = tree_cons (NULL_TREE, integer_type_node, parmtypes); } - if (flag_this_is_variable > 0) - { - constp = 0; - volatilep = 0; - parms = tree_cons (NULL_TREE, - build1 (NOP_EXPR, TYPE_POINTER_TO (basetype), - integer_zero_node), parms); - } - else - { - constp = 0; - volatilep = 0; - instance_ptr = build_new (NULL_TREE, basetype, void_type_node, 0); - if (instance_ptr == error_mark_node) - return error_mark_node; - instance_ptr = save_expr (instance_ptr); - TREE_CALLS_NEW (instance_ptr) = 1; - instance = build_indirect_ref (instance_ptr, NULL_PTR); - -#if 0 - /* This breaks initialization of a reference from a new - expression of a different type. And it doesn't appear to - serve its original purpose any more, either. jason 10/12/94 */ - /* If it's a default argument initialized from a ctor, what we get - from instance_ptr will match the arglist for the FUNCTION_DECL - of the constructor. */ - if (parms && TREE_CODE (TREE_VALUE (parms)) == CALL_EXPR - && TREE_OPERAND (TREE_VALUE (parms), 1) - && TREE_CALLS_NEW (TREE_VALUE (TREE_OPERAND (TREE_VALUE (parms), 1)))) - parms = build_tree_list (NULL_TREE, instance_ptr); - else -#endif - parms = tree_cons (NULL_TREE, instance_ptr, parms); - } + constp = 0; + volatilep = 0; + instance_ptr = build_int_2 (0, 0); + TREE_TYPE (instance_ptr) = build_pointer_type (basetype); + parms = tree_cons (NULL_TREE, instance_ptr, parms); } parmtypes = tree_cons (NULL_TREE, TREE_TYPE (instance_ptr), parmtypes); @@ -2075,25 +2123,14 @@ build_method_call (instance, name, parms tree parm = instance_ptr; if (TREE_CODE (TREE_TYPE (parm)) == REFERENCE_TYPE) - { - /* TREE_VALUE (parms) may have been modified by now; - restore it to its original value. */ - TREE_VALUE (parms) = parm; - friend_parms = parms; - } + parm = convert_from_reference (parm); else if (TREE_CODE (TREE_TYPE (parm)) == POINTER_TYPE) - { - tree new_type; - parm = build_indirect_ref (parm, "friendifying parms (compiler error)"); - new_type = cp_build_type_variant (TREE_TYPE (parm), constp, - volatilep); - new_type = build_reference_type (new_type); - parm = convert (new_type, parm); - friend_parms = tree_cons (NULL_TREE, parm, TREE_CHAIN (parms)); - } + parm = build_indirect_ref (parm, "friendifying parms (compiler error)"); else my_friendly_abort (167); + friend_parms = tree_cons (NULL_TREE, parm, TREE_CHAIN (parms)); + cp->h_len = len; cp->harshness = (struct harshness_code *) alloca ((len + 1) * sizeof (struct harshness_code)); @@ -2134,6 +2171,7 @@ build_method_call (instance, name, parms basetype_path = TREE_VALUE (basetype_path); basetype = BINFO_TYPE (basetype_path); +#if 0 /* Cast the instance variable if necessary. */ if (basetype != TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (TREE_VALUE (parms))))) @@ -2144,7 +2182,7 @@ build_method_call (instance, name, parms { tree type = build_pointer_type (build_type_variant (basetype, constp, volatilep)); - TREE_VALUE (parms) = convert_force (type, instance_ptr); + TREE_VALUE (parms) = convert_force (type, instance_ptr, 0); } } @@ -2152,6 +2190,7 @@ build_method_call (instance, name, parms the access-control rewrite will make this change more cleanly. */ if (TREE_VALUE (parms) == error_mark_node) return error_mark_node; +#endif if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (function))) function = DECL_CHAIN (function); @@ -2197,24 +2236,17 @@ build_method_call (instance, name, parms cp->function = function; cp->basetypes = basetype_path; + /* Don't allow non-converting constructors to convert. */ + if (flags & LOOKUP_ONLYCONVERTING + && DECL_LANG_SPECIFIC (function) + && DECL_NONCONVERTING_P (function)) + continue; + /* No "two-level" conversions. */ if (flags & LOOKUP_NO_CONVERSION && (cp->h.code & USER_CODE)) continue; - /* If we used default parameters, we must - check to see whether anyone else might - use them also, and report a possible - ambiguity. */ - if (! TYPE_USES_MULTIPLE_INHERITANCE (save_basetype) - && cp->harshness[len].distance == 0 - && cp->h.code < best) - { - if (! DECL_STATIC_FUNCTION_P (function)) - TREE_VALUE (parms) = cp->arg; - if (best == 1) - goto found_and_maybe_warn; - } cp++; } } @@ -2344,9 +2376,10 @@ build_method_call (instance, name, parms else if (ever_seen > 1) { TREE_CHAIN (last) = void_list_node; - cp_error ("no matching function for call to `%T::%D (%A)'", - TREE_TYPE (TREE_TYPE (instance_ptr)), - name, TREE_CHAIN (parmtypes)); + cp_error ("no matching function for call to `%T::%D (%A)%V'", + TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (instance_ptr))), + name, TREE_CHAIN (parmtypes), + TREE_TYPE (TREE_TYPE (instance_ptr))); TREE_CHAIN (last) = NULL_TREE; print_candidates (found_fns); } @@ -2434,6 +2467,19 @@ build_method_call (instance, name, parms /* Declare external function if necessary. */ assemble_external (function); +#if 1 + /* Is it a synthesized method that needs to be synthesized? */ + if (DECL_ARTIFICIAL (function) && ! flag_no_inline + && ! DECL_INITIAL (function) + /* Kludge: don't synthesize for default args. */ + && current_function_decl) + synthesize_method (function); +#endif + + if (pedantic && DECL_THIS_INLINE (function) && ! DECL_ARTIFICIAL (function) + && ! DECL_INITIAL (function) && ! DECL_PENDING_INLINE_INFO (function)) + cp_warning ("inline function `%#D' called before definition", function); + fntype = TREE_TYPE (function); if (TREE_CODE (fntype) == POINTER_TYPE) fntype = TREE_TYPE (fntype); @@ -2603,6 +2649,10 @@ build_method_call (instance, name, parms } #endif + if (parms == error_mark_node + || (parms && TREE_CHAIN (parms) == error_mark_node)) + return error_mark_node; + if (need_vtbl == needed) { function = build_vfn_ref (&TREE_VALUE (parms), instance, @@ -2620,14 +2670,8 @@ build_method_call (instance, name, parms if (TREE_CODE (function) == FUNCTION_DECL) { is_constructor = DECL_CONSTRUCTOR_P (function); - if (DECL_INLINE (function)) - function = build1 (ADDR_EXPR, build_pointer_type (fntype), function); - else - { - assemble_external (function); - TREE_USED (function) = 1; - function = default_conversion (function); - } + TREE_USED (function) = 1; + function = default_conversion (function); } else { @@ -2639,9 +2683,8 @@ build_method_call (instance, name, parms TREE_TYPE (result) = value_type; TREE_SIDE_EFFECTS (result) = 1; - TREE_RAISES (result) - = TYPE_RAISES_EXCEPTIONS (fntype) || (parms && TREE_RAISES (parms)); TREE_HAS_CONSTRUCTOR (result) = is_constructor; + result = convert_from_reference (result); return result; } }