[C++ PATCH] Fix a recent regression (PR c++/90947)
Jason Merrill
jason@redhat.com
Thu Oct 31 07:27:00 GMT 2019
On 10/30/19 7:29 PM, Jakub Jelinek wrote:
> On Tue, Oct 29, 2019 at 04:26:14PM -0400, Jason Merrill wrote:
>> I think type_initializer_zero_p should return false if
>> CLASSTYPE_NON_AGGREGATE; we can't expect that value-initialization will have
>> the intended effect in that case.
>
> That indeed works for this testcase and doesn't break anything else in the
> testsuite. I've actually used TYPE_NON_AGGREGATE_CLASS because a
> RECORD_TYPE might not be always a CLASS_TYPE_P.
>
> Here is what I've bootstrapped/regtested on x86_64-linux and i686-linux, ok
> for trunk?
OK.
> 2019-10-30 Jakub Jelinek <jakub@redhat.com>
>
> 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.
>
> --- gcc/tree.h.jj 2019-10-30 08:13:49.017848260 +0100
> +++ gcc/tree.h 2019-10-30 08:57:59.457046198 +0100
> @@ -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);
>
> --- gcc/tree.c.jj 2019-10-30 08:13:48.974848922 +0100
> +++ gcc/tree.c 2019-10-30 08:57:59.460046152 +0100
> @@ -11396,73 +11396,6 @@ initializer_each_zero_or_onep (const_tre
> }
> }
>
> -/* 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
> --- gcc/cp/cp-tree.h.jj 2019-10-30 08:13:48.819851308 +0100
> +++ gcc/cp/cp-tree.h 2019-10-30 08:57:59.462046121 +0100
> @@ -7380,6 +7380,11 @@ extern tree cxx_copy_lang_qualifiers (c
>
> 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);
> --- gcc/cp/decl.c.jj 2019-10-30 08:13:48.885850291 +0100
> +++ gcc/cp/decl.c 2019-10-30 08:57:59.466046060 +0100
> @@ -5972,9 +5972,8 @@ reshape_init_array_1 (tree elt_type, tre
> /* 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). */
> --- gcc/cp/tree.c.jj 2019-10-30 08:13:48.777851956 +0100
> +++ gcc/cp/tree.c 2019-10-30 09:17:23.743135729 +0100
> @@ -5541,6 +5541,68 @@ maybe_warn_zero_as_null_pointer_constant
> 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. */
> --- gcc/testsuite/g++.dg/init/array54.C.jj 2019-10-30 09:21:12.676608668 +0100
> +++ gcc/testsuite/g++.dg/init/array54.C 2019-10-30 09:26:42.813522422 +0100
> @@ -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 ();
> +}
>
>
> Jakub
>
More information about the Gcc-patches
mailing list