On Thu, Jun 11, 2020 at 06:15:26PM -0400, Jason Merrill via Gcc-patches wrote: > On 6/11/20 5:28 PM, Marek Polacek wrote: > > On Thu, Jun 11, 2020 at 03:51:29PM -0400, Jason Merrill wrote: > > > On 6/9/20 2:17 PM, Marek Polacek wrote: > > > > 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. > > > > > > Would it work to handle this only in add_list_candidates? > > > > 'fraid not -- we don't call add_list_candidates at all when compiling > > desig16.C. > > Hmm, why not? What is turning the CONSTRUCTOR into an argument vec?
Nevermind, I must've glossed over a local patch. This better patch implements your suggestion. I still changed implicit_conversion_error to give a better diagnostic but that should be fine. Thanks, Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk? -- >8 -- 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. There are multiple contexts where we can use designated initializers: function-like casts, member list initializers, NTTP, etc. I've adjusted add_list_candidates and implicit_conversion_error in order to to detect this case. gcc/cp/ChangeLog: PR c++/95369 * call.c (add_list_candidates): Return if a designated initializer is used with a non-aggregate. (implicit_conversion_error): Give an error for the case above. 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 | 13 +++++++++++++ gcc/testsuite/g++.dg/cpp2a/desig11.C | 2 +- gcc/testsuite/g++.dg/cpp2a/desig16.C | 28 ++++++++++++++++++++++++++++ 3 files changed, 42 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 b99959f76f9..1a54e9f4440 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -3952,6 +3952,14 @@ add_list_candidates (tree fns, tree first_arg, if (any_strictly_viable (*candidates)) return; } + else if (CONSTRUCTOR_IS_DESIGNATED_INIT (init_list) + && !CP_AGGREGATE_TYPE_P (totype)) + { + if (complain & tf_error) + error ("designated initializers cannot be used with a " + "non-aggregate type %qT", totype); + return; + } /* Expand the CONSTRUCTOR into a new argument vec. */ vec<tree, va_gc> *new_args; @@ -4301,6 +4309,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/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..3edb68d24a4 --- /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|no matching function" } +}; + +S +f() +{ + X<{.a = 1, .b = 2}> x; // { dg-error "designated initializers" } + S s{ .a = 1, .b = 2 }; // { dg-error "designated initializers|no matching function" } + S s2 = { .a = 1, .b = 2 }; // { dg-error "designated initializers" } + S s3 = S{ .a = 1, .b = 2 }; // { dg-error "designated initializers|no matching function" } + g({.a = 1, .b = 2}); // { dg-error "designated initializers" } + g(S{.a = 1, .b = 2}); // { dg-error "designated initializers|no matching function" } + return {.a = 1, .b = 2}; // { dg-error "designated initializers" } +} base-commit: c7bac01ab41f019a66bc07fc704752f436707eb8 -- Marek Polacek • Red Hat, Inc. • 300 A St, Boston, MA