diff options
-rw-r--r-- | gcc/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/cp/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 5 | ||||
-rw-r--r-- | gcc/cp/decl.c | 5 | ||||
-rw-r--r-- | gcc/cp/tree.c | 62 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/init/array54.C | 13 | ||||
-rw-r--r-- | gcc/tree.c | 67 | ||||
-rw-r--r-- | gcc/tree.h | 6 |
8 files changed, 97 insertions, 76 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d1a83f5..9f45419 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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 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. */ diff --git a/gcc/testsuite/g++.dg/init/array54.C b/gcc/testsuite/g++.dg/init/array54.C new file mode 100644 index 0000000..f6be350 --- /dev/null +++ b/gcc/testsuite/g++.dg/init/array54.C @@ -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 (); +} @@ -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 @@ -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); |