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
This commit is contained in:
parent
be9f7afb32
commit
31f7f784fe
49 changed files with 937 additions and 97 deletions
|
@ -1,3 +1,8 @@
|
|||
2016-11-01 Jason Merrill <jason@redhat.com>
|
||||
|
||||
* tree-inline.c (copy_tree_body_r): Only copy the taken branch of
|
||||
a COND_EXPR with constant condition.
|
||||
|
||||
2016-11-01 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* dwarf2out.c (gen_variable_die): Remove again origin_die variable
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
2016-11-01 Jason Merrill <jason@redhat.com>
|
||||
|
||||
* c.opt (-fnew-inheriting-ctors): New.
|
||||
* c-opts.c: Default to on for ABI 11+.
|
||||
|
||||
2016-10-31 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR c++/77948
|
||||
|
|
|
@ -902,6 +902,12 @@ c_common_post_options (const char **pfilename)
|
|||
if (flag_abi_version == 0)
|
||||
flag_abi_version = 11;
|
||||
|
||||
/* By default, enable the new inheriting constructor semantics along with ABI
|
||||
11. New and old should coexist fine, but it is a change in what
|
||||
artificial symbols are generated. */
|
||||
if (!global_options_set.x_flag_new_inheriting_ctors)
|
||||
flag_new_inheriting_ctors = abi_version_at_least (11);
|
||||
|
||||
if (cxx_dialect >= cxx11)
|
||||
{
|
||||
/* If we're allowing C++0x constructs, don't warn about C++98
|
||||
|
|
|
@ -1362,6 +1362,10 @@ fimplicit-templates
|
|||
C++ ObjC++ Var(flag_implicit_templates) Init(1)
|
||||
Emit implicit instantiations of templates.
|
||||
|
||||
fnew-inheriting-ctors
|
||||
C++ ObjC++ Var(flag_new_inheriting_ctors) Init(1)
|
||||
Implement C++17 inheriting constructor semantics.
|
||||
|
||||
ffriend-injection
|
||||
C++ ObjC++ Var(flag_friend_injection)
|
||||
Inject friend functions into enclosing namespace.
|
||||
|
|
|
@ -907,7 +907,8 @@ Driver Undocumented
|
|||
; identity, such as ia32 calling convention attributes (stdcall, etc.)
|
||||
; Default in G++ 6 (set in c_common_post_options).
|
||||
;
|
||||
; 11: The version of the ABI that corrects mangling of sizeof... expressions.
|
||||
; 11: The version of the ABI that corrects mangling of sizeof... expressions
|
||||
; and introduces new inheriting constructor handling.
|
||||
; Default in G++ 7.
|
||||
;
|
||||
; Additional positive integers will be assigned as new versions of
|
||||
|
|
|
@ -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.
|
||||
|
|
139
gcc/cp/call.c
139
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.
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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>.
|
||||
|
|
215
gcc/cp/method.c
215
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. */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
27
gcc/cp/pt.c
27
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:
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -199,6 +199,7 @@ in the following sections.
|
|||
-fno-implicit-templates @gol
|
||||
-fno-implicit-inline-templates @gol
|
||||
-fno-implement-inlines -fms-extensions @gol
|
||||
-fnew-inheriting-ctors @gol
|
||||
-fno-nonansi-builtins -fnothrow-opt -fno-operator-names @gol
|
||||
-fno-optional-diags -fpermissive @gol
|
||||
-fno-pretty-templates @gol
|
||||
|
@ -2220,6 +2221,10 @@ Version 10, which first appeared in G++ 6.1, adds mangling of
|
|||
attributes that affect type identity, such as ia32 calling convention
|
||||
attributes (e.g. @samp{stdcall}).
|
||||
|
||||
Version 11, which first appeared in G++ 7, corrects the mangling of
|
||||
sizeof... expressions. It also implies
|
||||
@option{-fnew-inheriting-ctors}.
|
||||
|
||||
See also @option{-Wabi}.
|
||||
|
||||
@item -fabi-compat-version=@var{n}
|
||||
|
@ -2413,6 +2418,13 @@ errors if these functions are not inlined everywhere they are called.
|
|||
Disable Wpedantic warnings about constructs used in MFC, such as implicit
|
||||
int and getting a pointer to member function via non-standard syntax.
|
||||
|
||||
@item -fnew-inheriting-ctors
|
||||
@opindex fnew-inheriting-ctors
|
||||
Enable the P0136 adjustment to the semantics of C++11 constructor
|
||||
inheritance. This is part of C++17 but also considered to be a Defect
|
||||
Report against C++11 and C++14. This flag is enabled by default
|
||||
unless @option{-fabi-version=10} or lower is specified.
|
||||
|
||||
@item -fno-nonansi-builtins
|
||||
@opindex fno-nonansi-builtins
|
||||
Disable built-in declarations of functions that are not mandated by
|
||||
|
|
|
@ -9,7 +9,7 @@ struct A
|
|||
|
||||
struct B : A
|
||||
{
|
||||
using A::A; // { dg-error "A::i" }
|
||||
using A::A; // { dg-prune-output "A::i" }
|
||||
};
|
||||
|
||||
constexpr B b(0); // { dg-error "B::B" }
|
||||
constexpr B b(0); // { dg-error "" }
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
// { dg-do compile { target c++11 } }
|
||||
// { dg-options -fno-new-inheriting-ctors }
|
||||
|
||||
struct A
|
||||
{
|
||||
|
|
15
gcc/testsuite/g++.dg/cpp0x/inh-ctor11a.C
Normal file
15
gcc/testsuite/g++.dg/cpp0x/inh-ctor11a.C
Normal file
|
@ -0,0 +1,15 @@
|
|||
// { dg-do compile { target c++11 } }
|
||||
// { dg-options -fnew-inheriting-ctors }
|
||||
|
||||
struct A
|
||||
{
|
||||
A(int, ...);
|
||||
};
|
||||
|
||||
struct B: A
|
||||
{
|
||||
using A::A;
|
||||
};
|
||||
|
||||
B b1(42);
|
||||
B b2(42, 1.0); // { dg-bogus "ellipsis" "" { xfail *-*-* } }
|
|
@ -2,6 +2,7 @@
|
|||
// constructors was a deliberate choice.
|
||||
|
||||
// { dg-do compile { target c++11 } }
|
||||
// { dg-options -fno-new-inheriting-ctors }
|
||||
|
||||
struct A { A(int); };
|
||||
struct B: public A
|
||||
|
|
14
gcc/testsuite/g++.dg/cpp0x/inh-ctor15a.C
Normal file
14
gcc/testsuite/g++.dg/cpp0x/inh-ctor15a.C
Normal file
|
@ -0,0 +1,14 @@
|
|||
// P0136 caused us to start inheriting base copy constructors.
|
||||
// { dg-do compile { target c++11 } }
|
||||
// { dg-options -fnew-inheriting-ctors }
|
||||
|
||||
struct A { A(int); };
|
||||
struct B: public A
|
||||
{
|
||||
using A::A;
|
||||
};
|
||||
|
||||
A a (42);
|
||||
|
||||
B b1 (24); // inherited
|
||||
B b2 (a); // also inherited now
|
|
@ -1,4 +1,5 @@
|
|||
// { dg-do compile { target c++11 } }
|
||||
// { dg-options -fno-new-inheriting-ctors }
|
||||
|
||||
struct B1 {
|
||||
B1(int);
|
||||
|
|
21
gcc/testsuite/g++.dg/cpp0x/inh-ctor3a.C
Normal file
21
gcc/testsuite/g++.dg/cpp0x/inh-ctor3a.C
Normal file
|
@ -0,0 +1,21 @@
|
|||
// { dg-do compile { target c++11 } }
|
||||
// { dg-options -fnew-inheriting-ctors }
|
||||
|
||||
struct B1 {
|
||||
B1(int);
|
||||
};
|
||||
struct B2 {
|
||||
B2(int);
|
||||
};
|
||||
struct D1 : B1, B2 {
|
||||
using B1::B1;
|
||||
using B2::B2;
|
||||
}; // ambiguous
|
||||
struct D2 : B1, B2 {
|
||||
using B1::B1;
|
||||
using B2::B2;
|
||||
D2(int); // OK: user declaration supersedes both implicit declarations
|
||||
};
|
||||
|
||||
D2 d2(42);
|
||||
D1 d1(42); // { dg-error "ambiguous" }
|
|
@ -15,7 +15,7 @@ void test() {
|
|||
D1 e; // { dg-error "deleted" } D1 has no default constructor
|
||||
}
|
||||
struct D2 : B2 {
|
||||
using B2::B2; // { dg-error "no match" } implicitly declares D2(double)
|
||||
using B2::B2; // { dg-error "B1::B1" }
|
||||
B1 b;
|
||||
};
|
||||
D2 f(1.0); // { dg-error "deleted" } B1 has no default constructor
|
||||
|
|
|
@ -9,7 +9,7 @@ protected:
|
|||
|
||||
struct B: A
|
||||
{
|
||||
using A::A; // { dg-message "protected" }
|
||||
using A::A;
|
||||
};
|
||||
|
||||
B b(42); // { dg-error "this context" }
|
||||
|
|
5
gcc/testsuite/g++.dg/cpp1z/inh-ctor1.C
Normal file
5
gcc/testsuite/g++.dg/cpp1z/inh-ctor1.C
Normal file
|
@ -0,0 +1,5 @@
|
|||
// { dg-do compile { target c++11 } }
|
||||
|
||||
struct A { };
|
||||
struct B: A { };
|
||||
struct C: B { using A::A; }; // { dg-error "direct" }
|
33
gcc/testsuite/g++.dg/cpp1z/inh-ctor22.C
Normal file
33
gcc/testsuite/g++.dg/cpp1z/inh-ctor22.C
Normal file
|
@ -0,0 +1,33 @@
|
|||
// Testcase from P0136
|
||||
// { dg-do compile { target c++11 } }
|
||||
|
||||
struct B1 {
|
||||
template <class... Ts>
|
||||
B1(int, Ts...) { }
|
||||
};
|
||||
|
||||
struct B2 {
|
||||
B2(double) { }
|
||||
};
|
||||
|
||||
int get();
|
||||
|
||||
struct D1 : B1 { // { dg-message "B1::B1" }
|
||||
using B1::B1; // inherits B1(int, ...)
|
||||
int x;
|
||||
int y = get();
|
||||
};
|
||||
|
||||
void test() {
|
||||
D1 d(2, 3, 4); // OK: B1 is initialized by calling B1(2, 3, 4),
|
||||
// then d.x is default-initialized (no initialization is performed),
|
||||
// then d.y is initialized by calling get()
|
||||
D1 e; // { dg-error "" } D1 has a deleted default constructor
|
||||
}
|
||||
|
||||
struct D2 : B2 {
|
||||
using B2::B2; // { dg-message "B1::B1" }
|
||||
B1 b;
|
||||
};
|
||||
|
||||
D2 f(1.0); // { dg-error "" } B1 has no default constructor
|
19
gcc/testsuite/g++.dg/cpp1z/inh-ctor23.C
Normal file
19
gcc/testsuite/g++.dg/cpp1z/inh-ctor23.C
Normal file
|
@ -0,0 +1,19 @@
|
|||
// Testcase from P0136
|
||||
// { dg-do compile { target c++11 } }
|
||||
// { dg-options "-fnew-inheriting-ctors -fdump-tree-gimple" }
|
||||
|
||||
struct W { W(int); };
|
||||
struct V: W { using W::W; };
|
||||
struct X : virtual V { using V::V; X() = delete; };
|
||||
struct Y : X { using X::X; };
|
||||
struct Z : Y, virtual V { using Y::Y; };
|
||||
Z z(0); // OK: initialization of Y does not invoke default constructor of X
|
||||
|
||||
// Check that we're passing this and __vtt along to the Y inheriting
|
||||
// constructor, but not the int parameter.
|
||||
// { dg-final { scan-assembler "_ZN1YCI21WEi" } }
|
||||
// { dg-final { scan-tree-dump "Y::Y ._2, _3.;" "gimple" } }
|
||||
|
||||
// And that we *are* passing the int along to V::V.
|
||||
// { dg-final { scan-assembler "_ZN1VCI21WEi" } }
|
||||
// { dg-final { scan-tree-dump "V::V .this, _1.;" "gimple" } }
|
27
gcc/testsuite/g++.dg/cpp1z/inh-ctor24.C
Normal file
27
gcc/testsuite/g++.dg/cpp1z/inh-ctor24.C
Normal file
|
@ -0,0 +1,27 @@
|
|||
// Testcase from P0136
|
||||
// { dg-do compile { target c++11 } }
|
||||
// { dg-options -fnew-inheriting-ctors }
|
||||
|
||||
struct A { A(int); };
|
||||
struct B : A { using A::A; };
|
||||
|
||||
struct C1 : B { using B::B; };
|
||||
struct C2 : B { using B::B; };
|
||||
|
||||
struct D1 : C1, C2 {
|
||||
using C1::C1;
|
||||
using C2::C2;
|
||||
};
|
||||
|
||||
struct V1 : virtual B { using B::B; };
|
||||
struct V2 : virtual B { using B::B; };
|
||||
|
||||
struct D2 : V1, V2 {
|
||||
using V1::V1;
|
||||
using V2::V2;
|
||||
};
|
||||
|
||||
D1 d1(0); // { dg-error "" } ambiguous
|
||||
D2 d2(0); // OK: initializes virtual B base class, which initializes the A base
|
||||
// class then initializes the V1 and V2 base classes as if by a
|
||||
// defaulted default constructor
|
9
gcc/testsuite/g++.dg/cpp1z/inh-ctor25.C
Normal file
9
gcc/testsuite/g++.dg/cpp1z/inh-ctor25.C
Normal file
|
@ -0,0 +1,9 @@
|
|||
// Testcase from P0136
|
||||
// { dg-do compile { target c++11 } }
|
||||
|
||||
struct M { M(); M(int); };
|
||||
struct N : M { using M::M; };
|
||||
struct O : M {};
|
||||
struct P : N, O { using N::N; using O::O; };
|
||||
P p(0); // OK: use M(0) to initialize N's base class,
|
||||
// use M() to initialize O's base class
|
17
gcc/testsuite/g++.dg/cpp1z/inh-ctor26.C
Normal file
17
gcc/testsuite/g++.dg/cpp1z/inh-ctor26.C
Normal file
|
@ -0,0 +1,17 @@
|
|||
// Testcase from P0136
|
||||
// { dg-do compile { target c++11 } }
|
||||
// { dg-options -fnew-inheriting-ctors }
|
||||
|
||||
struct A {
|
||||
template<typename T> A(T, typename T::type = 0);
|
||||
A(int);
|
||||
};
|
||||
struct B : A {
|
||||
using A::A;
|
||||
B(int);
|
||||
};
|
||||
B b(42L); // now calls B(int), used to call B<long>(long),
|
||||
// which called A(int) due to substitution failure
|
||||
// in A<long>(long).
|
||||
|
||||
// { dg-final { scan-assembler "_ZN1BC1Ei" } }
|
15
gcc/testsuite/g++.dg/cpp1z/inh-ctor27.C
Normal file
15
gcc/testsuite/g++.dg/cpp1z/inh-ctor27.C
Normal file
|
@ -0,0 +1,15 @@
|
|||
// { dg-do compile { target c++11 } }
|
||||
|
||||
struct A
|
||||
{
|
||||
A(int = 0);
|
||||
};
|
||||
|
||||
struct B: A
|
||||
{
|
||||
B();
|
||||
using A::A;
|
||||
};
|
||||
|
||||
B b1(1);
|
||||
B b;
|
7
gcc/testsuite/g++.dg/cpp1z/inh-ctor28.C
Normal file
7
gcc/testsuite/g++.dg/cpp1z/inh-ctor28.C
Normal file
|
@ -0,0 +1,7 @@
|
|||
// { dg-do compile { target c++11 } }
|
||||
// { dg-options -fnew-inheriting-ctors }
|
||||
|
||||
struct V { V(int); };
|
||||
struct W : virtual V { using V::V; };
|
||||
struct X : virtual W, virtual V { using W::W; };
|
||||
X x(0);
|
15
gcc/testsuite/g++.dg/cpp1z/inh-ctor29.C
Normal file
15
gcc/testsuite/g++.dg/cpp1z/inh-ctor29.C
Normal file
|
@ -0,0 +1,15 @@
|
|||
// { dg-do compile { target c++11 } }
|
||||
|
||||
struct A
|
||||
{
|
||||
A(int = 0);
|
||||
};
|
||||
|
||||
struct B: A
|
||||
{
|
||||
B();
|
||||
using A::A;
|
||||
};
|
||||
|
||||
B b1(1);
|
||||
B b;
|
17
gcc/testsuite/g++.dg/cpp1z/inh-ctor30.C
Normal file
17
gcc/testsuite/g++.dg/cpp1z/inh-ctor30.C
Normal file
|
@ -0,0 +1,17 @@
|
|||
// { dg-do compile { target c++11 } }
|
||||
|
||||
struct A
|
||||
{
|
||||
A(double);
|
||||
};
|
||||
|
||||
struct B: A
|
||||
{
|
||||
B(short);
|
||||
using A::A;
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
B b(1); // { dg-error "ambiguous" }
|
||||
}
|
15
gcc/testsuite/g++.dg/cpp1z/inh-ctor31.C
Normal file
15
gcc/testsuite/g++.dg/cpp1z/inh-ctor31.C
Normal file
|
@ -0,0 +1,15 @@
|
|||
// { dg-do compile { target c++11 } }
|
||||
|
||||
struct B;
|
||||
struct A
|
||||
{
|
||||
A(const B&, int = 0);
|
||||
};
|
||||
|
||||
struct B: A
|
||||
{
|
||||
using A::A;
|
||||
};
|
||||
|
||||
extern B b;
|
||||
B b2{b};
|
16
gcc/testsuite/g++.dg/cpp1z/inh-ctor32.C
Normal file
16
gcc/testsuite/g++.dg/cpp1z/inh-ctor32.C
Normal file
|
@ -0,0 +1,16 @@
|
|||
// { dg-do compile { target c++11 } }
|
||||
|
||||
struct B;
|
||||
struct A
|
||||
{
|
||||
A(const B&, int = 0);
|
||||
};
|
||||
|
||||
struct B: A
|
||||
{
|
||||
using A::A;
|
||||
B(B&);
|
||||
};
|
||||
|
||||
extern const B b;
|
||||
B b2{b}; // { dg-error "" }
|
23
gcc/testsuite/g++.dg/cpp1z/inh-ctor33.C
Normal file
23
gcc/testsuite/g++.dg/cpp1z/inh-ctor33.C
Normal file
|
@ -0,0 +1,23 @@
|
|||
// { dg-do link { target c++11 } }
|
||||
// { dg-options -fnew-inheriting-ctors }
|
||||
|
||||
struct A
|
||||
{
|
||||
A() { }
|
||||
A(const A&); // should never be called
|
||||
};
|
||||
|
||||
struct B
|
||||
{
|
||||
B(A) { }
|
||||
};
|
||||
|
||||
struct C: B
|
||||
{
|
||||
using B::B;
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
C c{A()};
|
||||
}
|
18
gcc/testsuite/g++.dg/cpp1z/inh-ctor34.C
Normal file
18
gcc/testsuite/g++.dg/cpp1z/inh-ctor34.C
Normal file
|
@ -0,0 +1,18 @@
|
|||
// { dg-do compile { target c++11 } }
|
||||
// { dg-options -fnew-inheriting-ctors }
|
||||
|
||||
class A
|
||||
{
|
||||
A(int);
|
||||
friend void f();
|
||||
};
|
||||
|
||||
struct B: A
|
||||
{
|
||||
using A::A;
|
||||
};
|
||||
|
||||
void f()
|
||||
{
|
||||
B b(42);
|
||||
}
|
21
gcc/testsuite/g++.dg/cpp1z/inh-ctor35.C
Normal file
21
gcc/testsuite/g++.dg/cpp1z/inh-ctor35.C
Normal file
|
@ -0,0 +1,21 @@
|
|||
// Core 1715
|
||||
// { dg-do compile { target c++11 } }
|
||||
// { dg-options -fno-new-inheriting-ctors }
|
||||
|
||||
template<class T> struct S {
|
||||
private:
|
||||
typedef int X;
|
||||
friend struct B;
|
||||
};
|
||||
|
||||
struct B {
|
||||
template<class T> B(T, typename T::X);
|
||||
};
|
||||
|
||||
struct D: B {
|
||||
using B::B; // { dg-prune-output "private" }
|
||||
};
|
||||
|
||||
S<int> s;
|
||||
B b(s, 2); // Okay, thanks to friendship.
|
||||
D d(s, 2); // { dg-error "" } was an error before P0136
|
21
gcc/testsuite/g++.dg/cpp1z/inh-ctor35a.C
Normal file
21
gcc/testsuite/g++.dg/cpp1z/inh-ctor35a.C
Normal file
|
@ -0,0 +1,21 @@
|
|||
// Core 1715
|
||||
// { dg-do compile { target c++11 } }
|
||||
// { dg-options -fnew-inheriting-ctors }
|
||||
|
||||
template<class T> struct S {
|
||||
private:
|
||||
typedef int X;
|
||||
friend struct B;
|
||||
};
|
||||
|
||||
struct B {
|
||||
template<class T> B(T, typename T::X);
|
||||
};
|
||||
|
||||
struct D: B {
|
||||
using B::B;
|
||||
};
|
||||
|
||||
S<int> s;
|
||||
B b(s, 2); // Okay, thanks to friendship.
|
||||
D d(s, 2); // Now OK as well.
|
23
gcc/testsuite/g++.dg/cpp1z/using1.C
Normal file
23
gcc/testsuite/g++.dg/cpp1z/using1.C
Normal file
|
@ -0,0 +1,23 @@
|
|||
// Test for hiding of used base functions when all the conversion sequences are
|
||||
// equivalent, needed to avoid a regression on inherited default ctors.
|
||||
|
||||
struct A
|
||||
{
|
||||
void f(short,int=0);
|
||||
void g(char,int=0);
|
||||
};
|
||||
|
||||
struct B:A
|
||||
{
|
||||
using A::f;
|
||||
void f(short);
|
||||
using A::g;
|
||||
void g(short);
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
B().f(1); // OK, derived f hides base f for single arg
|
||||
B().f(1,2); // OK, base f can still be called with two args
|
||||
B().g(1); // { dg-error "" } signatures differ, ambiguous
|
||||
}
|
|
@ -1045,6 +1045,7 @@ copy_tree_body_r (tree *tp, int *walk_subtrees, void *data)
|
|||
copy_body_data *id = (copy_body_data *) data;
|
||||
tree fn = id->src_fn;
|
||||
tree new_block;
|
||||
bool copied = false;
|
||||
|
||||
/* Begin by recognizing trees that we'll completely rewrite for the
|
||||
inlining context. Our output for these trees is completely
|
||||
|
@ -1241,10 +1242,40 @@ copy_tree_body_r (tree *tp, int *walk_subtrees, void *data)
|
|||
*walk_subtrees = 0;
|
||||
return NULL;
|
||||
}
|
||||
else if (TREE_CODE (*tp) == COND_EXPR)
|
||||
{
|
||||
tree cond = TREE_OPERAND (*tp, 0);
|
||||
walk_tree (&cond, copy_tree_body_r, data, NULL);
|
||||
tree folded = fold (cond);
|
||||
if (TREE_CODE (folded) == INTEGER_CST)
|
||||
{
|
||||
/* Only copy the taken branch; for a C++ base constructor clone
|
||||
inherited from a virtual base, copying the other branch leads
|
||||
to references to parameters that were optimized away. */
|
||||
tree branch = (integer_nonzerop (folded)
|
||||
? TREE_OPERAND (*tp, 1)
|
||||
: TREE_OPERAND (*tp, 2));
|
||||
tree type = TREE_TYPE (*tp);
|
||||
if (VOID_TYPE_P (type)
|
||||
|| type == TREE_TYPE (branch))
|
||||
{
|
||||
*tp = branch;
|
||||
return copy_tree_body_r (tp, walk_subtrees, data);
|
||||
}
|
||||
}
|
||||
/* Avoid copying the condition twice. */
|
||||
copy_tree_r (tp, walk_subtrees, NULL);
|
||||
TREE_OPERAND (*tp, 0) = cond;
|
||||
walk_tree (&TREE_OPERAND (*tp, 1), copy_tree_body_r, data, NULL);
|
||||
walk_tree (&TREE_OPERAND (*tp, 2), copy_tree_body_r, data, NULL);
|
||||
*walk_subtrees = 0;
|
||||
copied = true;
|
||||
}
|
||||
|
||||
/* Here is the "usual case". Copy this tree node, and then
|
||||
tweak some special cases. */
|
||||
copy_tree_r (tp, walk_subtrees, NULL);
|
||||
if (!copied)
|
||||
copy_tree_r (tp, walk_subtrees, NULL);
|
||||
|
||||
/* If EXPR has block defined, map it to newly constructed block.
|
||||
When inlining we want EXPRs without block appear in the block
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
2016-11-01 Jason Merrill <jason@redhat.com>
|
||||
|
||||
* cp-demangle.c (d_ctor_dtor_name): Handle inheriting constructor.
|
||||
|
||||
2016-10-31 Mark Wielaard <mjw@redhat.com>
|
||||
|
||||
* cplus-dem.c (ada_demangle): Initialize demangled to NULL and
|
||||
|
|
|
@ -2168,6 +2168,13 @@ d_ctor_dtor_name (struct d_info *di)
|
|||
case 'C':
|
||||
{
|
||||
enum gnu_v3_ctor_kinds kind;
|
||||
int inheriting = 0;
|
||||
|
||||
if (d_peek_next_char (di) == 'I')
|
||||
{
|
||||
inheriting = 1;
|
||||
d_advance (di, 1);
|
||||
}
|
||||
|
||||
switch (d_peek_next_char (di))
|
||||
{
|
||||
|
@ -2189,7 +2196,12 @@ d_ctor_dtor_name (struct d_info *di)
|
|||
default:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
d_advance (di, 2);
|
||||
|
||||
if (inheriting)
|
||||
cplus_demangle_type (di);
|
||||
|
||||
return d_make_ctor (di, kind, di->last_name);
|
||||
}
|
||||
|
||||
|
|
|
@ -4592,3 +4592,7 @@ __t2m05B500000000000000000_
|
|||
|
||||
__10%0__S4_0T0T0
|
||||
%0<>::%0(%0<>)
|
||||
|
||||
# Inheriting constructor
|
||||
_ZN1DCI11BEi
|
||||
D::B(int)
|
||||
|
|
Loading…
Add table
Reference in a new issue