]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR c++/90947 (Simple lookup table of array of strings is miscompiled)
authorJakub Jelinek <jakub@redhat.com>
Thu, 31 Oct 2019 07:10:57 +0000 (08:10 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Thu, 31 Oct 2019 07:10:57 +0000 (08:10 +0100)
PR c++/90947
* tree.h (type_initializer_zero_p): Remove.
* tree.c (type_initializer_zero_p): Remove.
cp/
* cp-tree.h (type_initializer_zero_p): Declare.
* decl.c (reshape_init_array_1): Formatting fix.
* tree.c (type_initializer_zero_p): New function.  Moved from
../tree.c, use next_initializable_field, formatting fix.  Return
false for TYPE_NON_AGGREGATE_CLASS types.

From-SVN: r277656

gcc/ChangeLog
gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/tree.c
gcc/testsuite/g++.dg/init/array54.C [new file with mode: 0644]
gcc/tree.c
gcc/tree.h

index d1a83f50d1281322ea050149fa77039cf9440bf0..9f454193905c5569bb508c0f805231117444faee 100644 (file)
@@ -1,3 +1,9 @@
+2019-10-31  Jakub Jelinek  <jakub@redhat.com>
+
+       PR c++/90947
+       * tree.h (type_initializer_zero_p): Remove.
+       * tree.c (type_initializer_zero_p): Remove.
+
 2019-10-30  Bernd Edlinger  <bernd.edlinger@hotmail.de>
 
        * doc/invoke.texi (-Wshadow, -Wshadow=global
index 585420a62c3c188c557e462c8903d2bd16519f1f..31f251c1b7e20fa2de303e1e99f282b4396c7f98 100644 (file)
@@ -1,3 +1,12 @@
+2019-10-31  Jakub Jelinek  <jakub@redhat.com>
+
+       PR c++/90947
+       * cp-tree.h (type_initializer_zero_p): Declare.
+       * decl.c (reshape_init_array_1): Formatting fix.
+       * tree.c (type_initializer_zero_p): New function.  Moved from
+       ../tree.c, use next_initializable_field, formatting fix.  Return
+       false for TYPE_NON_AGGREGATE_CLASS types.
+
 2019-10-30  Jason Merrill  <jason@redhat.com>
 
        PR c++/92268 - hard error satisfying return-type-requirement
index 42e03a31e20a2b23c9c7a8e03d519512e235c5c6..42d5111ac0fb3c600c655baab7f8c65f3d72bd7b 100644 (file)
@@ -7382,6 +7382,11 @@ extern tree cxx_copy_lang_qualifiers             (const_tree, const_tree);
 
 extern void cxx_print_statistics               (void);
 extern bool maybe_warn_zero_as_null_pointer_constant (tree, location_t);
+/* Analogous to initializer_zerop but also examines the type for
+   which the initializer is being used.  Unlike initializer_zerop,
+   considers empty strings to be zero initializers for arrays and
+   non-zero for pointers.  */
+extern bool type_initializer_zero_p            (tree, tree);
 
 /* in ptree.c */
 extern void cxx_print_xnode                    (FILE *, tree, int);
index 8320597c10884e82b9f98aa19bb84af0ac9b9993..72acc8f0224b3a96929bf0f6bdf6173754523c8f 100644 (file)
@@ -5973,9 +5973,8 @@ reshape_init_array_1 (tree elt_type, tree max_index, reshape_iter *d,
       /* 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)))
-       last_nonzero = index;
-      else if (!type_initializer_zero_p (elt_type, elt_init))
+      if (POINTER_TYPE_P (elt_type) != POINTER_TYPE_P (init_type)
+         || !type_initializer_zero_p (elt_type, elt_init))
        last_nonzero = index;
 
       /* This can happen with an invalid initializer (c++/54501).  */
index ca4d3e2a48bad424b4981fbbf6a1a1d0d2df3540..a4b8b00c92295a3f112eb64d40c34a070db6fb9b 100644 (file)
@@ -5540,6 +5540,68 @@ maybe_warn_zero_as_null_pointer_constant (tree expr, location_t loc)
   return false;
 }
 \f
+/* Given an initializer INIT for a TYPE, return true if INIT is zero
+   so that it can be replaced by value initialization.  This function
+   distinguishes betwen empty strings as initializers for arrays and
+   for pointers (which make it return false).  */
+
+bool
+type_initializer_zero_p (tree type, tree init)
+{
+  if (type == error_mark_node || init == error_mark_node)
+    return false;
+
+  STRIP_NOPS (init);
+
+  if (POINTER_TYPE_P (type))
+    return TREE_CODE (init) != STRING_CST && initializer_zerop (init);
+
+  if (TREE_CODE (init) != CONSTRUCTOR)
+    return initializer_zerop (init);
+
+  if (TREE_CODE (type) == ARRAY_TYPE)
+    {
+      tree elt_type = TREE_TYPE (type);
+      elt_type = TYPE_MAIN_VARIANT (elt_type);
+      if (elt_type == char_type_node)
+       return initializer_zerop (init);
+
+      tree elt_init;
+      unsigned HOST_WIDE_INT i;
+      FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (init), i, elt_init)
+       if (!type_initializer_zero_p (elt_type, elt_init))
+         return false;
+      return true;
+    }
+
+  if (TREE_CODE (type) != RECORD_TYPE)
+    return initializer_zerop (init);
+
+  if (TYPE_NON_AGGREGATE_CLASS (type))
+    return false;
+
+  tree fld = TYPE_FIELDS (type);
+
+  tree fld_init;
+  unsigned HOST_WIDE_INT i;
+  FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (init), i, fld_init)
+    {
+      fld = next_initializable_field (fld);
+      if (!fld)
+       return true;
+
+      tree fldtype = TREE_TYPE (fld);
+      if (!type_initializer_zero_p (fldtype, fld_init))
+       return false;
+
+      fld = DECL_CHAIN (fld);
+      if (!fld)
+       break;
+    }
+
+  return true;
+}
+\f
 #if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007)
 /* Complain that some language-specific thing hanging off a tree
    node has been accessed improperly.  */
diff --git a/gcc/testsuite/g++.dg/init/array54.C b/gcc/testsuite/g++.dg/init/array54.C
new file mode 100644 (file)
index 0000000..f6be350
--- /dev/null
@@ -0,0 +1,13 @@
+// PR c++/90947
+// { dg-do run { target c++11 } }
+
+#include <atomic>
+
+static std::atomic<int> a[1] { {1} };
+
+int
+main ()
+{
+  if (a[0].load () != 1)
+    __builtin_abort ();
+}
index ad477d3feb24192cfb6c990fbc84bad74c3d5c19..3866804b99dbc1b57955d4db2c6d3261d9be18d5 100644 (file)
@@ -11123,73 +11123,6 @@ initializer_each_zero_or_onep (const_tree expr)
     }
 }
 
-/* Given an initializer INIT for a TYPE, return true if INIT is zero
-   so that it can be replaced by value initialization.  This function
-   distinguishes betwen empty strings as initializers for arrays and
-   for pointers (which make it return false).  */
-
-bool
-type_initializer_zero_p (tree type, tree init)
-{
-  if (type  == error_mark_node || init == error_mark_node)
-    return false;
-
-  STRIP_NOPS (init);
-
-  if (POINTER_TYPE_P (type))
-    return TREE_CODE (init) != STRING_CST && initializer_zerop (init);
-
-  if (TREE_CODE (init) != CONSTRUCTOR)
-    return initializer_zerop (init);
-
-  if (TREE_CODE (type) == ARRAY_TYPE)
-    {
-      tree elt_type = TREE_TYPE (type);
-      elt_type = TYPE_MAIN_VARIANT (elt_type);
-      if (elt_type == char_type_node)
-       return initializer_zerop (init);
-
-      tree elt_init;
-      unsigned HOST_WIDE_INT i;
-      FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (init), i, elt_init)
-       if (!type_initializer_zero_p (elt_type, elt_init))
-         return false;
-      return true;
-    }
-
-  if (TREE_CODE (type) != RECORD_TYPE)
-    return initializer_zerop (init);
-
-  tree fld = TYPE_FIELDS (type);
-
-  tree fld_init;
-  unsigned HOST_WIDE_INT i;
-  FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (init), i, fld_init)
-    {
-      /* Advance to the next member, skipping over everything that
-        canot be initialized (including unnamed bit-fields).  */
-      while (TREE_CODE (fld) != FIELD_DECL
-            || DECL_ARTIFICIAL (fld)
-            || (DECL_BIT_FIELD (fld) && !DECL_NAME (fld)))
-       {
-         fld = DECL_CHAIN (fld);
-         if (!fld)
-           return true;
-         continue;
-       }
-
-      tree fldtype = TREE_TYPE (fld);
-      if (!type_initializer_zero_p (fldtype, fld_init))
-       return false;
-
-      fld = DECL_CHAIN (fld);
-      if (!fld)
-       break;
-    }
-
-  return true;
-}
-
 /* Check if vector VEC consists of all the equal elements and
    that the number of elements corresponds to the type of VEC.
    The function returns first element of the vector
index c825109b5f7e5a5be3421fc6ee6f62be67f8f2ab..18d6c0e0c21f14f54e3a0f9614bdfe0f5fd35536 100644 (file)
@@ -4690,12 +4690,6 @@ extern tree first_field (const_tree);
 extern bool initializer_zerop (const_tree, bool * = NULL);
 extern bool initializer_each_zero_or_onep (const_tree);
 
-/* Analogous to initializer_zerop but also examines the type for
-   which the initializer is being used.  Unlike initializer_zerop,
-   considers empty strings to be zero initializers for arrays and
-   non-zero for pointers.  */
-extern bool type_initializer_zero_p (tree, tree);
-
 extern wide_int vector_cst_int_elt (const_tree, unsigned int);
 extern tree vector_cst_elt (const_tree, unsigned int);