aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMarek Polacek <polacek@redhat.com>2020-06-15 15:31:32 -0400
committerMarek Polacek <polacek@redhat.com>2020-06-16 13:19:44 -0400
commit04afaf4575ff239279cfa34aff17101345451965 (patch)
treed091dc21ff9341deebe58246a414828e44ccb56d /gcc
parent2661635323bd44410f1a154683eccecd2c163b46 (diff)
downloadgcc-04afaf4575ff239279cfa34aff17101345451965.zip
gcc-04afaf4575ff239279cfa34aff17101345451965.tar.gz
gcc-04afaf4575ff239279cfa34aff17101345451965.tar.bz2
c++: Don't allow designated initializers with non-aggregates [PR95369]
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.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/call.c13
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/desig11.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/desig16.C28
3 files changed, 42 insertions, 1 deletions
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index b55dc83..1d95bd2 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 d6895a7..a189fff 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 0000000..3edb68d
--- /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" }
+}