From 6464d9b18207d381568b0a5b5a953286ccd2a5b6 Mon Sep 17 00:00:00 2001 From: Martin Sebor Date: Fri, 5 Apr 2019 13:49:38 -0600 Subject: [PATCH] PR bootstrap/89980 - pointer initialization with empty string folded to zero gcc/cp/ChangeLog: PR bootstrap/89980 * decl.c (reshape_init_array_1): Avoid treating empty strings as zeros in array initializers. Use trivial_type_p () instead of TYPE_HAS_TRIVIAL_DFLT(). gcc/testsuite/ChangeLog: PR bootstrap/89980 * g++.dg/init/array52.C: New test. From-SVN: r270177 --- gcc/cp/ChangeLog | 7 ++ gcc/cp/decl.c | 12 ++-- gcc/testsuite/ChangeLog | 7 +- gcc/testsuite/g++.dg/init/array52.C | 100 ++++++++++++++++++++++++++++ 4 files changed, 120 insertions(+), 6 deletions(-) create mode 100644 gcc/testsuite/g++.dg/init/array52.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 6bfd26c6a2e..17c9aa712aa 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,10 @@ +2019-04-05 Martin Sebor + + PR bootstrap/89980 + * decl.c (reshape_init_array_1): Avoid treating empty strings + as zeros in array initializers. + Use trivial_type_p () instead of TYPE_HAS_TRIVIAL_DFLT(). + 2019-04-04 Jason Merrill PR c++/89948 - ICE with break in statement-expr. diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 400e1a274aa..2528a8cd670 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -5800,7 +5800,7 @@ reshape_init_array_1 (tree elt_type, tree max_index, reshape_iter *d, } /* Set to the index of the last element with a non-zero initializer. - Initializers for elements past this one can be dropped. */ + Zero initializers for elements past this one can be dropped. */ unsigned HOST_WIDE_INT last_nonzero = -1; /* Loop until there are no more initializers. */ for (index = 0; @@ -5820,7 +5820,11 @@ reshape_init_array_1 (tree elt_type, tree max_index, reshape_iter *d, if (!TREE_CONSTANT (elt_init)) TREE_CONSTANT (new_init) = false; - if (!initializer_zerop (elt_init)) + /* Pointers initialized to strings must be treated as non-zero + even if the string is empty. */ + tree init_type = TREE_TYPE (elt_init); + if ((POINTER_TYPE_P (elt_type) != POINTER_TYPE_P (init_type)) + || !initializer_zerop (elt_init)) last_nonzero = index; /* This can happen with an invalid initializer (c++/54501). */ @@ -5828,9 +5832,7 @@ reshape_init_array_1 (tree elt_type, tree max_index, reshape_iter *d, break; } - if (sized_array_p - && (!CLASS_TYPE_P (elt_type) - || TYPE_HAS_TRIVIAL_DFLT (elt_type))) + if (sized_array_p && trivial_type_p (elt_type)) { /* Strip trailing zero-initializers from an array of a trivial type of known size. They are redundant and get in the way diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 83fccaa6eab..dc6f911fc4f 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-04-05 Martin Sebor + + PR bootstrap/89980 + * g++.dg/init/array52.C: New test. + 2019-04-05 David Malcolm PR c/89985 @@ -12,7 +17,7 @@ 2019-04-05 Marek Polacek - PR c++/89973 - -Waddress-of-packed-member ICE with invalid conversion. + PR c++/89973 - -Waddress-of-packed-member ICE with invalid conversion. * g++.dg/warn/Waddress-of-packed-member2.C: New test. 2019-04-05 Richard Biener diff --git a/gcc/testsuite/g++.dg/init/array52.C b/gcc/testsuite/g++.dg/init/array52.C new file mode 100644 index 00000000000..e7b4cb394ad --- /dev/null +++ b/gcc/testsuite/g++.dg/init/array52.C @@ -0,0 +1,100 @@ +// PR c++/89980 - pointer initialization with empty string folded to zero +// { dg-do compile } +// { dg-options "-O2 -Wall -fdump-tree-optimized" } + +#if __cplusplus >= 201103L + +#define SA(e) static_assert (e, #e) + +static constexpr const char* const ca1[2] = { "" }; + +void fca1 (void) +{ + SA (ca1[0] && ca1[0][0] == 0 && ca1[1] == 0); +} + +static constexpr const char* const ca2[][2] = +{ + { }, { 0 }, { 0, 0 }, { "" }, { "", "" }, { "", 0 }, { 0, "" } +}; + +void fca2 (void) +{ + SA (ca2[0][0] == 0 && ca2[0][1] == 0); + SA (ca2[1][0] == 0 && ca2[1][1] == 0); + SA (ca2[2][0] == 0 && ca2[2][1] == 0); + + SA (ca2[3][0] && ca2[3][0][0] == 0 && ca2[3][1] == 0); + SA (ca2[4][0] && ca2[4][0][0] == 0 && ca2[4][1] && ca2[4][1][0] == 0); + SA (ca2[5][0] && ca2[5][0][0] == 0 && ca2[5][1] == 0); + SA (ca2[6][0] == 0 && ca2[6][1] && ca2[6][1][0] == 0); +} + +struct A +{ + const char *p; + char a[2]; +}; + +static constexpr A ca3[] = +{ + { }, { 0 }, { 0, "" }, { "" }, { "", "" } +}; + +void fca3 (void) +{ + SA (ca3[0].p == 0 && ca3[0].a[0] == 0 && ca3[0].a[1] == 0); + SA (ca3[1].p == 0 && ca3[1].a[0] == 0 && ca3[1].a[1] == 0); + SA (ca3[2].p == 0 && ca3[2].a[0] == 0 && ca3[2].a[1] == 0); + SA (ca3[3].p && ca3[3].p[0] == 0 && ca3[3].a[0] == 0 && ca3[3].a[1] == 0); + SA (ca3[4].p && ca3[4].p[0] == 0 && ca3[4].a[0] == 0 && ca3[4].a[1] == 0); +} + +#endif // C++ 11 and above + + +#define A(e) ((e) ? (void)0 : __builtin_abort ()) + +static const char* const a1[2] = { "" }; + +void fa1 (void) +{ + A (a1[0] && a1[0][0] == 0 && a1[1] == 0); +} + +static const char* const a2[][2] = +{ + { }, { 0 }, { 0, 0 }, { "" }, { "", "" }, { "", 0 }, { 0, "" } +}; + +void fa2 (void) +{ + A (a2[0][0] == 0 && a2[0][1] == 0); + A (a2[1][0] == 0 && a2[1][1] == 0); + A (a2[2][0] == 0 && a2[2][1] == 0); + + A (a2[3][0] && a2[3][0][0] == 0 && a2[3][1] == 0); + A (a2[4][0] && a2[4][0][0] == 0 && a2[4][1] && a2[4][1][0] == 0); + A (a2[5][0] && a2[5][0][0] == 0 && a2[5][1] == 0); + A (a2[6][0] == 0 && a2[6][1] && a2[6][1][0] == 0); +} + +struct B +{ + const char *p; + char a[2]; +}; + +static const B a3[] = +{ + { }, { 0 }, { 0, "" }, { "" }, { "", "" } +}; + +void fa3 (void) +{ + A (a3[0].p == 0 && a3[0].a[0] == 0 && a3[0].a[1] == 0); + A (a3[1].p == 0 && a3[1].a[0] == 0 && a3[1].a[1] == 0); + A (a3[2].p == 0 && a3[2].a[0] == 0 && a3[2].a[1] == 0); + A (a3[3].p && a3[3].p[0] == 0 && a3[3].a[0] == 0 && a3[3].a[1] == 0); + A (a3[4].p && a3[4].p[0] == 0 && a3[4].a[0] == 0 && a3[4].a[1] == 0); +} -- 2.30.2