aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2019-10-31 08:10:57 +0100
committerJakub Jelinek <jakub@gcc.gnu.org>2019-10-31 08:10:57 +0100
commitfbdbe8b06a1c5626ad6360a4af33cb638c14cda1 (patch)
tree6f3b3270e66eb2e75172648e9848a118150d9d5e /gcc/cp
parente4c431266f9aaf604edfca68e852ae8efe966e8e (diff)
downloadgcc-fbdbe8b06a1c5626ad6360a4af33cb638c14cda1.zip
gcc-fbdbe8b06a1c5626ad6360a4af33cb638c14cda1.tar.gz
gcc-fbdbe8b06a1c5626ad6360a4af33cb638c14cda1.tar.bz2
re PR c++/90947 (Simple lookup table of array of strings is miscompiled)
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
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/ChangeLog9
-rw-r--r--gcc/cp/cp-tree.h5
-rw-r--r--gcc/cp/decl.c5
-rw-r--r--gcc/cp/tree.c62
4 files changed, 78 insertions, 3 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 585420a..31f251c 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 42e03a3..42d5111 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -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);
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 8320597..72acc8f 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -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). */
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index ca4d3e2..a4b8b00 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -5540,6 +5540,68 @@ maybe_warn_zero_as_null_pointer_constant (tree expr, location_t loc)
return false;
}
+/* 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;
+}
+
#if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007)
/* Complain that some language-specific thing hanging off a tree
node has been accessed improperly. */