diff options
author | Patrick Palka <ppalka@redhat.com> | 2021-08-18 08:37:45 -0400 |
---|---|---|
committer | Patrick Palka <ppalka@redhat.com> | 2021-08-18 08:37:45 -0400 |
commit | be4a4fb516688d7cfe28a80a4aa333f4ecf0b518 (patch) | |
tree | 40bd7e48f685156136613ae9e09ddb5f805609e0 /gcc/cp/decl.c | |
parent | a6b3db3e8625a3cba1240f0b5e1a29bd6c68b8ca (diff) | |
download | gcc-be4a4fb516688d7cfe28a80a4aa333f4ecf0b518.zip gcc-be4a4fb516688d7cfe28a80a4aa333f4ecf0b518.tar.gz gcc-be4a4fb516688d7cfe28a80a4aa333f4ecf0b518.tar.bz2 |
c++: aggregate CTAD and brace elision [PR101344]
Here the problem is ultimately that collect_ctor_idx_types always
recurses into an eligible sub-CONSTRUCTOR regardless of whether the
corresponding pair of braces was elided in the original initializer.
This causes us to reject some completely-braced forms of aggregate
CTAD as in the first testcase below, because collect_ctor_idx_types
effectively assumes that the original initializer is always minimally
braced (and so the aggregate deduction candidate is given a function
type that's incompatible with the original completely-braced initializer).
In order to fix this, collect_ctor_idx_types needs to somehow know the
shape of the original initializer when iterating over the reshaped
initializer. To that end this patch makes reshape_init flag sub-ctors
that were built to undo brace elision in the original ctor, so that
collect_ctor_idx_types that determine whether to recurse into a sub-ctor
by simply inspecting this flag.
This happens to also fix PR101820, which is about aggregate CTAD using
designated initializers, for much the same reasons.
A curious case is the "intermediately-braced" initialization of 'e3'
(which we reject) in the first testcase below. It seems to me we're
behaving as specified here (according to [over.match.class.deduct]/1)
because the initializer element x_1={1, 2, 3, 4} corresponds to the
subobject e_1=E::t, hence the type T_1 of the first function parameter
of the aggregate deduction candidate is T(&&)[2][2], but T can't be
deduced from x_1 using this parameter type (as opposed to say T(&&)[4]).
PR c++/101344
PR c++/101820
gcc/cp/ChangeLog:
* cp-tree.h (CONSTRUCTOR_BRACES_ELIDED_P): Define.
* decl.c (reshape_init_r): Set it.
* pt.c (collect_ctor_idx_types): Recurse into a sub-CONSTRUCTOR
iff CONSTRUCTOR_BRACES_ELIDED_P.
gcc/testsuite/ChangeLog:
* g++.dg/cpp2a/class-deduction-aggr11.C: New test.
* g++.dg/cpp2a/class-deduction-aggr12.C: New test.
Diffstat (limited to 'gcc/cp/decl.c')
-rw-r--r-- | gcc/cp/decl.c | 18 |
1 files changed, 14 insertions, 4 deletions
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 32d07ba..3414cbd 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -6657,7 +6657,8 @@ reshape_init_r (tree type, reshape_iter *d, tree first_initializer_p, /* A non-aggregate type is always initialized with a single initializer. */ if (!CP_AGGREGATE_TYPE_P (type) - /* As is an array with dependent bound. */ + /* As is an array with dependent bound, which we can see + during C++20 aggregate CTAD. */ || (cxx_dialect >= cxx20 && TREE_CODE (type) == ARRAY_TYPE && uses_template_parms (TYPE_DOMAIN (type)))) @@ -6774,6 +6775,7 @@ reshape_init_r (tree type, reshape_iter *d, tree first_initializer_p, initializer already, and there is not a CONSTRUCTOR, it means that there is a missing set of braces (that is, we are processing the case for which reshape_init exists). */ + bool braces_elided_p = false; if (!first_initializer_p) { if (TREE_CODE (stripped_init) == CONSTRUCTOR) @@ -6809,17 +6811,25 @@ reshape_init_r (tree type, reshape_iter *d, tree first_initializer_p, warning (OPT_Wmissing_braces, "missing braces around initializer for %qT", type); + braces_elided_p = true; } /* Dispatch to specialized routines. */ + tree new_init; if (CLASS_TYPE_P (type)) - return reshape_init_class (type, d, first_initializer_p, complain); + new_init = reshape_init_class (type, d, first_initializer_p, complain); else if (TREE_CODE (type) == ARRAY_TYPE) - return reshape_init_array (type, d, first_initializer_p, complain); + new_init = reshape_init_array (type, d, first_initializer_p, complain); else if (VECTOR_TYPE_P (type)) - return reshape_init_vector (type, d, complain); + new_init = reshape_init_vector (type, d, complain); else gcc_unreachable(); + + if (braces_elided_p + && TREE_CODE (new_init) == CONSTRUCTOR) + CONSTRUCTOR_BRACES_ELIDED_P (new_init) = true; + + return new_init; } /* Undo the brace-elision allowed by [dcl.init.aggr] in a |