From: Marek Polacek <polacek@redhat.com>
To: Patrick Palka <ppalka@redhat.com>
Cc: gcc-patches@gcc.gnu.org
Subject: Re: [PATCH] c++: aggregate CTAD and brace elision [PR101344]
Date: Mon, 16 Aug 2021 15:18:34 -0400 [thread overview]
Message-ID: <YRq6Cso4Doqu0/y3@redhat.com> (raw)
In-Reply-To: <20210816190608.1339856-1-ppalka@redhat.com>
On Mon, Aug 16, 2021 at 03:06:08PM -0400, Patrick Palka via Gcc-patches wrote:
> During aggregate CTAD, collect_ctor_idx_types always recurses into a
> 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 given
> initializer is always minimally-braced (hence the aggregate deduction
> candidate is given a function type that's incompatible with the written
> initializer).
>
> This patch fixes this by making reshape_init flag CONSTRUCTORs that
> were built to undo brace elision in the original CONSTRUCTOR, so that
> collect_ctor_idx_types can determine whether to recurse into a
> sub-CONSTRUCTOR by simply inspecting this flag.
>
> This happens to also fix PR101820, which is about aggregate CTAD using
> designated initializers, for a similar reason as above.
>
> A tricky case is the "intermediately-braced" initialization of 'e3'
> in the first testcase below. It seems to me we're correct to continue
> to reject this according to [over.match.class.deduct]/1 because here
> the initializer element {1, 2, 3, 4} corresponds to the subobject E::t,
> hence the type T_1 of the first funciton parameter of the aggregate
> deduction candidate is T(&&)[2][2] which the argument {1, 2, 3, 4} isn't
> compatible with (as opposed to say T(&&)[4]).
>
> Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
> trunk/11?
>
> 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 | 6 ++++
> gcc/cp/decl.c | 18 +++++++++---
> gcc/cp/pt.c | 7 +----
> .../g++.dg/cpp2a/class-deduction-aggr11.C | 29 +++++++++++++++++++
> .../g++.dg/cpp2a/class-deduction-aggr12.C | 15 ++++++++++
> 5 files changed, 65 insertions(+), 10 deletions(-)
> create mode 100644 gcc/testsuite/g++.dg/cpp2a/class-deduction-aggr11.C
> create mode 100644 gcc/testsuite/g++.dg/cpp2a/class-deduction-aggr12.C
>
> diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
> index bd3f12a393e..8cbf6cc30b0 100644
> --- a/gcc/cp/cp-tree.h
> +++ b/gcc/cp/cp-tree.h
> @@ -4502,6 +4502,12 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
> #define CONSTRUCTOR_IS_PAREN_INIT(NODE) \
> (CONSTRUCTOR_CHECK(NODE)->base.private_flag)
>
> +/* True if reshape_init built this CONSTRUCTOR to undo the brace elision
> + of another CONSTRUCTOR. This flag is used during C++20 aggregate
> + CTAD. */
> +#define CONSTRUCTOR_BRACES_ELIDED_P(NODE) \
> + (CONSTRUCTOR_CHECK (NODE)->base.protected_flag)
> +
> /* True if NODE represents a conversion for direct-initialization in a
> template. Set by perform_implicit_conversion_flags. */
> #define IMPLICIT_CONV_EXPR_DIRECT_INIT(NODE) \
> diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
> index b3671ee8956..9e257b32e18 100644
> --- a/gcc/cp/decl.c
> +++ b/gcc/cp/decl.c
> @@ -6650,7 +6650,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))))
> @@ -6767,6 +6768,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)
> @@ -6802,17 +6804,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)
> + if (TREE_CODE (new_init) == CONSTRUCTOR)
> + CONSTRUCTOR_BRACES_ELIDED_P (new_init) = 1;
Any reason for the two ifs and not an &&?
Marek
next prev parent reply other threads:[~2021-08-16 19:18 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-08-16 19:06 Patrick Palka
2021-08-16 19:18 ` Marek Polacek [this message]
2021-08-16 19:26 ` Patrick Palka
2021-08-16 20:05 ` Jason Merrill
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=YRq6Cso4Doqu0/y3@redhat.com \
--to=polacek@redhat.com \
--cc=gcc-patches@gcc.gnu.org \
--cc=ppalka@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).