diff options
author | Jason Merrill <jason@redhat.com> | 2016-11-01 21:50:29 -0400 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2016-11-01 21:50:29 -0400 |
commit | 31f7f784fe7fa68bca218df43ec8965569d6cb5d (patch) | |
tree | 1dffc88ff5b0ae93ef01f8ea3bba2713ee747362 /gcc/cp | |
parent | be9f7afb32b8cf2dfb6d08f86804b6eabd30c838 (diff) | |
download | gcc-31f7f784fe7fa68bca218df43ec8965569d6cb5d.zip gcc-31f7f784fe7fa68bca218df43ec8965569d6cb5d.tar.gz gcc-31f7f784fe7fa68bca218df43ec8965569d6cb5d.tar.bz2 |
Implement P0136R1, Rewording inheriting constructors.
gcc/c-family/
* c.opt (-fnew-inheriting-ctors): New.
* c-opts.c: Default to on for ABI 11+.
gcc/cp/
* call.c (enum rejection_reason_code): Add rr_inherited_ctor.
(inherited_ctor_rejection): New.
(add_function_candidate): Reject inherited ctors for copying.
(enforce_access): Use strip_inheriting_ctors.
(print_z_candidate): Likewise. Handle rr_inherited_ctor.
(convert_like_real): Avoid copying inheriting ctor parameters.
(build_over_call): Likewise. A base ctor inheriting from vbase
has no parms. Sorry about varargs.
(joust): A local constructor beats inherited with the same convs.
* class.c (add_method): Handle hiding inheriting ctors.
(one_inherited_ctor): Handle new semantics.
(add_implicitly_declared_members): Pass using_decl down.
(build_clone): A base ctor inheriting from vbase has no parms.
* cp-tree.h (DECL_INHERITED_CTOR): Store this instead of the base.
(SET_DECL_INHERITED_CTOR): Likewise.
(DECL_INHERITED_CTOR_BASE): Adjust.
* constexpr.c: Adjust.
* error.c (dump_function_decl): Decorate inheriting ctors.
* init.c (emit_mem_initializers): Suppress access control in
inheriting ctor.
* mangle.c (write_special_name_constructor): Handle new inheriting
ctor mangling.
* method.c (strip_inheriting_ctors, inherited_ctor_binfo)
(ctor_omit_inherited_parms, binfo_inherited_from): New.
(synthesized_method_walk): Use binfo_inherited_from. Suppress
access control in inheriting ctor.
(deduce_inheriting_ctor): Deleted if ambiguous ctor inheritance.
(maybe_explain_implicit_delete): Explain ambigous ctor inheritance.
(add_one_base_init, do_build_copy_constructor): Adjust.
(locate_fn_flags, explain_implicit_non_constexpr): Adjust.
(implicitly_declare_fn): Adjust.
(get_inherited_ctor): Remove.
* name-lookup.c (do_class_using_decl): Check for indirect ctor
inheritance.
* optimize.c (cdtor_comdat_group): Adjust for new mangling.
(maybe_clone_body): Handle omitted parms in base clone.
(maybe_thunk_body): Don't thunk if base clone omits parms.
* pt.c (tsubst_decl): Adjust.
(instantiate_template_1): Suppress access control in inheriting
ctor.
(fn_type_unification): Do deduction with inherited ctor.
* tree.c (special_function_p): Adjust.
gcc/
* tree-inline.c (copy_tree_body_r): Only copy the taken branch of
a COND_EXPR with constant condition.
libiberty/
* cp-demangle.c (d_ctor_dtor_name): Handle inheriting constructor.
From-SVN: r241765
Diffstat (limited to 'gcc/cp')
-rw-r--r-- | gcc/cp/ChangeLog | 46 | ||||
-rw-r--r-- | gcc/cp/call.c | 139 | ||||
-rw-r--r-- | gcc/cp/class.c | 79 | ||||
-rw-r--r-- | gcc/cp/constexpr.c | 4 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 21 | ||||
-rw-r--r-- | gcc/cp/error.c | 7 | ||||
-rw-r--r-- | gcc/cp/init.c | 12 | ||||
-rw-r--r-- | gcc/cp/mangle.c | 13 | ||||
-rw-r--r-- | gcc/cp/method.c | 215 | ||||
-rw-r--r-- | gcc/cp/name-lookup.c | 6 | ||||
-rw-r--r-- | gcc/cp/optimize.c | 13 | ||||
-rw-r--r-- | gcc/cp/pt.c | 27 | ||||
-rw-r--r-- | gcc/cp/tree.c | 2 |
13 files changed, 493 insertions, 91 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index d9ea36b..5eabdc2 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,49 @@ +2016-11-01 Jason Merrill <jason@redhat.com> + + Implement P0136R1, Rewording inheriting constructors. + * call.c (enum rejection_reason_code): Add rr_inherited_ctor. + (inherited_ctor_rejection): New. + (add_function_candidate): Reject inherited ctors for copying. + (enforce_access): Use strip_inheriting_ctors. + (print_z_candidate): Likewise. Handle rr_inherited_ctor. + (convert_like_real): Avoid copying inheriting ctor parameters. + (build_over_call): Likewise. A base ctor inheriting from vbase + has no parms. Sorry about varargs. + (joust): A local constructor beats inherited with the same convs. + * class.c (add_method): Handle hiding inheriting ctors. + (one_inherited_ctor): Handle new semantics. + (add_implicitly_declared_members): Pass using_decl down. + (build_clone): A base ctor inheriting from vbase has no parms. + * cp-tree.h (DECL_INHERITED_CTOR): Store this instead of the base. + (SET_DECL_INHERITED_CTOR): Likewise. + (DECL_INHERITED_CTOR_BASE): Adjust. + * constexpr.c: Adjust. + * error.c (dump_function_decl): Decorate inheriting ctors. + * init.c (emit_mem_initializers): Suppress access control in + inheriting ctor. + * mangle.c (write_special_name_constructor): Handle new inheriting + ctor mangling. + * method.c (strip_inheriting_ctors, inherited_ctor_binfo) + (ctor_omit_inherited_parms, binfo_inherited_from): New. + (synthesized_method_walk): Use binfo_inherited_from. Suppress + access control in inheriting ctor. + (deduce_inheriting_ctor): Deleted if ambiguous ctor inheritance. + (maybe_explain_implicit_delete): Explain ambigous ctor inheritance. + (add_one_base_init, do_build_copy_constructor): Adjust. + (locate_fn_flags, explain_implicit_non_constexpr): Adjust. + (implicitly_declare_fn): Adjust. + (get_inherited_ctor): Remove. + * name-lookup.c (do_class_using_decl): Check for indirect ctor + inheritance. + * optimize.c (cdtor_comdat_group): Adjust for new mangling. + (maybe_clone_body): Handle omitted parms in base clone. + (maybe_thunk_body): Don't thunk if base clone omits parms. + * pt.c (tsubst_decl): Adjust. + (instantiate_template_1): Suppress access control in inheriting + ctor. + (fn_type_unification): Do deduction with inherited ctor. + * tree.c (special_function_p): Adjust. + 2016-11-01 Jakub Jelinek <jakub@redhat.com> * cp-objcp-common.c (cp_decl_dwarf_attribute): Handle DW_AT_inline. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 4c19d2f..27aa7fd 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. diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 1a37934..c6b4ed6 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -1016,7 +1016,6 @@ add_method (tree type, tree method, tree using_decl) bool complete_p; bool insert_p = false; tree current_fns; - tree fns; if (method == error_mark_node) return false; @@ -1083,8 +1082,9 @@ add_method (tree type, tree method, tree using_decl) current_fns = insert_p ? NULL_TREE : (*method_vec)[slot]; /* Check to see if we've already got this method. */ - for (fns = current_fns; fns; fns = OVL_NEXT (fns)) + for (tree *p = ¤t_fns; *p; ) { + tree fns = *p; tree fn = OVL_CURRENT (fns); tree fn_type; tree method_type; @@ -1092,12 +1092,14 @@ add_method (tree type, tree method, tree using_decl) tree parms2; if (TREE_CODE (fn) != TREE_CODE (method)) - continue; + goto cont; /* Two using-declarations can coexist, we'll complain about ambiguity in overload resolution. */ - if (using_decl && TREE_CODE (fns) == OVERLOAD && OVL_USED (fns)) - continue; + if (using_decl && TREE_CODE (fns) == OVERLOAD && OVL_USED (fns) + /* Except handle inherited constructors specially. */ + && ! DECL_CONSTRUCTOR_P (fn)) + goto cont; /* [over.load] Member function declarations with the same name and the same parameter types cannot be @@ -1131,7 +1133,7 @@ add_method (tree type, tree method, tree using_decl) == FUNCTION_REF_QUALIFIED (method_type)) && (type_memfn_quals (fn_type) != type_memfn_quals (method_type) || type_memfn_rqual (fn_type) != type_memfn_rqual (method_type))) - continue; + goto cont; /* For templates, the return type and template parameters must be identical. */ @@ -1140,7 +1142,7 @@ add_method (tree type, tree method, tree using_decl) TREE_TYPE (method_type)) || !comp_template_parms (DECL_TEMPLATE_PARMS (fn), DECL_TEMPLATE_PARMS (method)))) - continue; + goto cont; if (! DECL_STATIC_FUNCTION_P (fn)) parms1 = TREE_CHAIN (parms1); @@ -1178,18 +1180,38 @@ add_method (tree type, tree method, tree using_decl) mangle_decl (method); } cgraph_node::record_function_versions (fn, method); - continue; + goto cont; } - if (DECL_INHERITED_CTOR_BASE (method)) + if (DECL_INHERITED_CTOR (method)) { - if (DECL_INHERITED_CTOR_BASE (fn)) + if (DECL_INHERITED_CTOR (fn)) { + tree basem = DECL_INHERITED_CTOR_BASE (method); + tree basef = DECL_INHERITED_CTOR_BASE (fn); + if (flag_new_inheriting_ctors) + { + if (basem == basef) + { + /* Inheriting the same constructor along different + paths, combine them. */ + SET_DECL_INHERITED_CTOR + (fn, ovl_cons (DECL_INHERITED_CTOR (method), + DECL_INHERITED_CTOR (fn))); + /* Adjust deletedness and such. */ + deduce_inheriting_ctor (fn); + /* And discard the new one. */ + return false; + } + else + /* Inherited ctors can coexist until overload + resolution. */ + goto cont; + } error_at (DECL_SOURCE_LOCATION (method), - "%q#D inherited from %qT", method, - DECL_INHERITED_CTOR_BASE (method)); + "%q#D", method); error_at (DECL_SOURCE_LOCATION (fn), "conflicts with version inherited from %qT", - DECL_INHERITED_CTOR_BASE (fn)); + basef); } /* Otherwise defer to the other function. */ return false; @@ -1200,6 +1222,13 @@ add_method (tree type, tree method, tree using_decl) /* Defer to the local function. */ return false; } + else if (flag_new_inheriting_ctors + && DECL_INHERITED_CTOR (fn)) + { + /* Hide the inherited constructor. */ + *p = OVL_NEXT (fns); + continue; + } else { error ("%q+#D cannot be overloaded", method); @@ -1212,6 +1241,12 @@ add_method (tree type, tree method, tree using_decl) will crash while processing the definitions. */ return false; } + + cont: + if (TREE_CODE (fns) == OVERLOAD) + p = &OVL_CHAIN (fns); + else + break; } /* A class should never have more than one destructor. */ @@ -3308,10 +3343,19 @@ one_inheriting_sig (tree t, tree ctor, tree *parms, int nparms) constructor CTOR. */ static void -one_inherited_ctor (tree ctor, tree t) +one_inherited_ctor (tree ctor, tree t, tree using_decl) { tree parms = FUNCTION_FIRST_USER_PARMTYPE (ctor); + if (flag_new_inheriting_ctors) + { + ctor = implicitly_declare_fn (sfk_inheriting_constructor, + t, /*const*/false, ctor, parms); + add_method (t, ctor, using_decl); + TYPE_HAS_USER_CONSTRUCTOR (t) = true; + return; + } + tree *new_parms = XALLOCAVEC (tree, list_length (parms)); int i = 0; for (; parms && parms != void_list_node; parms = TREE_CHAIN (parms)) @@ -3412,7 +3456,7 @@ add_implicitly_declared_members (tree t, tree* access_decls, input_location = DECL_SOURCE_LOCATION (using_decl); if (ctor_list) for (; ctor_list; ctor_list = OVL_NEXT (ctor_list)) - one_inherited_ctor (OVL_CURRENT (ctor_list), t); + one_inherited_ctor (OVL_CURRENT (ctor_list), t, using_decl); *access_decls = TREE_CHAIN (*access_decls); input_location = loc; } @@ -4772,6 +4816,11 @@ build_clone (tree fn, tree name) } } + /* A base constructor inheriting from a virtual base doesn't get the + arguments. */ + if (ctor_omit_inherited_parms (fn)) + DECL_CHAIN (DECL_CHAIN (DECL_ARGUMENTS (clone))) = NULL_TREE; + for (parms = DECL_ARGUMENTS (clone); parms; parms = DECL_CHAIN (parms)) { DECL_CONTEXT (parms) = clone; diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index 1ebd647..43457d2 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -171,13 +171,13 @@ is_valid_constexpr_fn (tree fun, bool complain) { bool ret = true; - if (DECL_INHERITED_CTOR_BASE (fun) + if (DECL_INHERITED_CTOR (fun) && TREE_CODE (fun) == TEMPLATE_DECL) { ret = false; if (complain) error ("inherited constructor %qD is not constexpr", - get_inherited_ctor (fun)); + DECL_INHERITED_CTOR (fun)); } else { diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 45224dc..d3a5aeb 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -2730,12 +2730,21 @@ struct GTY(()) lang_decl { (LANG_DECL_FN_CHECK (NODE)->context = (THUNKS)) /* If NODE, a FUNCTION_DECL, is a C++11 inheriting constructor, then this - is the base it inherits from. */ -#define DECL_INHERITED_CTOR_BASE(NODE) \ - (DECL_CONSTRUCTOR_P (NODE) ? LANG_DECL_FN_CHECK (NODE)->context : NULL_TREE) + is the constructor it inherits from. */ +#define DECL_INHERITED_CTOR(NODE) \ + (DECL_DECLARES_FUNCTION_P (NODE) && DECL_CONSTRUCTOR_P (NODE) \ + ? LANG_DECL_FN_CHECK (NODE)->context : NULL_TREE) + +/* And this is the base that constructor comes from. */ +#define DECL_INHERITED_CTOR_BASE(NODE) \ + (DECL_INHERITED_CTOR (NODE) \ + ? DECL_CONTEXT (flag_new_inheriting_ctors \ + ? strip_inheriting_ctors (NODE) \ + : DECL_INHERITED_CTOR (NODE)) \ + : NULL_TREE) /* Set the inherited base. */ -#define SET_DECL_INHERITED_CTOR_BASE(NODE,INH) \ +#define SET_DECL_INHERITED_CTOR(NODE,INH) \ (LANG_DECL_FN_CHECK (NODE)->context = (INH)) /* Nonzero if NODE is a thunk, rather than an ordinary function. */ @@ -6036,7 +6045,9 @@ extern tree get_copy_ctor (tree, tsubst_flags_t); extern tree get_copy_assign (tree); extern tree get_default_ctor (tree); extern tree get_dtor (tree, tsubst_flags_t); -extern tree get_inherited_ctor (tree); +extern tree strip_inheriting_ctors (tree); +extern tree inherited_ctor_binfo (tree); +extern bool ctor_omit_inherited_parms (tree); extern tree locate_ctor (tree); extern tree implicitly_declare_fn (special_function_kind, tree, bool, tree, tree); diff --git a/gcc/cp/error.c b/gcc/cp/error.c index 917a448..aa92a7e 100644 --- a/gcc/cp/error.c +++ b/gcc/cp/error.c @@ -1617,6 +1617,13 @@ dump_function_decl (cxx_pretty_printer *pp, tree t, int flags) pp_cxx_requires_clause (pp, reqs); dump_substitution (pp, t, template_parms, template_args, flags); + + if (tree base = DECL_INHERITED_CTOR_BASE (t)) + { + pp_cxx_ws_string (pp, "[inherited from"); + dump_type (pp, base, TFF_PLAIN_IDENTIFIER); + pp_character (pp, ']'); + } } else if (template_args) { diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 2418a9d..5eba4c3 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -1117,7 +1117,7 @@ emit_mem_initializers (tree mem_inits) } if (DECL_DEFAULTED_FN (current_function_decl) - && ! DECL_INHERITED_CTOR_BASE (current_function_decl)) + && ! DECL_INHERITED_CTOR (current_function_decl)) flags |= LOOKUP_DEFAULTED; /* Sort the mem-initializers into the order in which the @@ -1138,6 +1138,13 @@ emit_mem_initializers (tree mem_inits) if (arguments == error_mark_node) continue; + /* Suppress access control when calling the inherited ctor. */ + bool inherited_base = (DECL_INHERITED_CTOR (current_function_decl) + && flag_new_inheriting_ctors + && arguments); + if (inherited_base) + push_deferring_access_checks (dk_deferred); + if (arguments == NULL_TREE) { /* If these initializations are taking place in a copy constructor, @@ -1172,6 +1179,9 @@ emit_mem_initializers (tree mem_inits) /* C++14 DR1658 Means we do not have to construct vbases of abstract classes. */ construct_virtual_base (subobject, arguments); + + if (inherited_base) + pop_deferring_access_checks (); } in_base_initializer = 0; diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c index cb2f260..f3b2fe3 100644 --- a/gcc/cp/mangle.c +++ b/gcc/cp/mangle.c @@ -1786,18 +1786,25 @@ write_identifier (const char *identifier) static void write_special_name_constructor (const tree ctor) { + write_char ('C'); + bool new_inh = (flag_new_inheriting_ctors + && DECL_INHERITED_CTOR (ctor)); + if (new_inh) + write_char ('I'); if (DECL_BASE_CONSTRUCTOR_P (ctor)) - write_string ("C2"); + write_char ('2'); /* This is the old-style "[unified]" constructor. In some cases, we may emit this function and call it from the clones in order to share code and save space. */ else if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (ctor)) - write_string ("C4"); + write_char ('4'); else { gcc_assert (DECL_COMPLETE_CONSTRUCTOR_P (ctor)); - write_string ("C1"); + write_char ('1'); } + if (new_inh) + write_type (DECL_INHERITED_CTOR_BASE (ctor)); } /* Handle destructor productions of non-terminal <special-name>. diff --git a/gcc/cp/method.c b/gcc/cp/method.c index 73a670b..73d42b1 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -492,6 +492,118 @@ forward_parm (tree parm) return exp; } +/* Strip all inheriting constructors, if any, to return the original + constructor from a (possibly indirect) base class. */ + +tree +strip_inheriting_ctors (tree fn) +{ + gcc_assert (flag_new_inheriting_ctors); + while (tree inh = DECL_INHERITED_CTOR (fn)) + { + inh = OVL_CURRENT (inh); + fn = inh; + } + return fn; +} + +/* Find the binfo for the base subobject of BINFO being initialized by + inherited constructor FNDECL (a member of a direct base of BINFO). */ + +static tree inherited_ctor_binfo (tree, tree); +static tree +inherited_ctor_binfo_1 (tree binfo, tree fndecl) +{ + tree base = DECL_CONTEXT (fndecl); + tree base_binfo; + for (int i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++) + if (BINFO_TYPE (base_binfo) == base) + return inherited_ctor_binfo (base_binfo, fndecl); + + gcc_unreachable(); +} + +/* Find the binfo for the base subobject of BINFO being initialized by + inheriting constructor FNDECL (a member of BINFO), or BINFO if FNDECL is not + an inheriting constructor. */ + +static tree +inherited_ctor_binfo (tree binfo, tree fndecl) +{ + tree inh = DECL_INHERITED_CTOR (fndecl); + if (!inh) + return binfo; + + tree results = NULL_TREE; + for (; inh; inh = OVL_NEXT (inh)) + { + tree one = inherited_ctor_binfo_1 (binfo, OVL_CURRENT (inh)); + if (!results) + results = one; + else if (one != results) + results = tree_cons (NULL_TREE, one, results); + } + return results; +} + +/* Find the binfo for the base subobject being initialized by inheriting + constructor FNDECL, or NULL_TREE if FNDECL is not an inheriting + constructor. */ + +tree +inherited_ctor_binfo (tree fndecl) +{ + if (!DECL_INHERITED_CTOR (fndecl)) + return NULL_TREE; + tree binfo = TYPE_BINFO (DECL_CONTEXT (fndecl)); + return inherited_ctor_binfo (binfo, fndecl); +} + +/* True if we should omit all user-declared parameters from constructor FN, + because it is a base clone of a ctor inherited from a virtual base. */ + +bool +ctor_omit_inherited_parms (tree fn) +{ + if (!flag_new_inheriting_ctors) + /* We only optimize away the parameters in the new model. */ + return false; + if (!DECL_BASE_CONSTRUCTOR_P (fn) + || !CLASSTYPE_VBASECLASSES (DECL_CONTEXT (fn))) + return false; + tree binfo = inherited_ctor_binfo (fn); + for (; binfo; binfo = BINFO_INHERITANCE_CHAIN (binfo)) + if (BINFO_VIRTUAL_P (binfo)) + return true; + return false; +} + +/* True iff constructor(s) INH inherited into BINFO initializes INIT_BINFO. + This can be true for multiple virtual bases as well as one direct + non-virtual base. */ + +static bool +binfo_inherited_from (tree binfo, tree init_binfo, tree inh) +{ + /* inh is an OVERLOAD if we inherited the same constructor along + multiple paths, check all of them. */ + for (; inh; inh = OVL_NEXT (inh)) + { + tree fn = OVL_CURRENT (inh); + tree base = DECL_CONTEXT (fn); + tree base_binfo = NULL_TREE; + for (int i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++) + if (BINFO_TYPE (base_binfo) == base) + break; + if (base_binfo == init_binfo + || (flag_new_inheriting_ctors + && binfo_inherited_from (base_binfo, init_binfo, + DECL_INHERITED_CTOR (fn)))) + return true; + } + return false; +} + /* Subroutine of do_build_copy_constructor: Add a mem-initializer for BINFO given the parameter or parameters PARM, possibly inherited constructor base INH, or move flag MOVE_P. */ @@ -505,7 +617,7 @@ add_one_base_init (tree binfo, tree parm, bool move_p, tree inh, { /* An inheriting constructor only has a mem-initializer for the base it inherits from. */ - if (BINFO_TYPE (binfo) != inh) + if (!binfo_inherited_from (TYPE_BINFO (current_class_type), binfo, inh)) return member_init_list; tree *p = &init; @@ -537,7 +649,7 @@ do_build_copy_constructor (tree fndecl) tree parm = FUNCTION_FIRST_USER_PARM (fndecl); bool move_p = DECL_MOVE_CONSTRUCTOR_P (fndecl); bool trivial = trivial_fn_p (fndecl); - tree inh = DECL_INHERITED_CTOR_BASE (fndecl); + tree inh = DECL_INHERITED_CTOR (fndecl); if (!inh) parm = convert_from_reference (parm); @@ -901,7 +1013,7 @@ locate_fn_flags (tree type, tree name, tree argtype, int flags, { if (TREE_CODE (argtype) == TREE_LIST) { - for (tree elt = argtype; elt != void_list_node; + for (tree elt = argtype; elt && elt != void_list_node; elt = TREE_CHAIN (elt)) { tree type = TREE_VALUE (elt); @@ -996,25 +1108,6 @@ get_copy_assign (tree type) return fn; } -/* Locate the inherited constructor of constructor CTOR. */ - -tree -get_inherited_ctor (tree ctor) -{ - gcc_assert (DECL_INHERITED_CTOR_BASE (ctor)); - - push_deferring_access_checks (dk_no_check); - tree fn = locate_fn_flags (DECL_INHERITED_CTOR_BASE (ctor), - complete_ctor_identifier, - FUNCTION_FIRST_USER_PARMTYPE (ctor), - LOOKUP_NORMAL|LOOKUP_SPECULATIVE, - tf_none); - pop_deferring_access_checks (); - if (fn == error_mark_node) - return NULL_TREE; - return fn; -} - /* walk_tree helper function for is_trivially_xible. If *TP is a call, return it if it calls something other than a trivial special member function. */ @@ -1330,7 +1423,7 @@ static void synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p, tree *spec_p, bool *trivial_p, bool *deleted_p, bool *constexpr_p, bool diag, - tree inherited_base, tree inherited_parms) + tree inheriting_ctor, tree inherited_parms) { tree binfo, base_binfo, scope, fnname, rval, argtype; bool move_p, copy_arg_p, assign_p, expected_trivial, check_vdtor; @@ -1389,7 +1482,7 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p, } gcc_assert ((sfk == sfk_inheriting_constructor) - == (inherited_base != NULL_TREE)); + == (inheriting_ctor != NULL_TREE)); /* If that user-written default constructor would satisfy the requirements of a constexpr constructor (7.1.5), the @@ -1465,7 +1558,7 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p, scope = push_scope (ctype); flags = LOOKUP_NORMAL|LOOKUP_SPECULATIVE; - if (!inherited_base) + if (!inheriting_ctor) flags |= LOOKUP_DEFAULTED; complain = diag ? tf_warning_or_error : tf_none; @@ -1485,13 +1578,25 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p, /* We'll handle virtual bases below. */ continue; + bool inherited_binfo = false; + if (copy_arg_p) argtype = build_stub_type (basetype, quals, move_p); - else if (basetype == inherited_base) - argtype = inherited_parms; + else if ((inherited_binfo + = binfo_inherited_from (binfo, base_binfo, inheriting_ctor))) + { + /* Don't check access on the inherited constructor. */ + argtype = inherited_parms; + if (flag_new_inheriting_ctors) + push_deferring_access_checks (dk_deferred); + } rval = locate_fn_flags (base_binfo, fnname, argtype, flags, complain); - if (inherited_base) - argtype = NULL_TREE; + if (inherited_binfo) + { + if (flag_new_inheriting_ctors) + pop_deferring_access_checks (); + argtype = NULL_TREE; + } process_subob_fn (rval, spec_p, trivial_p, deleted_p, constexpr_p, diag, basetype); @@ -1547,9 +1652,24 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p, FOR_EACH_VEC_ELT (*vbases, i, base_binfo) { tree basetype = BINFO_TYPE (base_binfo); + bool inherited_binfo = false; + if (copy_arg_p) argtype = build_stub_type (basetype, quals, move_p); + else if ((inherited_binfo + = binfo_inherited_from (binfo, base_binfo, inheriting_ctor))) + { + argtype = inherited_parms; + if (flag_new_inheriting_ctors) + push_deferring_access_checks (dk_deferred); + } rval = locate_fn_flags (base_binfo, fnname, argtype, flags, complain); + if (inherited_binfo) + { + if (flag_new_inheriting_ctors) + pop_deferring_access_checks (); + argtype = NULL_TREE; + } process_subob_fn (rval, spec_p, trivial_p, deleted_p, constexpr_p, diag, basetype); @@ -1598,7 +1718,7 @@ get_defaulted_eh_spec (tree decl) bool const_p = CP_TYPE_CONST_P (non_reference (parm_type)); tree spec = empty_except_spec; synthesized_method_walk (ctype, sfk, const_p, &spec, NULL, NULL, - NULL, false, DECL_INHERITED_CTOR_BASE (decl), + NULL, false, DECL_INHERITED_CTOR (decl), parms); return spec; } @@ -1657,6 +1777,17 @@ maybe_explain_implicit_delete (tree decl) decl, ctype); informed = true; } + else if (sfk == sfk_inheriting_constructor) + { + tree binfo = inherited_ctor_binfo (decl); + if (TREE_CODE (binfo) != TREE_BINFO) + { + inform (DECL_SOURCE_LOCATION (decl), + "%q#D inherits from multiple base subobjects", + decl); + informed = true; + } + } if (!informed) { tree parms = FUNCTION_FIRST_USER_PARMTYPE (decl); @@ -1668,7 +1799,7 @@ maybe_explain_implicit_delete (tree decl) synthesized_method_walk (ctype, sfk, const_p, &raises, NULL, &deleted_p, NULL, false, - DECL_INHERITED_CTOR_BASE (decl), parms); + DECL_INHERITED_CTOR (decl), parms); if (deleted_p) { inform (DECL_SOURCE_LOCATION (decl), @@ -1676,7 +1807,7 @@ maybe_explain_implicit_delete (tree decl) "definition would be ill-formed:", decl); synthesized_method_walk (ctype, sfk, const_p, NULL, NULL, NULL, NULL, true, - DECL_INHERITED_CTOR_BASE (decl), parms); + DECL_INHERITED_CTOR (decl), parms); } else if (!comp_except_specs (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (decl)), @@ -1709,7 +1840,7 @@ explain_implicit_non_constexpr (tree decl) synthesized_method_walk (DECL_CLASS_CONTEXT (decl), special_function_p (decl), const_p, NULL, NULL, NULL, &dummy, true, - DECL_INHERITED_CTOR_BASE (decl), + DECL_INHERITED_CTOR (decl), FUNCTION_FIRST_USER_PARMTYPE (decl)); } @@ -1720,14 +1851,17 @@ explain_implicit_non_constexpr (tree decl) void deduce_inheriting_ctor (tree decl) { - gcc_assert (DECL_INHERITED_CTOR_BASE (decl)); + gcc_assert (DECL_INHERITED_CTOR (decl)); tree spec; bool trivial, constexpr_, deleted; synthesized_method_walk (DECL_CONTEXT (decl), sfk_inheriting_constructor, false, &spec, &trivial, &deleted, &constexpr_, /*diag*/false, - DECL_INHERITED_CTOR_BASE (decl), + DECL_INHERITED_CTOR (decl), FUNCTION_FIRST_USER_PARMTYPE (decl)); + if (TREE_CODE (inherited_ctor_binfo (decl)) != TREE_BINFO) + /* Inherited the same constructor from different base subobjects. */ + deleted = true; DECL_DELETED_FN (decl) = deleted; TREE_TYPE (decl) = build_exception_variant (TREE_TYPE (decl), spec); } @@ -1828,9 +1962,6 @@ implicitly_declare_fn (special_function_kind kind, tree type, gcc_unreachable (); } - tree inherited_base = (inherited_ctor - ? DECL_CONTEXT (inherited_ctor) - : NULL_TREE); bool trivial_p = false; if (inherited_ctor && TREE_CODE (inherited_ctor) == TEMPLATE_DECL) @@ -1846,12 +1977,12 @@ implicitly_declare_fn (special_function_kind kind, tree type, raises = unevaluated_noexcept_spec (); synthesized_method_walk (type, kind, const_p, NULL, &trivial_p, &deleted_p, &constexpr_p, false, - inherited_base, inherited_parms); + inherited_ctor, inherited_parms); } else synthesized_method_walk (type, kind, const_p, &raises, &trivial_p, &deleted_p, &constexpr_p, false, - inherited_base, inherited_parms); + inherited_ctor, inherited_parms); /* Don't bother marking a deleted constructor as constexpr. */ if (deleted_p) constexpr_p = false; @@ -1902,7 +2033,7 @@ implicitly_declare_fn (special_function_kind kind, tree type, { tree *p = &DECL_ARGUMENTS (fn); int index = 1; - for (tree parm = inherited_parms; parm != void_list_node; + for (tree parm = inherited_parms; parm && parm != void_list_node; parm = TREE_CHAIN (parm)) { *p = cp_build_parm_decl (NULL_TREE, TREE_VALUE (parm)); @@ -1912,7 +2043,7 @@ implicitly_declare_fn (special_function_kind kind, tree type, DECL_CONTEXT (*p) = fn; p = &DECL_CHAIN (*p); } - SET_DECL_INHERITED_CTOR_BASE (fn, inherited_base); + SET_DECL_INHERITED_CTOR (fn, inherited_ctor); DECL_NONCONVERTING_P (fn) = DECL_NONCONVERTING_P (inherited_ctor); /* A constructor so declared has the same access as the corresponding constructor in X. */ diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index 023ed87..e574c27 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -3421,6 +3421,12 @@ do_class_using_decl (tree scope, tree name) return NULL_TREE; } } + else if (name == ctor_identifier + && BINFO_INHERITANCE_CHAIN (BINFO_INHERITANCE_CHAIN (binfo))) + { + error ("cannot inherit constructors from indirect base %qT", scope); + return NULL_TREE; + } else if (!name_dependent_p) { decl = lookup_member (binfo, name, 0, false, tf_warning_or_error); diff --git a/gcc/cp/optimize.c b/gcc/cp/optimize.c index e2032c1..b926ef7 100644 --- a/gcc/cp/optimize.c +++ b/gcc/cp/optimize.c @@ -166,7 +166,8 @@ cdtor_comdat_group (tree complete, tree base) { gcc_assert (!diff_seen && idx > 0 - && (p[idx - 1] == 'C' || p[idx - 1] == 'D') + && (p[idx - 1] == 'C' || p[idx - 1] == 'D' + || p[idx - 1] == 'I') && p[idx] == '1' && q[idx] == '2'); grp_name[idx] = '5'; @@ -259,6 +260,11 @@ maybe_thunk_body (tree fn, bool force) (for non-vague linkage ctors) or the COMDAT group (otherwise). */ populate_clone_array (fn, fns); + + /* Don't use thunks if the base clone omits inherited parameters. */ + if (ctor_omit_inherited_parms (fns[0])) + return 0; + DECL_ABSTRACT_P (fn) = false; if (!DECL_WEAK (fn)) { @@ -490,7 +496,7 @@ maybe_clone_body (tree fn) parm = DECL_CHAIN (parm); if (DECL_HAS_VTT_PARM_P (clone)) clone_parm = DECL_CHAIN (clone_parm); - for (; parm; + for (; parm && clone_parm; parm = DECL_CHAIN (parm), clone_parm = DECL_CHAIN (clone_parm)) /* Update this parameter. */ update_cloned_parm (parm, clone_parm, first); @@ -616,7 +622,8 @@ maybe_clone_body (tree fn) else { decl_map->put (parm, clone_parm); - clone_parm = DECL_CHAIN (clone_parm); + if (clone_parm) + clone_parm = DECL_CHAIN (clone_parm); } } diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 7352213..e513448 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -12056,7 +12056,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain) maybe_retrofit_in_chrg (r); if (DECL_CONSTRUCTOR_P (r)) grok_ctor_properties (ctx, r); - if (DECL_INHERITED_CTOR_BASE (r)) + if (DECL_INHERITED_CTOR (r)) deduce_inheriting_ctor (r); /* If this is an instantiation of a member template, clone it. If it isn't, that'll be handled by @@ -17663,11 +17663,16 @@ instantiate_template_1 (tree tmpl, tree orig_args, tsubst_flags_t complain) DECL_TI_ARGS (fndecl) = targ_ptr; /* Now we know the specialization, compute access previously - deferred. */ - push_access_scope (fndecl); - if (!perform_deferred_access_checks (complain)) - access_ok = false; - pop_access_scope (fndecl); + deferred. Do no access control for inheriting constructors, + as we already checked access for the inherited constructor. */ + if (!(flag_new_inheriting_ctors + && DECL_INHERITED_CTOR (fndecl))) + { + push_access_scope (fndecl); + if (!perform_deferred_access_checks (complain)) + access_ok = false; + pop_access_scope (fndecl); + } pop_deferring_access_checks (); /* If we've just instantiated the main entry point for a function, @@ -17825,6 +17830,11 @@ fn_type_unification (tree fn, static int deduction_depth; struct pending_template *old_last_pend = last_pending_template; struct tinst_level *old_error_tinst = last_error_tinst_level; + + tree orig_fn = fn; + if (flag_new_inheriting_ctors) + fn = strip_inheriting_ctors (fn); + tree tparms = DECL_INNERMOST_TEMPLATE_PARMS (fn); tree tinst; tree r = error_mark_node; @@ -18113,6 +18123,11 @@ fn_type_unification (tree fn, } } + /* After doing deduction with the inherited constructor, actually return an + instantiation of the inheriting constructor. */ + if (orig_fn != fn) + decl = instantiate_template (orig_fn, targs, complain); + r = decl; fail: diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 03eef00..ac15d67 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -4282,7 +4282,7 @@ special_function_p (const_tree decl) /* Rather than doing all this stuff with magic names, we should probably have a field of type `special_function_kind' in DECL_LANG_SPECIFIC. */ - if (DECL_INHERITED_CTOR_BASE (decl)) + if (DECL_INHERITED_CTOR (decl)) return sfk_inheriting_constructor; if (DECL_COPY_CONSTRUCTOR_P (decl)) return sfk_copy_constructor; |