aboutsummaryrefslogtreecommitdiff
path: root/gcc
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
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')
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.dg/Warray-bounds-26.c17
-rw-r--r--gcc/tree.c47
4 files changed, 57 insertions, 19 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 2a875d3..c9a5f21 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,10 @@
+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.
+
2017-12-17 Sandra Loosemore <sandra@codesourcery.com>
* doc/extend.texi (x86 Function Attributes): Reformat nocf_check
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 5cb9c93..8fe9a88 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2017-12-18 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/77291
+ * gcc.dg/Warray-bounds-26.c: New testcase.
+
2017-12-17 Uros Bizjak <ubizjak@gmail.com>
* gcc.dg/guality/guality.h (guality_check): Cast %lli arguments
diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-26.c b/gcc/testsuite/gcc.dg/Warray-bounds-26.c
new file mode 100644
index 0000000..85bdb3e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Warray-bounds-26.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -Warray-bounds" } */
+
+struct Rec {
+ unsigned char data[1]; // actually variable length
+};
+
+union U {
+ unsigned char buf[42];
+ struct Rec rec;
+};
+
+int Load()
+{
+ union U u;
+ return u.rec.data[1]; /* { dg-bogus "array bound" } */
+}
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;
}