diff options
Diffstat (limited to 'gcc/cp/call.c')
-rw-r--r-- | gcc/cp/call.c | 139 |
1 files changed, 126 insertions, 13 deletions
diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 4c19d2ffcd3..27aa7fdd74b 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -414,6 +414,7 @@ enum rejection_reason_code { rr_bad_arg_conversion, rr_template_unification, rr_invalid_copy, + rr_inherited_ctor, rr_constraint_failure }; @@ -689,6 +690,13 @@ invalid_copy_with_fn_template_rejection (void) return r; } +static struct rejection_reason * +inherited_ctor_rejection (void) +{ + struct rejection_reason *r = alloc_rejection (rr_inherited_ctor); + return r; +} + // Build a constraint failure record, saving information into the // template_instantiation field of the rejection. If FN is not a template // declaration, the TMPL member is the FN declaration and TARGS is empty. @@ -2111,6 +2119,18 @@ add_function_candidate (struct z_candidate **candidates, } } + /* Don't consider inherited constructors for initialization from an + expression of the same or derived type. */ + /* FIXME extend to operator=. */ + if (i == 0 && len == 1 + && DECL_INHERITED_CTOR (fn) + && reference_related_p (ctype, argtype)) + { + viable = 0; + reason = inherited_ctor_rejection (); + goto out; + } + /* Core issue 899: When [copy-]initializing a temporary to be bound to the first parameter of a copy constructor (12.8) called with a single argument in the context of direct-initialization, @@ -3393,32 +3413,40 @@ print_z_candidate (location_t loc, const char *msgstr, const char *msg = (msgstr == NULL ? "" : ACONCAT ((msgstr, " ", NULL))); - location_t cloc = location_of (candidate->fn); + tree fn = candidate->fn; + if (flag_new_inheriting_ctors) + fn = strip_inheriting_ctors (fn); + location_t cloc = location_of (fn); - if (identifier_p (candidate->fn)) + if (identifier_p (fn)) { cloc = loc; if (candidate->num_convs == 3) - inform (cloc, "%s%D(%T, %T, %T) <built-in>", msg, candidate->fn, + inform (cloc, "%s%D(%T, %T, %T) <built-in>", msg, fn, candidate->convs[0]->type, candidate->convs[1]->type, candidate->convs[2]->type); else if (candidate->num_convs == 2) - inform (cloc, "%s%D(%T, %T) <built-in>", msg, candidate->fn, + inform (cloc, "%s%D(%T, %T) <built-in>", msg, fn, candidate->convs[0]->type, candidate->convs[1]->type); else - inform (cloc, "%s%D(%T) <built-in>", msg, candidate->fn, + inform (cloc, "%s%D(%T) <built-in>", msg, fn, candidate->convs[0]->type); } - else if (TYPE_P (candidate->fn)) - inform (cloc, "%s%T <conversion>", msg, candidate->fn); + else if (TYPE_P (fn)) + inform (cloc, "%s%T <conversion>", msg, fn); else if (candidate->viable == -1) - inform (cloc, "%s%#D <near match>", msg, candidate->fn); - else if (DECL_DELETED_FN (candidate->fn)) - inform (cloc, "%s%#D <deleted>", msg, candidate->fn); + inform (cloc, "%s%#D <near match>", msg, fn); + else if (DECL_DELETED_FN (fn)) + inform (cloc, "%s%#D <deleted>", msg, fn); else - inform (cloc, "%s%#D", msg, candidate->fn); + inform (cloc, "%s%#D", msg, fn); + if (fn != candidate->fn) + { + cloc = location_of (candidate->fn); + inform (cloc, " inherited here"); + } /* Give the user some information about why this candidate failed. */ if (candidate->reason != NULL) { @@ -3483,6 +3511,11 @@ print_z_candidate (location_t loc, const char *msgstr, diagnose_constraints (cloc, tmpl, args); } break; + case rr_inherited_ctor: + inform (cloc, " an inherited constructor is not a candidate for " + "initialization from an expression of the same or derived " + "type"); + break; case rr_none: default: /* This candidate didn't have any issues or we failed to @@ -6338,10 +6371,22 @@ enforce_access (tree basetype_path, tree decl, tree diag_decl, { gcc_assert (TREE_CODE (basetype_path) == TREE_BINFO); + if (flag_new_inheriting_ctors + && DECL_INHERITED_CTOR (decl)) + { + /* 7.3.3/18: The additional constructors are accessible if they would be + accessible when used to construct an object of the corresponding base + class. */ + decl = strip_inheriting_ctors (decl); + basetype_path = TYPE_BINFO (DECL_CONTEXT (decl)); + } + if (!accessible_p (basetype_path, decl, true)) { if (complain & tf_error) { + if (flag_new_inheriting_ctors) + diag_decl = strip_inheriting_ctors (diag_decl); if (TREE_PRIVATE (decl)) { error ("%q#D is private within this context", diag_decl); @@ -6773,6 +6818,15 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum, if (! MAYBE_CLASS_TYPE_P (totype)) return expr; + + /* Don't introduce copies when passing arguments along to the inherited + constructor. */ + if (current_function_decl + && flag_new_inheriting_ctors + && DECL_INHERITED_CTOR (current_function_decl) + && TREE_ADDRESSABLE (totype)) + return expr; + /* Fall through. */ case ck_base: if (convs->kind == ck_base && !convs->need_temporary_p) @@ -7800,6 +7854,29 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain) check_function_arguments (input_location, TREE_TYPE (fn), nargs, fargs); } + if (DECL_INHERITED_CTOR (fn)) + { + /* Check for passing ellipsis arguments to an inherited constructor. We + could handle this by open-coding the inherited constructor rather than + defining it, but let's not bother now. */ + if (!cp_unevaluated_operand + && cand->convs[cand->num_convs-1]->ellipsis_p) + { + if (complain & tf_error) + { + sorry ("passing arguments to ellipsis of inherited constructor " + "%qD", cand->fn); + inform (DECL_SOURCE_LOCATION (cand->fn), "declared here"); + } + return error_mark_node; + } + + /* A base constructor inheriting from a virtual base doesn't get the + inherited arguments, just this and __vtt. */ + if (ctor_omit_inherited_parms (fn)) + nargs = 2; + } + /* Avoid actually calling copy constructors and copy assignment operators, if possible. */ @@ -7985,13 +8062,21 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain) } tree call = build_cxx_call (fn, nargs, argarray, complain|decltype_flag); - if (call != error_mark_node - && cand->flags & LOOKUP_LIST_INIT_CTOR) + if (call == error_mark_node) + return call; + if (cand->flags & LOOKUP_LIST_INIT_CTOR) { tree c = extract_call_expr (call); /* build_new_op_1 will clear this when appropriate. */ CALL_EXPR_ORDERED_ARGS (c) = true; } + if (current_function_decl + && flag_new_inheriting_ctors + && DECL_INHERITED_CTOR (current_function_decl) + && cand->num_convs) + /* Don't introduce copies when passing arguments along to the inherited + constructor. */ + CALL_FROM_THUNK_P (call) = true; return call; } @@ -9539,6 +9624,34 @@ joust (struct z_candidate *cand1, struct z_candidate *cand2, bool warn, return winner; } + /* or, if not that, F2 is from a using-declaration, F1 is not, and the + conversion sequences are equivalent. + (proposed in http://lists.isocpp.org/core/2016/10/1142.php) */ + if (DECL_P (cand1->fn) && DECL_CLASS_SCOPE_P (cand1->fn) + && !DECL_CONV_FN_P (cand1->fn) + && DECL_P (cand2->fn) && DECL_CLASS_SCOPE_P (cand2->fn) + && !DECL_CONV_FN_P (cand2->fn)) + { + bool used1 = (DECL_INHERITED_CTOR (cand1->fn) + || (BINFO_TYPE (cand1->access_path) + != DECL_CONTEXT (cand1->fn))); + bool used2 = (DECL_INHERITED_CTOR (cand2->fn) + || (BINFO_TYPE (cand2->access_path) + != DECL_CONTEXT (cand2->fn))); + if (int diff = used2 - used1) + { + for (i = 0; i < len; ++i) + { + conversion *t1 = cand1->convs[i + off1]; + conversion *t2 = cand2->convs[i + off2]; + if (!same_type_p (t1->type, t2->type)) + break; + } + if (i == len) + return diff; + } + } + /* Check whether we can discard a builtin candidate, either because we have two identical ones or matching builtin and non-builtin candidates. |