PR bootstrap/89980 - pointer initialization with empty string folded to zero
authorMartin Sebor <msebor@gcc.gnu.org>
Fri, 5 Apr 2019 19:49:38 +0000 (13:49 -0600)
committerMartin Sebor <msebor@gcc.gnu.org>
Fri, 5 Apr 2019 19:49:38 +0000 (13:49 -0600)
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
gcc/cp/decl.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/init/array52.C [new file with mode: 0644]

index 6bfd26c6a2e061bd8c69c06d3e8552bbc429bcb3..17c9aa712aa65fa938fa9b8d03820f0ecc3ef3d4 100644 (file)
@@ -1,3 +1,10 @@
+2019-04-05  Martin Sebor  <msebor@redhat.com>
+
+       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  <jason@redhat.com>
 
        PR c++/89948 - ICE with break in statement-expr.
index 400e1a274aa36804626d63eff8503de72b01a5b0..2528a8cd670f57d9594ea25b8a8c22d80e184969 100644 (file)
@@ -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
index 83fccaa6eabc416e7511dec45ff2dc092429fafa..dc6f911fc4ff55772a361b6a24522229935652ae 100644 (file)
@@ -1,3 +1,8 @@
+2019-04-05  Martin Sebor  <msebor@redhat.com>
+
+       PR bootstrap/89980
+       * g++.dg/init/array52.C: New test.
+
 2019-04-05  David Malcolm  <dmalcolm@redhat.com>
 
        PR c/89985
@@ -12,7 +17,7 @@
 
 2019-04-05  Marek Polacek  <polacek@redhat.com>
 
-       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  <rguenther@suse.de>
diff --git a/gcc/testsuite/g++.dg/init/array52.C b/gcc/testsuite/g++.dg/init/array52.C
new file mode 100644 (file)
index 0000000..e7b4cb3
--- /dev/null
@@ -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);
+}