c++: aggregate CTAD and brace elision [PR101344]
authorPatrick Palka <ppalka@redhat.com>
Wed, 18 Aug 2021 12:37:45 +0000 (08:37 -0400)
committerPatrick Palka <ppalka@redhat.com>
Wed, 18 Aug 2021 12:37:45 +0000 (08:37 -0400)
commitbe4a4fb516688d7cfe28a80a4aa333f4ecf0b518
tree40bd7e48f685156136613ae9e09ddb5f805609e0
parenta6b3db3e8625a3cba1240f0b5e1a29bd6c68b8ca
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.
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/pt.c
gcc/testsuite/g++.dg/cpp2a/class-deduction-aggr11.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp2a/class-deduction-aggr12.C [new file with mode: 0644]