diff options
author | Martin Sebor <msebor@redhat.com> | 2019-08-01 23:45:36 +0000 |
---|---|---|
committer | Martin Sebor <msebor@gcc.gnu.org> | 2019-08-01 17:45:36 -0600 |
commit | b74f15a88ee1a2b96784803f0e38c386796ee704 (patch) | |
tree | 7c4a96774ea3cef422ba9596824ceb090bf0ff21 /gcc/tree.c | |
parent | f3b4eae6c3ac560f28f2d1d209ae5e0e030f95fe (diff) | |
download | gcc-b74f15a88ee1a2b96784803f0e38c386796ee704.zip gcc-b74f15a88ee1a2b96784803f0e38c386796ee704.tar.gz gcc-b74f15a88ee1a2b96784803f0e38c386796ee704.tar.bz2 |
PR c++/90947 - Simple lookup table of array of strings is miscompiled
gcc/cp/ChangeLog:
PR c++/90947
* decl.c (reshape_init_array_1): Avoid truncating initializer
lists containing string literals.
gcc/testsuite/ChangeLog:
PR c++/90947
* c-c++-common/array-1.c: New test.
* g++.dg/abi/mangle73.C: New test.
* g++.dg/cpp2a/nontype-class23.C: New test.
* g++.dg/init/array53.C: New test.
gcc/ChangeLog:
PR c++/90947
* tree.c (type_initializer_zero_p): Define.
* tree.h (type_initializer_zero_p): New function.
From-SVN: r273989
Diffstat (limited to 'gcc/tree.c')
-rw-r--r-- | gcc/tree.c | 67 |
1 files changed, 67 insertions, 0 deletions
@@ -11376,6 +11376,73 @@ 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 |