diff options
author | Martin Sebor <msebor@redhat.com> | 2019-11-06 01:25:09 +0000 |
---|---|---|
committer | Martin Sebor <msebor@gcc.gnu.org> | 2019-11-05 18:25:09 -0700 |
commit | 91eb5fa8e1fae57f6d69b2b973ffdf1988d18ca1 (patch) | |
tree | 35311a912227df67c92d9e17b2e86ffc2784693a /gcc/tree.c | |
parent | eebabc49a3f5385d33cab235ec42e1ee0b5ca3c2 (diff) | |
download | gcc-91eb5fa8e1fae57f6d69b2b973ffdf1988d18ca1.zip gcc-91eb5fa8e1fae57f6d69b2b973ffdf1988d18ca1.tar.gz gcc-91eb5fa8e1fae57f6d69b2b973ffdf1988d18ca1.tar.bz2 |
PR tree-optimization/92373 - ICE in -Warray-bounds on access to member array in an initialized char buffer
gcc/testsuite/ChangeLog:
PR tree-optimization/92373
* gcc.dg/Warray-bounds-55.c: New test.
* gcc.dg/Wzero-length-array-bounds-2.c: New test.
gcc/ChangeLog:
PR tree-optimization/92373
* tree.c (component_ref_size): Only consider initializers of objects
of matching struct types.
Return null for instances of interior zero-length arrays.
From-SVN: r277871
Diffstat (limited to 'gcc/tree.c')
-rw-r--r-- | gcc/tree.c | 49 |
1 files changed, 27 insertions, 22 deletions
@@ -13635,6 +13635,8 @@ component_ref_size (tree ref, bool *interior_zero_length /* = NULL */) return NULL_TREE; base = TREE_OPERAND (ref, 0); + while (TREE_CODE (base) == COMPONENT_REF) + base = TREE_OPERAND (base, 0); baseoff = tree_to_poly_int64 (byte_position (TREE_OPERAND (ref, 1))); } @@ -13656,27 +13658,28 @@ component_ref_size (tree ref, bool *interior_zero_length /* = NULL */) memsize = NULL_TREE; - /* MEMBER is a true flexible array member. Compute its size from - the initializer of the BASE object if it has one. */ - if (tree init = DECL_P (base) ? DECL_INITIAL (base) : NULL_TREE) - { - init = get_initializer_for (init, member); - if (init) - { - memsize = TYPE_SIZE_UNIT (TREE_TYPE (init)); - if (tree refsize = TYPE_SIZE_UNIT (reftype)) - { - /* Use the larger of the initializer size and the tail - padding in the enclosing struct. */ - poly_int64 rsz = tree_to_poly_int64 (refsize); - rsz -= baseoff; - if (known_lt (tree_to_poly_int64 (memsize), rsz)) - memsize = wide_int_to_tree (TREE_TYPE (memsize), rsz); - } + if (typematch) + /* MEMBER is a true flexible array member. Compute its size from + the initializer of the BASE object if it has one. */ + if (tree init = DECL_P (base) ? DECL_INITIAL (base) : NULL_TREE) + { + init = get_initializer_for (init, member); + if (init) + { + memsize = TYPE_SIZE_UNIT (TREE_TYPE (init)); + if (tree refsize = TYPE_SIZE_UNIT (reftype)) + { + /* Use the larger of the initializer size and the tail + padding in the enclosing struct. */ + poly_int64 rsz = tree_to_poly_int64 (refsize); + rsz -= baseoff; + if (known_lt (tree_to_poly_int64 (memsize), rsz)) + memsize = wide_int_to_tree (TREE_TYPE (memsize), rsz); + } - baseoff = 0; - } - } + baseoff = 0; + } + } if (!memsize) { @@ -13689,17 +13692,19 @@ component_ref_size (tree ref, bool *interior_zero_length /* = NULL */) /* The size of a flexible array member of an extern struct with no initializer cannot be determined (it's defined in another translation unit and can have an initializer - witth an arbitrary number of elements). */ + with an arbitrary number of elements). */ return NULL_TREE; /* Use the size of the base struct or, for interior zero-length arrays, the size of the enclosing type. */ memsize = TYPE_SIZE_UNIT (bt); } - else + else if (DECL_P (base)) /* Use the size of the BASE object (possibly an array of some other type such as char used to store the struct). */ memsize = DECL_SIZE_UNIT (base); + else + return NULL_TREE; } /* If the flexible array member has a known size use the greater |