The following applies the patch produced earlier this year, applying
TLC to array bound warnings and catching a few more cases.

Bootstrapped and tested on x86_64-unknown-linux-gnu, applied.

Richard.

2015-04-16  Richard Biener  <rguent...@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-12.c: New testcase.
        * gcc.dg/Warray-bounds-13.c: Likewise.
        * c-c++-common/ubsan/bounds-4.c: Disable -Warray-bounds.
        * c-c++-common/ubsan/bounds-6.c: Likewise.

Index: gcc/tree-vrp.c
===================================================================
*** gcc/tree-vrp.c.orig 2015-01-27 10:47:58.812933951 +0100
--- gcc/tree-vrp.c      2015-01-27 11:18:02.129291796 +0100
*************** check_array_ref (location_t location, tr
*** 6533,6538 ****
--- 6533,6546 ----
    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);
*************** check_array_ref (location_t location, tr
*** 6546,6554 ****
    if (vr && vr->type == VR_ANTI_RANGE)
      {
        if (TREE_CODE (up_sub) == INTEGER_CST
!           && tree_int_cst_lt (up_bound, up_sub)
            && TREE_CODE (low_sub) == INTEGER_CST
!           && tree_int_cst_lt (low_sub, low_bound))
          {
            warning_at (location, OPT_Warray_bounds,
                      "array subscript is outside array bounds");
--- 6554,6564 ----
    if (vr && vr->type == VR_ANTI_RANGE)
      {
        if (TREE_CODE (up_sub) == INTEGER_CST
!           && (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_le (low_sub, low_bound))
          {
            warning_at (location, OPT_Warray_bounds,
                      "array subscript is outside array bounds");
*************** check_array_ref (location_t location, tr
*** 6557,6566 ****
      }
    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))))
      {
        if (dump_file && (dump_flags & TDF_DETAILS))
        {
--- 6567,6574 ----
      }
    else if (TREE_CODE (up_sub) == INTEGER_CST
           && (ignore_off_by_one
!              ? !tree_int_cst_le (up_sub, up_bound_p1)
!              : !tree_int_cst_le (up_sub, up_bound)))
      {
        if (dump_file && (dump_flags & TDF_DETAILS))
        {
*************** check_array_ref (location_t location, tr
*** 6593,6617 ****
  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
      {
--- 6601,6606 ----
*************** check_array_bounds (tree *tp, int *walk_
*** 6701,6712 ****
    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;
  
    return NULL_TREE;
  }
--- 6690,6700 ----
    if (TREE_CODE (t) == ARRAY_REF)
      check_array_ref (location, t, false /*ignore_off_by_one*/);
  
!   else if (TREE_CODE (t) == ADDR_EXPR)
!     {
!       search_for_addr_array (t, location);
!       *walk_subtree = FALSE;
!     }
  
    return NULL_TREE;
  }
*************** check_all_array_refs (void)
*** 6736,6764 ****
        {
          gimple stmt = gsi_stmt (si);
          struct walk_stmt_info wi;
!         if (!gimple_has_location (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));
! 
!             walk_gimple_op (gsi_stmt (si),
!                             check_array_bounds,
!                             &wi);
!           }
        }
      }
  }
--- 6724,6740 ----
        {
          gimple stmt = gsi_stmt (si);
          struct walk_stmt_info wi;
!         if (!gimple_has_location (stmt)
!             || is_gimple_debug (stmt))
            continue;
  
!         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);
        }
      }
  }
Index: gcc/testsuite/gcc.dg/Warray-bounds-12.c
===================================================================
*** gcc/testsuite/gcc.dg/Warray-bounds-12.c.orig        2015-01-27 
10:47:58.813933937 +0100
--- gcc/testsuite/gcc.dg/Warray-bounds-12.c     2015-01-27 10:53:02.737370976 
+0100
***************
*** 1,4 ****
--- 1,32 ----
  /* { 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;
+ }
+ /* { dg-do compile } */
  /* { dg-options "-O3 -Warray-bounds" } */
  /* { dg-additional-options "-mssse3" { target x86_64-*-* i?86-*-* } } */
  
Index: gcc/testsuite/gcc.dg/Warray-bounds-13.c
===================================================================
*** gcc/testsuite/gcc.dg/Warray-bounds-13.c.orig        2015-01-27 
10:47:58.814933926 +0100
--- gcc/testsuite/gcc.dg/Warray-bounds-13.c     2015-01-27 10:53:02.738370988 
+0100
***************
*** 1,4 ****
--- 1,24 ----
  /* { 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" } */
+ }
+ /* { dg-do compile } */
  /* { dg-options "-O3 -Warray-bounds" } */
  
  extern char *bar[17];
Index: gcc/testsuite/c-c++-common/ubsan/bounds-4.c
===================================================================
--- gcc/testsuite/c-c++-common/ubsan/bounds-4.c (revision 222140)
+++ gcc/testsuite/c-c++-common/ubsan/bounds-4.c (working copy)
@@ -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: gcc/testsuite/c-c++-common/ubsan/bounds-6.c
===================================================================
--- gcc/testsuite/c-c++-common/ubsan/bounds-6.c (revision 222140)
+++ gcc/testsuite/c-c++-common/ubsan/bounds-6.c (working copy)
@@ -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;
 }

Reply via email to