diff options
Diffstat (limited to 'gcc/cp/call.c')
-rw-r--r-- | gcc/cp/call.c | 98 |
1 files changed, 67 insertions, 31 deletions
diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 496cf91e17e..a931500d2d8 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -599,29 +599,6 @@ build_method_call (instance, name, parms, basetype_path, flags) return build_min_nt (METHOD_CALL_EXPR, name, instance, parms, NULL_TREE); } - /* This is the logic that magically deletes the second argument to - operator delete, if it is not needed. */ - if (name == ansi_opname[(int) DELETE_EXPR] && list_length (parms)==2) - { - tree save_last = TREE_CHAIN (parms); - - /* get rid of unneeded argument */ - TREE_CHAIN (parms) = NULL_TREE; - if (build_method_call (instance, name, parms, basetype_path, - (LOOKUP_SPECULATIVELY|flags) & ~LOOKUP_COMPLAIN)) - { - /* If it finds a match, return it. */ - 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; - } - /* We already know whether it's needed or not for vec delete. */ - else if (name == ansi_opname[(int) VEC_DELETE_EXPR] - && TYPE_LANG_SPECIFIC (TREE_TYPE (instance)) - && ! TYPE_VEC_DELETE_TAKES_SIZE (TREE_TYPE (instance))) - TREE_CHAIN (parms) = NULL_TREE; - if (TREE_CODE (name) == BIT_NOT_EXPR) { if (parms) @@ -1088,8 +1065,8 @@ add_function_candidate (candidates, fn, arglist, flags) tree parmnode, argnode; int viable = 1; - /* The `this' and `in_chrg' arguments to constructors are not considered - in overload resolution. */ + /* The `this', `in_chrg', and `vlist' arguments to constructors are + not considered in overload resolution. */ if (DECL_CONSTRUCTOR_P (fn)) { parmlist = TREE_CHAIN (parmlist); @@ -1099,6 +1076,22 @@ add_function_candidate (candidates, fn, arglist, flags) parmlist = TREE_CHAIN (parmlist); arglist = TREE_CHAIN (arglist); } + if ((flags & LOOKUP_HAS_VLIST) + && DECL_CONSTRUCTOR_FOR_PVBASE_P (fn)) + { + parmlist = TREE_CHAIN (parmlist); + arglist = TREE_CHAIN (arglist); + } + else if (!(flags & LOOKUP_HAS_VLIST) + && !DECL_CONSTRUCTOR_FOR_PVBASE_P (fn)) + /* Ok */; + else + { + /* The ctor expects a vlist and the arguments don't have + one, or vice versa, so fn is not even a candidate, since + the corresponding ctor would be the candidate. */ + return candidates; + } } len = list_length (arglist); @@ -2094,6 +2087,11 @@ build_user_type_conversion_1 (totype, expr, flags) tree t = build_int_2 (0, 0); TREE_TYPE (t) = build_pointer_type (totype); args = build_scratch_list (NULL_TREE, expr); + if (TYPE_USES_PVBASES (totype) && !flag_vtable_thunks_compat) + { + args = scratch_tree_cons (NULL_TREE, vlist_zero_node, args); + flags |= LOOKUP_HAS_VLIST; + } if (TYPE_USES_VIRTUAL_BASECLASSES (totype)) args = scratch_tree_cons (NULL_TREE, integer_one_node, args); args = scratch_tree_cons (NULL_TREE, t, args); @@ -2461,7 +2459,11 @@ build_object_call (obj, args) return error_mark_node; } - if (DECL_NAME (cand->fn) == ansi_opname [CALL_EXPR]) + /* Since cand->fn will be a type, not a function, for a conversion + function, we must be careful not to unconditionally look at + DECL_NAME here. */ + if (TREE_CODE (cand->fn) == FUNCTION_DECL + && DECL_NAME (cand->fn) == ansi_opname [CALL_EXPR]) return build_over_call (cand, mem_args, LOOKUP_NORMAL); obj = convert_like (TREE_VEC_ELT (cand->convs, 0), obj); @@ -2776,9 +2778,19 @@ build_new_op (code, flags, arg1, arg2, arg3) conv = TREE_OPERAND (conv, 0); arg1 = convert_like (conv, arg1); if (arg2) - arg2 = convert_like (TREE_VEC_ELT (cand->convs, 1), arg2); + { + conv = TREE_VEC_ELT (cand->convs, 1); + if (TREE_CODE (conv) == REF_BIND) + conv = TREE_OPERAND (conv, 0); + arg2 = convert_like (conv, arg2); + } if (arg3) - arg3 = convert_like (TREE_VEC_ELT (cand->convs, 2), arg3); + { + conv = TREE_VEC_ELT (cand->convs, 2); + if (TREE_CODE (conv) == REF_BIND) + conv = TREE_OPERAND (conv, 0); + arg3 = convert_like (conv, arg3); + } builtin: switch (code) @@ -3047,6 +3059,7 @@ convert_like (convs, expr) = WRAPPER_PTR (TREE_OPERAND (convs, 1)); tree fn = cand->fn; tree args; + int flags = LOOKUP_NORMAL; if (DECL_CONSTRUCTOR_P (fn)) { @@ -3054,13 +3067,19 @@ convert_like (convs, expr) TREE_TYPE (t) = build_pointer_type (DECL_CONTEXT (fn)); args = build_scratch_list (NULL_TREE, expr); + if (TYPE_USES_PVBASES (DECL_CONTEXT (fn)) + && !flag_vtable_thunks_compat) + { + args = scratch_tree_cons (NULL_TREE, vlist_zero_node, args); + flags != LOOKUP_HAS_VLIST; + } if (TYPE_USES_VIRTUAL_BASECLASSES (DECL_CONTEXT (fn))) args = scratch_tree_cons (NULL_TREE, integer_one_node, args); args = scratch_tree_cons (NULL_TREE, t, args); } else args = build_this (expr); - expr = build_over_call (cand, args, LOOKUP_NORMAL); + expr = build_over_call (cand, args, flags); /* If this is a constructor or a function returning an aggr type, we need to build up a TARGET_EXPR. */ @@ -3269,6 +3288,13 @@ build_over_call (cand, args, flags) arg = TREE_CHAIN (arg); parm = TREE_CHAIN (parm); } + if (flags & LOOKUP_HAS_VLIST) + { + converted_args = expr_tree_cons + (NULL_TREE, TREE_VALUE (arg), converted_args); + arg = TREE_CHAIN (arg); + parm = TREE_CHAIN (parm); + } } /* Bypass access control for 'this' parameter. */ else if (TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE) @@ -3378,6 +3404,8 @@ build_over_call (cand, args, flags) arg = TREE_CHAIN (converted_args); if (TYPE_USES_VIRTUAL_BASECLASSES (DECL_CONTEXT (fn))) arg = TREE_CHAIN (arg); + if (flags & LOOKUP_HAS_VLIST) + arg = TREE_CHAIN (arg); arg = TREE_VALUE (arg); /* Pull out the real argument, disregarding const-correctness. */ @@ -3553,6 +3581,8 @@ build_new_method_call (instance, name, args, basetype_path, flags) remove it for error reporting. */ if (flags & LOOKUP_HAS_IN_CHARGE) user_args = TREE_CHAIN (args); + if (flags & LOOKUP_HAS_VLIST) + user_args = TREE_CHAIN (user_args); args = resolve_args (args); @@ -3625,6 +3655,12 @@ build_new_method_call (instance, name, args, basetype_path, flags) if (name == ctor_identifier && TYPE_USES_VIRTUAL_BASECLASSES (basetype) && ! (flags & LOOKUP_HAS_IN_CHARGE)) { + if (TYPE_USES_PVBASES(basetype) + && (!flag_vtable_thunks_compat || (name == dtor_identifier))) + { + args = scratch_tree_cons (NULL_TREE, vlist_zero_node, args); + flags |= LOOKUP_HAS_VLIST; + } flags |= LOOKUP_HAS_IN_CHARGE; args = scratch_tree_cons (NULL_TREE, integer_one_node, args); } @@ -4341,8 +4377,8 @@ joust (cand1, cand2, warn) != DECL_CONSTRUCTOR_P (cand2->fn)) /* Don't warn if the two conv ops convert to the same type... */ || (! DECL_CONSTRUCTOR_P (cand1->fn) - && ! same_type_p (TREE_TYPE (cand1->second_conv), - TREE_TYPE (cand2->second_conv))))) + && ! same_type_p (TREE_TYPE (TREE_TYPE (cand1->fn)), + TREE_TYPE (TREE_TYPE (cand2->fn)))))) { int comp = compare_ics (cand1->second_conv, cand2->second_conv); if (comp != winner) |