Another part of 95369 is that we accept designated initializers with non-aggregate types. That seems to be wrong since they're part of aggregate initialization. clang/icc also reject it.
(Un)fortunately there are multiple contexts where we can use designated initializers: function-like casts, member list initializers, NTTP, etc. So I've adjusted multiple places in the compiler in order to to detect this case and to provide a nice diagnostic, instead of an ugly raft of errors. Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk? gcc/cp/ChangeLog: PR c++/95369 * call.c (implicit_conversion): Return NULL if a designated initializer is used with a non-aggregate. (implicit_conversion_error): Give an error for the case above. * decl.c (check_initializer): Likewise. * init.c (build_aggr_init): Likewise. * semantics.c (finish_compound_literal): Likewise. gcc/testsuite/ChangeLog: PR c++/95369 * g++.dg/cpp2a/desig11.C: Adjust dg-error. * g++.dg/cpp2a/desig16.C: New test. --- gcc/cp/call.c | 11 +++++++++++ gcc/cp/decl.c | 9 +++++++++ gcc/cp/init.c | 10 ++++++++++ gcc/cp/semantics.c | 7 +++++++ gcc/testsuite/g++.dg/cpp2a/desig11.C | 2 +- gcc/testsuite/g++.dg/cpp2a/desig16.C | 28 ++++++++++++++++++++++++++++ 6 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/g++.dg/cpp2a/desig16.C diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 3c97b9846e2..346fb850f84 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -2020,6 +2020,12 @@ implicit_conversion (tree to, tree from, tree expr, bool c_cast_p, if (is_std_init_list (to) && !CONSTRUCTOR_IS_DESIGNATED_INIT (expr)) return build_list_conv (to, expr, flags, complain); + /* Designated initializers can only be used to initialize an aggregate + because they're part of aggregate initialization. Return NULL here, + implicit_conversion_error will issue an actual error. */ + if (CONSTRUCTOR_IS_DESIGNATED_INIT (expr) && !CP_AGGREGATE_TYPE_P (to)) + return NULL; + /* As an extension, allow list-initialization of _Complex. */ if (TREE_CODE (to) == COMPLEX_TYPE && !CONSTRUCTOR_IS_DESIGNATED_INIT (expr)) @@ -4301,6 +4307,11 @@ implicit_conversion_error (location_t loc, tree type, tree expr) instantiate_type (type, expr, complain); else if (invalid_nonstatic_memfn_p (loc, expr, complain)) /* We gave an error. */; + else if (BRACE_ENCLOSED_INITIALIZER_P (expr) + && CONSTRUCTOR_IS_DESIGNATED_INIT (expr) + && !CP_AGGREGATE_TYPE_P (type)) + error_at (loc, "designated initializers cannot be used with a " + "non-aggregate type %qT", type); else { range_label_for_type_mismatch label (TREE_TYPE (expr), type); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index b8bd09b37e6..577643a1523 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -6668,6 +6668,15 @@ check_initializer (tree decl, tree init, int flags, vec<tree, va_gc> **cleanups) return NULL_TREE; } } + else if (CONSTRUCTOR_IS_DESIGNATED_INIT (init) + && !CP_AGGREGATE_TYPE_P (type)) + { + error_at (cp_expr_loc_or_loc (init, DECL_SOURCE_LOCATION (decl)), + "designated initializers cannot be used with a " + "non-aggregate type %qT", type); + TREE_TYPE (decl) = error_mark_node; + return NULL_TREE; + } } if (TREE_CODE (decl) == CONST_DECL) diff --git a/gcc/cp/init.c b/gcc/cp/init.c index ef4b3c4dc3c..de261cfe7a6 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -1802,6 +1802,16 @@ build_aggr_init (tree exp, tree init, int flags, tsubst_flags_t complain) TREE_TYPE (init) = itype; return stmt_expr; } + else if (init + && BRACE_ENCLOSED_INITIALIZER_P (init) + && CONSTRUCTOR_IS_DESIGNATED_INIT (init) + && !CP_AGGREGATE_TYPE_P (type)) + { + if (complain & tf_error) + error_at (init_loc, "designated initializers cannot be used with a " + "non-aggregate type %qT", type); + return error_mark_node; + } if (init && init != void_type_node && TREE_CODE (init) != TREE_LIST diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 64587c791c6..f25c4ec7110 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -2933,6 +2933,13 @@ finish_compound_literal (tree type, tree compound_literal, if (TYPE_NON_AGGREGATE_CLASS (type)) { + if (CONSTRUCTOR_IS_DESIGNATED_INIT (compound_literal)) + { + if (complain & tf_error) + error ("designated initializers cannot be used with a " + "non-aggregate type %qT", type); + return error_mark_node; + } /* Trying to deal with a CONSTRUCTOR instead of a TREE_LIST everywhere that deals with function arguments would be a pain, so just wrap it in a TREE_LIST. The parser set a flag so we know diff --git a/gcc/testsuite/g++.dg/cpp2a/desig11.C b/gcc/testsuite/g++.dg/cpp2a/desig11.C index d6895a7be56..a189fff2059 100644 --- a/gcc/testsuite/g++.dg/cpp2a/desig11.C +++ b/gcc/testsuite/g++.dg/cpp2a/desig11.C @@ -11,4 +11,4 @@ int bar (_Complex int); // { dg-message "initializing argument 1 of" } int y = bar ({.real = 0, .imag = 1}); // { dg-error "cannot convert" } int baz (std::initializer_list<int>); -int z = baz ({.one = 1, .two = 2, .three = 3}); // { dg-error "could not convert" } +int z = baz ({.one = 1, .two = 2, .three = 3}); // { dg-error "designated initializers" } diff --git a/gcc/testsuite/g++.dg/cpp2a/desig16.C b/gcc/testsuite/g++.dg/cpp2a/desig16.C new file mode 100644 index 00000000000..580115d985e --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/desig16.C @@ -0,0 +1,28 @@ +// PR c++/95369 +// { dg-do compile { target c++20 } } + +struct S { + unsigned a; + unsigned b; + constexpr S(unsigned _a, unsigned _b) noexcept: a{_a}, b{_b} { } +}; + +template<S s> struct X { }; +void g(S); + +struct Z { + S s; + Z() : s{.a = 1, .b = 2} { } // { dg-error "designated initializers" } +}; + +S +f() +{ + X<{.a = 1, .b = 2}> x; // { dg-error "designated initializers" } + S s{ .a = 1, .b = 2 }; // { dg-error "designated initializers" } + S s2 = { .a = 1, .b = 2 }; // { dg-error "designated initializers" } + S s3 = S{ .a = 1, .b = 2 }; // { dg-error "designated initializers" } + g({.a = 1, .b = 2}); // { dg-error "designated initializers" } + g(S{.a = 1, .b = 2}); // { dg-error "designated initializers" } + return {.a = 1, .b = 2}; // { dg-error "designated initializers" } +} base-commit: ec34277611416aacdfdf3b8469b8e6ed43f623e6 -- Marek Polacek • Red Hat, Inc. • 300 A St, Boston, MA