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:
Jason Merrill 2016-11-01 21:50:29 -04:00 committed by Jason Merrill
parent be9f7afb32
commit 31f7f784fe
49 changed files with 937 additions and 97 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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.

View File

@ -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.

View File

@ -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 = &current_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;

View File

@ -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
{

View File

@ -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);

View File

@ -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)
{

View File

@ -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;

View File

@ -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>.

View File

@ -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. */

View File

@ -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);

View File

@ -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);
}
}

View File

@ -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:

View File

@ -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;

View File

@ -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

View File

@ -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 "" }

View File

@ -1,4 +1,5 @@
// { dg-do compile { target c++11 } }
// { dg-options -fno-new-inheriting-ctors }
struct A
{

View 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 *-*-* } }

View File

@ -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

View 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

View File

@ -1,4 +1,5 @@
// { dg-do compile { target c++11 } }
// { dg-options -fno-new-inheriting-ctors }
struct B1 {
B1(int);

View 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" }

View File

@ -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

View File

@ -9,7 +9,7 @@ protected:
struct B: A
{
using A::A; // { dg-message "protected" }
using A::A;
};
B b(42); // { dg-error "this context" }

View 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" }

View 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

View 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" } }

View 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

View 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

View 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" } }

View 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;

View 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);

View 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;

View 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" }
}

View 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};

View 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 "" }

View 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()};
}

View 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);
}

View 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

View 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.

View 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
}

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -4592,3 +4592,7 @@ __t2m05B500000000000000000_
__10%0__S4_0T0T0
%0<>::%0(%0<>)
# Inheriting constructor
_ZN1DCI11BEi
D::B(int)