aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree.c
diff options
context:
space:
mode:
authorRichard Biener <rguenther@suse.de>2017-12-18 08:33:26 +0000
committerRichard Biener <rguenth@gcc.gnu.org>2017-12-18 08:33:26 +0000
commit8c3563f392007b60a07d4c6d3c335355e19f3135 (patch)
tree32629a20d90cf5322cdbb3af02b73c4748820461 /gcc/tree.c
parent040a4493a64b308366d1d2fcb5611143d90c3c6d (diff)
downloadgcc-8c3563f392007b60a07d4c6d3c335355e19f3135.zip
gcc-8c3563f392007b60a07d4c6d3c335355e19f3135.tar.gz
gcc-8c3563f392007b60a07d4c6d3c335355e19f3135.tar.bz2
re PR tree-optimization/77291 (False positive for -Warray-bounds)
2017-12-18 Richard Biener <rguenther@suse.de> PR middle-end/77291 * tree.c (array_at_struct_end_p): Return true if the underlying object has space for at least one element in excess of what the array domain specifies. * gcc.dg/Warray-bounds-26.c: New testcase. From-SVN: r255775
Diffstat (limited to 'gcc/tree.c')
-rw-r--r--gcc/tree.c47
1 files changed, 28 insertions, 19 deletions
diff --git a/gcc/tree.c b/gcc/tree.c
index b43a3fd..65e945a 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -12644,6 +12644,7 @@ array_at_struct_end_p (tree ref)
if (TREE_CODE (ref) == STRING_CST)
return false;
+ tree ref_to_array = ref;
while (handled_component_p (ref))
{
/* If the reference chain contains a component reference to a
@@ -12682,35 +12683,43 @@ array_at_struct_end_p (tree ref)
/* The array now is at struct end. Treat flexible arrays as
always subject to extend, even into just padding constrained by
an underlying decl. */
- if (! TYPE_SIZE (atype))
+ if (! TYPE_SIZE (atype)
+ || ! TYPE_DOMAIN (atype)
+ || ! TYPE_MAX_VALUE (TYPE_DOMAIN (atype)))
return true;
- tree size = NULL;
-
if (TREE_CODE (ref) == MEM_REF
&& TREE_CODE (TREE_OPERAND (ref, 0)) == ADDR_EXPR)
- {
- size = TYPE_SIZE (TREE_TYPE (ref));
- ref = TREE_OPERAND (TREE_OPERAND (ref, 0), 0);
- }
+ ref = TREE_OPERAND (TREE_OPERAND (ref, 0), 0);
/* If the reference is based on a declared entity, the size of the array
is constrained by its given domain. (Do not trust commons PR/69368). */
if (DECL_P (ref)
- /* Be sure the size of MEM_REF target match. For example:
-
- char buf[10];
- struct foo *str = (struct foo *)&buf;
-
- str->trailin_array[2] = 1;
+ && !(flag_unconstrained_commons
+ && VAR_P (ref) && DECL_COMMON (ref))
+ && DECL_SIZE_UNIT (ref)
+ && TREE_CODE (DECL_SIZE_UNIT (ref)) == INTEGER_CST)
+ {
+ /* Check whether the array domain covers all of the available
+ padding. */
+ HOST_WIDE_INT offset;
+ if (TREE_CODE (TYPE_SIZE_UNIT (TREE_TYPE (atype))) != INTEGER_CST
+ || TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (atype))) != INTEGER_CST
+ || TREE_CODE (TYPE_MIN_VALUE (TYPE_DOMAIN (atype))) != INTEGER_CST)
+ return true;
+ if (! get_addr_base_and_unit_offset (ref_to_array, &offset))
+ return true;
- is valid because BUF allocate enough space. */
+ /* If at least one extra element fits it is a flexarray. */
+ if (wi::les_p ((wi::to_offset (TYPE_MAX_VALUE (TYPE_DOMAIN (atype)))
+ - wi::to_offset (TYPE_MIN_VALUE (TYPE_DOMAIN (atype)))
+ + 2)
+ * wi::to_offset (TYPE_SIZE_UNIT (TREE_TYPE (atype))),
+ wi::to_offset (DECL_SIZE_UNIT (ref)) - offset))
+ return true;
- && (!size || (DECL_SIZE (ref) != NULL
- && operand_equal_p (DECL_SIZE (ref), size, 0)))
- && !(flag_unconstrained_commons
- && VAR_P (ref) && DECL_COMMON (ref)))
- return false;
+ return false;
+ }
return true;
}