re PR tree-optimization/77291 (False positive for -Warray-bounds)
authorRichard Biener <rguenther@suse.de>
Mon, 18 Dec 2017 08:33:26 +0000 (08:33 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Mon, 18 Dec 2017 08:33:26 +0000 (08:33 +0000)
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

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/Warray-bounds-26.c [new file with mode: 0644]
gcc/tree.c

index 2a875d3ae7bb2a982f35177b6835a5aa5acf5007..c9a5f2123a1adeed58bbe635de77051027bbd1da 100644 (file)
@@ -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
index 5cb9c935b4dfba4aae5ffd13e7dc4cc33450861d..8fe9a88b33aaf541a341807a5b599dbc0bded56b 100644 (file)
@@ -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 (file)
index 0000000..85bdb3e
--- /dev/null
@@ -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" } */
+}
index b43a3fd7ace7301e622c2bb45eea6d8976490dae..65e945afe06cd166f799d8cc1fb6af68a504f082 100644 (file)
@@ -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;
 }