PR c++/90938 - Initializing array with {1} works but not {0}
authorMartin Sebor <msebor@redhat.com>
Thu, 5 Mar 2020 01:19:31 +0000 (18:19 -0700)
committerMartin Sebor <msebor@redhat.com>
Thu, 5 Mar 2020 01:19:31 +0000 (18:19 -0700)
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.

gcc/cp/ChangeLog
gcc/cp/tree.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp2a/nontype-class33.C [new file with mode: 0644]
gcc/testsuite/g++.dg/init/array55.C [new file with mode: 0644]
gcc/testsuite/g++.dg/init/array56.C [new file with mode: 0644]

index 254e5a3..f01563e 100644 (file)
@@ -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
index 3fc6287..a412345 100644 (file)
@@ -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)
     {
index 468f767..95c8710 100644 (file)
@@ -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 (file)
index 0000000..1b9dfb8
--- /dev/null
@@ -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 (file)
index 0000000..70fb183
--- /dev/null
@@ -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 (file)
index 0000000..63e1666
--- /dev/null
@@ -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" } }