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/method.c | |
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/method.c')
-rw-r--r-- | gcc/cp/method.c | 215 |
1 files changed, 173 insertions, 42 deletions
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. */ |