diff options
author | Martin Sebor <msebor@redhat.com> | 2020-03-04 18:32:40 -0700 |
---|---|---|
committer | Martin Sebor <msebor@redhat.com> | 2020-03-04 18:32:40 -0700 |
commit | 1665d97d37559ea7403d5b3e0efd5c5ae416e1ae (patch) | |
tree | 97feb0ca33c948cb816e2b3090ebce475597f266 | |
parent | 29bb27b7ef23e92151929f785dbad21c5d148bdc (diff) | |
download | gcc-1665d97d37559ea7403d5b3e0efd5c5ae416e1ae.tar.gz |
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/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/cp/tree.c | 10 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp2a/nontype-class33.C | 36 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/init/array55.C | 27 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/init/array56.C | 107 |
6 files changed, 192 insertions, 1 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index a9236063159..3f4c1b1f6a3 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 Marek Polacek <polacek@redhat.com> Backported from mainline diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 7275b7bf5b0..3f3583c825d 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -5509,7 +5509,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 db531c727e5..eca8fc03bea 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +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 Will Schmidt <will_schmidt@vnet.ibm.com> * gcc.target/powerpc/20050603-3.c: Remove XFAILS. 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" } } |