re PR tree-optimization/64277 (Incorrect warning "array subscript is above array...
authorRichard Biener <rguenther@suse.de>
Thu, 16 Apr 2015 12:03:11 +0000 (12:03 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Thu, 16 Apr 2015 12:03:11 +0000 (12:03 +0000)
2015-04-16  Richard Biener  <rguenther@suse.de>

PR tree-optimization/64277
* tree-vrp.c (check_array_ref): Fix anti-range handling,
simplify upper bound handling.
(search_for_addr_array): Simplify.
(check_array_bounds): Handle ADDR_EXPRs here.
(check_all_array_refs): Simplify.

* gcc.dg/Warray-bounds-14.c: New testcase.
* gcc.dg/Warray-bounds-15.c: Likewise.
* c-c++-common/ubsan/bounds-4.c: Disable -Warray-bounds.
* c-c++-common/ubsan/bounds-6.c: Likewise.

From-SVN: r222146

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/c-c++-common/ubsan/bounds-4.c
gcc/testsuite/c-c++-common/ubsan/bounds-6.c
gcc/testsuite/gcc.dg/Warray-bounds-14.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/Warray-bounds-15.c [new file with mode: 0644]
gcc/tree-vrp.c

index 4b661d1c928081d1eb12516d5d9025d32227ec2a..c4d0c150736d038353433d0f0b2f02f77e459431 100644 (file)
@@ -1,3 +1,12 @@
+2015-04-16  Richard Biener  <rguenther@suse.de>
+
+       PR tree-optimization/64277
+       * tree-vrp.c (check_array_ref): Fix anti-range handling,
+       simplify upper bound handling.
+       (search_for_addr_array): Simplify.
+       (check_array_bounds): Handle ADDR_EXPRs here.
+       (check_all_array_refs): Simplify.
+
 2015-04-16  Uros Bizjak  <ubizjak@gmail.com>
 
        * config/i386/i386.c (print_reg): Rewrite function.
index f8e227965ebd544faf037142d9e2a5f820388dd8..5a217e7dc2c5890eb443405313d10d97e17a7189 100644 (file)
@@ -1,3 +1,11 @@
+2015-04-16  Richard Biener  <rguenther@suse.de>
+
+       PR tree-optimization/64277
+       * gcc.dg/Warray-bounds-14.c: New testcase.
+       * gcc.dg/Warray-bounds-15.c: Likewise.
+       * c-c++-common/ubsan/bounds-4.c: Disable -Warray-bounds.
+       * c-c++-common/ubsan/bounds-6.c: Likewise.
+
 2015-04-16  Renlin Li  <renlin.li@arm.com>
 
        * gcc.target/aarch64/unsigned-unsignedfloat.c: New.
index 7748780884c331a2d4cfd84af0c6747e0de3d7fc..88e7e14050ecd5ebc2572d097b50539d0ce9cd95 100644 (file)
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-fsanitize=bounds -Wall -Wextra -Wno-unused" } */
+/* { dg-options "-fsanitize=bounds -Wall -Wextra -Wno-array-bounds -Wno-unused" } */
 
 /* Initializers of TREE_STATICs aren't instrumented.
    But don't ICE on 'em.  */
@@ -11,7 +11,7 @@ int *gpi;
 int
 main (void)
 {
-  gpi = &A[4];
+  gpi = &A[4]; /* This will warn with -Warray-bounds, but only if VRP runs.  */
   static int *pi = &A[4];
   return 0;
 }
index aef2055fb3ced3e0f8600e59cb1847514e515f35..952354985d7f560406c99ffda2e891c4108a7c97 100644 (file)
@@ -1,5 +1,5 @@
 /* { dg-do run } */
-/* { dg-options "-fsanitize=bounds -Wall -Wextra" } */
+/* { dg-options "-fsanitize=bounds -Wall -Wextra -Wno-array-bounds" } */
 
 /* Test off-by-one.  */
 
@@ -24,7 +24,7 @@ main (void)
   a = &u[4].a[10]; // Error
   a = &u[3].a[9]; // OK
   a = &u[3].a[10]; // OK
-  a = &u[3].a[11]; // Error
+  a = &u[3].a[11]; // Error, warns with -Warray-bounds, but only if VRP runs
 
   return 0;
 }
diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-14.c b/gcc/testsuite/gcc.dg/Warray-bounds-14.c
new file mode 100644 (file)
index 0000000..f3a33f9
--- /dev/null
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -Warray-bounds" } */
+
+int a[10];
+int foo1 (int i)
+{
+  if (i < 0 || i > 9)
+    return a[i];  /* { dg-warning "outside array bounds" } */
+  return 0;
+}
+int foo2 (int i)
+{
+  if (i < 0 || i > 8)
+    return a[i];  /* { dg-bogus "outside array bounds" } */
+  return 0;
+}
+int *foo3 (int i)
+{
+  if (i < 0 || i > 10)
+    return &a[i];  /* { dg-warning "outside array bounds" } */
+  return (void *)0;
+}
+int *foo4 (int i)
+{
+  if (i < 0 || i > 9)
+    return &a[i];  /* { dg-bogus "outside array bounds" } */
+  return (void *)0;
+}
diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-15.c b/gcc/testsuite/gcc.dg/Warray-bounds-15.c
new file mode 100644 (file)
index 0000000..f50e5ee
--- /dev/null
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -Warray-bounds" } */
+
+int a[10];
+int *foo1 (int i)
+{
+  return &a[10]; /* { dg-bogus "above array bounds" } */
+}
+int *foo2 (int i)
+{
+  return &a[11]; /* { dg-warning "above array bounds" } */
+}
+int foo3 (int i)
+{
+  return a[9]; /* { dg-bogus "above array bounds" } */
+}
+int foo4 (int i)
+{
+  return a[10]; /* { dg-warning "above array bounds" } */
+}
index 23e48b1144d9e1bc1ca898acaa70ecc033141373..41d7316865a3a10c91f4c1ea6ae07eb45db3b856 100644 (file)
@@ -6565,6 +6565,14 @@ check_array_ref (location_t location, tree ref, bool ignore_off_by_one)
   up_bound_p1 = int_const_binop (PLUS_EXPR, up_bound,
                                 build_int_cst (TREE_TYPE (up_bound), 1));
 
+  /* Empty array.  */
+  if (tree_int_cst_equal (low_bound, up_bound_p1))
+    {
+      warning_at (location, OPT_Warray_bounds,
+                 "array subscript is above array bounds");
+      TREE_NO_WARNING (ref) = 1;
+    }
+
   if (TREE_CODE (low_sub) == SSA_NAME)
     {
       vr = get_value_range (low_sub);
@@ -6578,9 +6586,11 @@ check_array_ref (location_t location, tree ref, bool ignore_off_by_one)
   if (vr && vr->type == VR_ANTI_RANGE)
     {
       if (TREE_CODE (up_sub) == INTEGER_CST
-          && tree_int_cst_lt (up_bound, up_sub)
+          && (ignore_off_by_one
+             ? tree_int_cst_lt (up_bound, up_sub)
+             : tree_int_cst_le (up_bound, up_sub))
           && TREE_CODE (low_sub) == INTEGER_CST
-          && tree_int_cst_lt (low_sub, low_bound))
+          && tree_int_cst_le (low_sub, low_bound))
         {
           warning_at (location, OPT_Warray_bounds,
                      "array subscript is outside array bounds");
@@ -6589,10 +6599,8 @@ check_array_ref (location_t location, tree ref, bool ignore_off_by_one)
     }
   else if (TREE_CODE (up_sub) == INTEGER_CST
           && (ignore_off_by_one
-              ? (tree_int_cst_lt (up_bound, up_sub)
-                 && !tree_int_cst_equal (up_bound_p1, up_sub))
-              : (tree_int_cst_lt (up_bound, up_sub)
-                 || tree_int_cst_equal (up_bound_p1, up_sub))))
+              ? !tree_int_cst_le (up_sub, up_bound_p1)
+              : !tree_int_cst_le (up_sub, up_bound)))
     {
       if (dump_file && (dump_flags & TDF_DETAILS))
        {
@@ -6625,25 +6633,6 @@ check_array_ref (location_t location, tree ref, bool ignore_off_by_one)
 static void
 search_for_addr_array (tree t, location_t location)
 {
-  while (TREE_CODE (t) == SSA_NAME)
-    {
-      gimple g = SSA_NAME_DEF_STMT (t);
-
-      if (gimple_code (g) != GIMPLE_ASSIGN)
-       return;
-
-      if (get_gimple_rhs_class (gimple_assign_rhs_code (g))
-         != GIMPLE_SINGLE_RHS)
-       return;
-
-      t = gimple_assign_rhs1 (g);
-    }
-
-
-  /* We are only interested in addresses of ARRAY_REF's.  */
-  if (TREE_CODE (t) != ADDR_EXPR)
-    return;
-
   /* Check each ARRAY_REFs in the reference chain. */
   do
     {
@@ -6733,12 +6722,11 @@ check_array_bounds (tree *tp, int *walk_subtree, void *data)
   if (TREE_CODE (t) == ARRAY_REF)
     check_array_ref (location, t, false /*ignore_off_by_one*/);
 
-  if (TREE_CODE (t) == MEM_REF
-      || (TREE_CODE (t) == RETURN_EXPR && TREE_OPERAND (t, 0)))
-    search_for_addr_array (TREE_OPERAND (t, 0), location);
-
-  if (TREE_CODE (t) == ADDR_EXPR)
-    *walk_subtree = FALSE;
+  else if (TREE_CODE (t) == ADDR_EXPR)
+    {
+      search_for_addr_array (t, location);
+      *walk_subtree = FALSE;
+    }
 
   return NULL_TREE;
 }
@@ -6768,29 +6756,17 @@ check_all_array_refs (void)
        {
          gimple stmt = gsi_stmt (si);
          struct walk_stmt_info wi;
-         if (!gimple_has_location (stmt))
+         if (!gimple_has_location (stmt)
+             || is_gimple_debug (stmt))
            continue;
 
-         if (is_gimple_call (stmt))
-           {
-             size_t i;
-             size_t n = gimple_call_num_args (stmt);
-             for (i = 0; i < n; i++)
-               {
-                 tree arg = gimple_call_arg (stmt, i);
-                 search_for_addr_array (arg, gimple_location (stmt));
-               }
-           }
-         else
-           {
-             memset (&wi, 0, sizeof (wi));
-             wi.info = CONST_CAST (void *, (const void *)
-                                   gimple_location_ptr (stmt));
+         memset (&wi, 0, sizeof (wi));
+         wi.info = CONST_CAST (void *, (const void *)
+                               gimple_location_ptr (stmt));
 
-             walk_gimple_op (gsi_stmt (si),
-                             check_array_bounds,
-                             &wi);
-           }
+         walk_gimple_op (gsi_stmt (si),
+                         check_array_bounds,
+                         &wi);
        }
     }
 }