aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree.c
diff options
context:
space:
mode:
authorMartin Sebor <msebor@redhat.com>2019-11-06 01:25:09 +0000
committerMartin Sebor <msebor@gcc.gnu.org>2019-11-05 18:25:09 -0700
commit91eb5fa8e1fae57f6d69b2b973ffdf1988d18ca1 (patch)
tree35311a912227df67c92d9e17b2e86ffc2784693a /gcc/tree.c
parenteebabc49a3f5385d33cab235ec42e1ee0b5ca3c2 (diff)
downloadgcc-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.c49
1 files changed, 27 insertions, 22 deletions
diff --git a/gcc/tree.c b/gcc/tree.c
index 3299b34..d08141b 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -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