aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Sebor <msebor@redhat.com>2020-03-04 18:19:31 -0700
committerMartin Sebor <msebor@redhat.com>2020-03-04 18:19:31 -0700
commitcb2409c60aeff498064346f85165531a3bbead14 (patch)
treed4339dd2f882ebf991d3047bd9549683abc233c1
parent547cdf8510a0096d5d6e4d54f0e3fe51d7b70e13 (diff)
PR c++/90938 - Initializing array with {1} works but not {0}
gcc/cp/ChangeLog: PR c++/90938 * tree.c (type_initializer_zero_p): Fail for structs initialized with non-structs. gcc/testsuite/ChangeLog: PR c++/90938 * g++.dg/init/array55.C: New test. * g++.dg/init/array56.C: New test. * g++.dg/cpp2a/nontype-class33.C: New test.
-rw-r--r--gcc/cp/ChangeLog6
-rw-r--r--gcc/cp/tree.c10
-rw-r--r--gcc/testsuite/ChangeLog7
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/nontype-class33.C36
-rw-r--r--gcc/testsuite/g++.dg/init/array55.C27
-rw-r--r--gcc/testsuite/g++.dg/init/array56.C107
6 files changed, 192 insertions, 1 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 254e5a31096..f01563e96fc 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,9 @@
+2020-03-04 Martin Sebor <msebor@redhat.com>
+
+ PR c++/90938
+ * tree.c (type_initializer_zero_p): Fail for structs initialized
+ with non-structs.
+
2020-03-04 Jason Merrill <jason@redhat.com>
PR c++/90432
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 3fc6287d566..a412345e3bf 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -5727,7 +5727,15 @@ type_initializer_zero_p (tree type, tree init)
return TREE_CODE (init) != STRING_CST && initializer_zerop (init);
if (TREE_CODE (init) != CONSTRUCTOR)
- return initializer_zerop (init);
+ {
+ /* A class can only be initialized by a non-class type if it has
+ a ctor that converts from that type. Such classes are excluded
+ since their semantics are unknown. */
+ if (RECORD_OR_UNION_TYPE_P (type)
+ && !RECORD_OR_UNION_TYPE_P (TREE_TYPE (init)))
+ return false;
+ return initializer_zerop (init);
+ }
if (TREE_CODE (type) == ARRAY_TYPE)
{
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 468f7673e29..95c8710800b 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,12 @@
2020-03-04 Martin Sebor <msebor@redhat.com>
+ PR c++/90938
+ * g++.dg/init/array55.C: New test.
+ * g++.dg/init/array56.C: New test.
+ * g++.dg/cpp2a/nontype-class33.C: New test.
+
+2020-03-04 Martin Sebor <msebor@redhat.com>
+
PR tree-optimization/93986
* gcc.dg/pr93986.c: New test.
diff --git a/gcc/testsuite/g++.dg/cpp2a/nontype-class33.C b/gcc/testsuite/g++.dg/cpp2a/nontype-class33.C
new file mode 100644
index 00000000000..1b9dfb88918
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/nontype-class33.C
@@ -0,0 +1,36 @@
+// PR c++/90938 - Initializing array with {1} works, but not {0}
+// { dg-do compile { target c++2a } }
+// { dg-options "-Wall" }
+
+struct A { int i; };
+struct B { A a[2]; };
+
+static const constexpr A a0 = { 0 };
+static const constexpr A a_ = { };
+
+template <B> struct X { };
+
+typedef X<B{ }> XB;
+typedef X<B{{A{ }}}> XB;
+typedef X<B{{A{ 0 }}}> XB;
+typedef X<B{{a_}}> XB;
+typedef X<B{{a0}}> XB;
+typedef X<B{{a_, A{ }}}> XB;
+typedef X<B{{a_, A{ 0 }}}> XB;
+typedef X<B{{a_, a_}}> XB;
+typedef X<B{{a_, a0}}> XB;
+
+
+struct C { constexpr C () = default; };
+struct D { C c[2]; };
+
+static const constexpr C c_ = { };
+
+template <D> struct Y { };
+
+typedef Y<D{ }> YD;
+typedef Y<D{C { }}> YD;
+typedef Y<D{{c_}}> YD;
+typedef Y<D{C{ }, C{ }}> YD;
+typedef Y<D{C{ }, c_}> YD;
+typedef Y<D{{c_, c_}}> YD;
diff --git a/gcc/testsuite/g++.dg/init/array55.C b/gcc/testsuite/g++.dg/init/array55.C
new file mode 100644
index 00000000000..70fb183b897
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/array55.C
@@ -0,0 +1,27 @@
+/* PR c++/90938 - Initializing array with {1} works, but not {0}
+ { dg-do compile { target c++11 } } */
+
+struct A
+{
+ A () = delete;
+ A (int) = delete;
+};
+
+A a_[] = { 0 }; // { dg-error "use of deleted function 'A::A\\\(int\\\)'" }
+
+A a1[1] = { 0 }; // { dg-error "use of deleted function 'A::A\\\(int\\\)'" }
+
+
+struct B
+{
+ B () = delete;
+ B (int) = delete;
+ B (long);
+};
+
+B b_[] = { 0 }; // { dg-error "use of deleted function 'B::B\\\(int\\\)'" }
+
+B b1[1] = { 0 }; // { dg-error "use of deleted function 'B::B\\\(int\\\)'" }
+
+B b2[] = { 0L };
+B b3[1] = { 0L };
diff --git a/gcc/testsuite/g++.dg/init/array56.C b/gcc/testsuite/g++.dg/init/array56.C
new file mode 100644
index 00000000000..63e16663ec1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/array56.C
@@ -0,0 +1,107 @@
+/* PR c++/90938 - Initializing array with {1} works, but not {0}
+ { dg-do compile { target c++11 } }
+ { dg-options "-O -Wall -fdump-tree-optimized" } */
+
+#define assert(e) \
+ ((e) ? (void)0 \
+ : (__builtin_printf ("assertion failed on line %i: %s\n", \
+ __LINE__, #e), \
+ __builtin_abort ()))
+
+namespace A {
+
+struct X
+{
+ X () = default;
+ X (int n) : n (n + 1) { }
+ int n;
+};
+
+static_assert (__is_trivial (X), "X is trivial");
+
+static void test ()
+{
+ {
+ X x[] { 0 };
+ assert (1 == x->n);
+ }
+
+ {
+ X x[1] { 0 };
+ assert (1 == x->n); // fails
+ }
+
+ {
+ X x[2] { 0 };
+ assert (1 == x[0].n && 0 == x[1].n); // fails
+ }
+
+ {
+ X x[] { 1, 0 };
+ assert (2 == x[0].n && 1 == x[1].n); // passes
+ }
+
+ {
+ X x[2] { 1, 0 };
+ assert (2 == x[0].n && 1 == x[1].n); // fails
+ }
+}
+
+}
+
+namespace B {
+
+struct X
+{
+ X () = default;
+ X (int *p) : p (p ? p : new int (1)) { }
+ int *p;
+};
+
+static_assert (__is_trivial (X), "X is trivial");
+
+static void test ()
+{
+ X x[1] { nullptr };
+ assert (*x->p == 1); // fails
+
+ X y[1] { 0 };
+ assert (*y->p == 1); // fails
+}
+
+}
+
+namespace C {
+
+static const char *vector_swizzle (int vecsize, int index)
+{
+ static const char *swizzle[4][4] =
+ {
+ { ".x", ".y", ".z", ".w" },
+ { ".xy", ".yz", ".zw", nullptr },
+ { ".xyz", ".yzw", nullptr, nullptr },
+ { "", nullptr, nullptr, nullptr },
+ };
+
+ assert (vecsize >= 1 && vecsize <= 4);
+ assert (index >= 0 && index < 4);
+ assert (swizzle[vecsize - 1][index]);
+
+ return swizzle[vecsize - 1][index];
+}
+
+static void test ()
+{
+ assert (!*vector_swizzle(4, 0));
+}
+
+}
+
+int main ()
+{
+ A::test ();
+ B::test ();
+ C::test ();
+}
+
+// { dg-final { scan-tree-dump-not "abort" "optimized" } }