[PATCH][1/2] Improve array bound warnings

Richard Biener rguenther@suse.de
Mon Jan 26 15:32:00 GMT 2015


I've looked at PR64277 and noticed we haven't been applying TLC to the
array-bound warning code for a long time.  I noticed we don't
warn for out-of-bound return &a[11]; - fixed with the simplifications.
I also noticed that anti-range handling has off-by-one errors
(well, always applied ignore_off_by_one and to both ends of the array).

Bootstrap and regtest pending on x86_64-unknown-linux-gnu.

It doesn't help the testcase in PR64277 ([2/2] will somewhat).

Ok for trunk?  (seems we never warned for returning &a[11] and
anti-range handling was broken all the time)

I can as well queue this for GCC 6.

Thanks,
Richard.

2015-01-26  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-12.c: New testcase.
	* gcc.dg/Warray-bounds-13.c: Likewise.

Index: gcc/tree-vrp.c
===================================================================
*** gcc/tree-vrp.c	(revision 220107)
--- gcc/tree-vrp.c	(working copy)
*************** 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");
--- 6546,6556 ----
    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))
  	{
--- 6559,6566 ----
      }
    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
      {
--- 6593,6598 ----
*************** 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;
  }
--- 6682,6692 ----
    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);
! 	    }
  	}
      }
  }
--- 6716,6732 ----
  	{
  	  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	(revision 0)
--- gcc/testsuite/gcc.dg/Warray-bounds-12.c	(working copy)
***************
*** 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;
+ }
Index: gcc/testsuite/gcc.dg/Warray-bounds-13.c
===================================================================
*** gcc/testsuite/gcc.dg/Warray-bounds-13.c	(revision 0)
--- gcc/testsuite/gcc.dg/Warray-bounds-13.c	(working copy)
***************
*** 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" } */
+ }



More information about the Gcc-patches mailing list