public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH][RFC] Add a subset of -Warray-bounds warnings to C/C++ front ends
@ 2008-04-04  1:04 Simon Baldwin
  2008-04-04  9:59 ` Richard Guenther
  2008-04-08 16:07 ` Dirk Mueller
  0 siblings, 2 replies; 28+ messages in thread
From: Simon Baldwin @ 2008-04-04  1:04 UTC (permalink / raw)
  To: gcc-patches

Attached below is a modest patch to provide a subset of the -Warray-bounds
warnings from tree-vrp.c in the C and C++ front ends.  This permits the
compiler to warn about egregious array bounds violations in unoptimized
compilations or compilations that may use -fno-tree-vrp.  At present, array
bounds checking is only done on optimized compilations.

A side effect of copying these warnings up into the language frontends is
that warnings are now printed even if the array access is in dead or
inaccessible code.

The current array bounds tests are modified to account for this new checking,
and additionally there are two new tests for warnings from -O0 compilations,
one for C and one for C++.

Bootstrapped, and regression tested on i686 Linux for gcc and g++.

Thoughts?  Okay for trunk?


:ADDPATCH diagnostic:

gcc/ChangeLog
2008-04-03  Simon Baldwin <simonb@google.com>

	* c-typeck.c (build_array_ref): Added array bounds checking for
	bounded arrays indexed by constants.

gcc/cp/ChangeLog
2008-04-03  Simon Baldwin <simonb@google.com>

	* typeck.c (build_array_ref): Added array bounds checking for
	bounded arrays indexed by constants.

gcc/testsuite/ChangeLog
2008-04-03  Simon Baldwin <simonb@google.com>
  
	* testsuite/gcc.dg/Warray-bounds.c: Updated for frontend warnings.
	* testsuite/g++.dg/warn/Warray-bounds.c: Updated for frontend warnings.
	* testsuite/gcc.dg/Warray-bounds-noopt.c: New testcase.
	* testsuite/g++.dg/warn/Warray-bounds-noopt.c: New testcase.


Index: gcc/doc/invoke.texi
===================================================================
--- gcc/doc/invoke.texi	(revision 133772)
+++ gcc/doc/invoke.texi	(working copy)
@@ -2658,7 +2658,7 @@
 @option{-Wall} turns on the following warning flags:
 
 @gccoptlist{-Waddress   @gol
--Warray-bounds @r{(only with} @option{-O2}@r{)}  @gol
+-Warray-bounds @r{(some checks, but more complete with} @option{-O2}@r{)}  @gol
 -Wc++0x-compat  @gol
 -Wchar-subscripts  @gol
 -Wimplicit-int  @gol
@@ -3361,7 +3361,8 @@
 @item -Warray-bounds
 @opindex Wno-array-bounds
 @opindex Warray-bounds
-This option is only active when @option{-ftree-vrp} is active
+This option performs a subset of checks in unoptimized compilations, and
+stricter checking when @option{-ftree-vrp} is active
 (default for -O2 and above). It warns about subscripts to arrays
 that are always out of bounds. This warning is enabled by @option{-Wall}.
 
Index: gcc/testsuite/gcc.dg/Warray-bounds.c
===================================================================
--- gcc/testsuite/gcc.dg/Warray-bounds.c	(revision 133772)
+++ gcc/testsuite/gcc.dg/Warray-bounds.c	(working copy)
@@ -56,13 +56,13 @@
     g(&a[8]);
     g(&a[9]);
     g(&a[10]);
-    g(&a[11]);             /* { dg-warning "array subscript" "" { xfail *-*-* } } */
-    g(&a[-30]+10);             /* { dg-warning "array subscript" } */
-    g(&a[-30]+30);
+    g(&a[11]);             /* { dg-warning "array subscript" } */
+    g(&a[-30]+10);         /* { dg-warning "array subscript" } */
+    g(&a[-30]+30);         /* { dg-warning "array subscript" } */
 
     g(&b[10]);
     g(&c.c[10]);
-    g(&b[11]);             /* { dg-warning "array subscript" "" { xfail *-*-* } } */
+    g(&b[11]);             /* { dg-warning "array subscript" } */
     g(&c.c[11]);           /* { dg-warning "array subscript" } */
 
     g(&a[0]);
@@ -71,11 +71,11 @@
 
     g(&a[-1]);             /* { dg-warning "array subscript" } */
     g(&b[-1]);             /* { dg-warning "array subscript" } */ 
-    h(sizeof a[-1]);
+    h(sizeof a[-1]);       /* { dg-warning "array subscript" } */
     h(sizeof a[10]);
-    h(sizeof b[-1]);
+    h(sizeof b[-1]);       /* { dg-warning "array subscript" } */
     h(sizeof b[10]);
-    h(sizeof c.c[-1]);
+    h(sizeof c.c[-1]);     /* { dg-warning "array subscript" } */
     h(sizeof c.c[10]);
 
     if (10 < 10)
@@ -83,11 +83,10 @@
     if (10 < 10)
        b[10] = 0;
     if (-1 >= 0)
-       c.c[-1] = 0;
+       c.c[-1] = 0;        /* { dg-warning "array subscript" } */
 
     for (i = 20; i < 30; ++i)
              a[i] = 1;       /* { dg-warning "array subscript" } */
 
     return a;
 }
-
Index: gcc/testsuite/g++.dg/warn/Warray-bounds.C
===================================================================
--- gcc/testsuite/g++.dg/warn/Warray-bounds.C	(revision 133772)
+++ gcc/testsuite/g++.dg/warn/Warray-bounds.C	(working copy)
@@ -57,12 +57,11 @@
     g(&a[9]);
     g(&a[10]);
     g(&a[11]);             /* { dg-warning "array subscript" } */
-    g(&a[-30]+10);             /* { dg-warning "array subscript" } */
-    g(&a[-30]+30);
+    g(&a[-30]+10);         /* { dg-warning "array subscript" } */
+    g(&a[-30]+30);         /* { dg-warning "array subscript" } */
 
     g(&b[10]);
     g(&c.c[10]);
-    g(&a[11]);             /* { dg-warning "array subscript" } */
     g(&b[11]);             /* { dg-warning "array subscript" } */
     g(&c.c[11]);           /* { dg-warning "array subscript" } */
 
@@ -72,11 +71,11 @@
 
     g(&a[-1]);             /* { dg-warning "array subscript" } */
     g(&b[-1]);             /* { dg-warning "array subscript" } */ 
-    h(sizeof a[-1]);
+    h(sizeof a[-1]);       /* { dg-warning "array subscript" } */
     h(sizeof a[10]);
-    h(sizeof b[-1]);
+    h(sizeof b[-1]);       /* { dg-warning "array subscript" } */
     h(sizeof b[10]);
-    h(sizeof c.c[-1]);
+    h(sizeof c.c[-1]);     /* { dg-warning "array subscript" } */
     h(sizeof c.c[10]);
 
     if (10 < 10)
@@ -84,8 +83,10 @@
     if (10 < 10)
        b[10] = 0;
     if (-1 >= 0)
-       c.c[-1] = 0;
+       c.c[-1] = 0;        /* { dg-warning "array subscript" } */
+
+    for (i = 20; i < 30; ++i)
+             a[i] = 1;       /* { dg-warning "array subscript" } */
 
     return a;
 }
-
Index: gcc/cp/typeck.c
===================================================================
--- gcc/cp/typeck.c	(revision 133772)
+++ gcc/cp/typeck.c	(working copy)
@@ -2554,7 +2554,8 @@
 
   if (TREE_CODE (TREE_TYPE (array)) == ARRAY_TYPE)
     {
-      tree rval, type;
+      bool has_warned_on_bounds_check = false;
+      tree rval, type, ref;
 
       warn_array_subscript_with_type_char (idx);
 
@@ -2571,6 +2572,48 @@
 	 pointer arithmetic.)  */
       idx = perform_integral_promotions (idx);
 
+      /* Warn about obvious array bounds errors for fixed size arrays that
+         are indexed by a constant.  This is a subset of similar checks in
+         tree-vrp.c; by doing this here we can get some level of checking
+         from non-optimized, non-vrp compilation.  */
+      if (TREE_CODE (idx) == INTEGER_CST && TYPE_DOMAIN (TREE_TYPE (array)))
+        {
+          const_tree max_index;
+
+          max_index = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (array)));
+          if (max_index && TREE_CODE (max_index) == INTEGER_CST
+              && tree_int_cst_lt (max_index, idx)
+              && !tree_int_cst_equal (idx, max_index)
+              /* Always allow off-by-one.  */
+              && !tree_int_cst_equal (int_const_binop (PLUS_EXPR,
+                                                       max_index,
+                                                       integer_one_node,
+                                                       0),
+                                      idx)
+              /* Accesses after the end of arrays of size 0 (gcc
+                 extension) and 1 are likely intentional ("struct
+                 hack").  */
+              && compare_tree_int (max_index, 1) > 0)
+            {
+              warning (OPT_Warray_bounds,
+                       "array subscript is above array bounds");
+              has_warned_on_bounds_check = true;
+            }
+          else
+            {
+              const_tree min_index;
+
+              min_index = TYPE_MIN_VALUE (TYPE_DOMAIN (TREE_TYPE (array)));
+              if (min_index && TREE_CODE (min_index) == INTEGER_CST
+                  && tree_int_cst_lt (idx, min_index))
+                {
+                  warning (OPT_Warray_bounds,
+                           "array subscript is below array bounds");
+                  has_warned_on_bounds_check = true;
+                }
+            }
+        }
+
       /* An array that is indexed by a non-constant
 	 cannot be stored in a register; we must be able to do
 	 address arithmetic on its address.
@@ -2621,7 +2664,12 @@
 	|= (CP_TYPE_VOLATILE_P (type) | TREE_SIDE_EFFECTS (array));
       TREE_THIS_VOLATILE (rval)
 	|= (CP_TYPE_VOLATILE_P (type) | TREE_THIS_VOLATILE (array));
-      return require_complete_type (fold_if_not_in_template (rval));
+      ref = require_complete_type (fold_if_not_in_template (rval));
+
+      /* Suppress bounds warning in tree-vrp.c if already warned here.  */
+      if (has_warned_on_bounds_check)
+        TREE_NO_WARNING (ref) = 1;
+      return ref;
     }
 
   {
Index: gcc/c-typeck.c
===================================================================
--- gcc/c-typeck.c	(revision 133772)
+++ gcc/c-typeck.c	(working copy)
@@ -2086,7 +2086,50 @@
 
   if (TREE_CODE (TREE_TYPE (array)) == ARRAY_TYPE)
     {
-      tree rval, type;
+      bool has_warned_on_bounds_check = false;
+      tree rval, type, ref;
+
+      /* Warn about obvious array bounds errors for fixed size arrays that
+         are indexed by a constant.  This is a subset of similar checks in
+         tree-vrp.c; by doing this here we can get some level of checking
+         from non-optimized, non-vrp compilation.  */
+      if (TREE_CODE (index) == INTEGER_CST && TYPE_DOMAIN (TREE_TYPE (array)))
+        {
+          const_tree max_index;
+
+          max_index = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (array)));
+          if (max_index && TREE_CODE (max_index) == INTEGER_CST
+              && tree_int_cst_lt (max_index, index)
+              && !tree_int_cst_equal (index, max_index)
+              /* Always allow off-by-one.  */
+              && !tree_int_cst_equal (int_const_binop (PLUS_EXPR,
+                                                       max_index,
+                                                       integer_one_node,
+                                                       0),
+                                      index)
+              /* Accesses after the end of arrays of size 0 (gcc
+                 extension) and 1 are likely intentional ("struct
+                 hack").  */
+              && compare_tree_int (max_index, 1) > 0)
+            {
+              warning (OPT_Warray_bounds,
+                       "array subscript is above array bounds");
+              has_warned_on_bounds_check = true;
+            }
+          else
+            {
+              const_tree min_index;
+
+              min_index = TYPE_MIN_VALUE (TYPE_DOMAIN (TREE_TYPE (array)));
+              if (min_index && TREE_CODE (min_index) == INTEGER_CST
+                  && tree_int_cst_lt (index, min_index))
+                {
+                  warning (OPT_Warray_bounds,
+                           "array subscript is below array bounds");
+                  has_warned_on_bounds_check = true;
+                }
+            }
+        }
 
       /* An array that is indexed by a non-constant
 	 cannot be stored in a register; we must be able to do
@@ -2139,7 +2182,12 @@
 	       in an inline function.
 	       Hope it doesn't break something else.  */
 	    | TREE_THIS_VOLATILE (array));
-      return require_complete_type (fold (rval));
+      ref = require_complete_type (fold (rval));
+
+      /* Suppress bounds warning in tree-vrp.c if already warned here.  */
+      if (has_warned_on_bounds_check)
+        TREE_NO_WARNING (ref) = 1;
+      return ref;
     }
   else
     {

^ permalink raw reply	[flat|nested] 28+ messages in thread

end of thread, other threads:[~2008-05-02 20:11 UTC | newest]

Thread overview: 28+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-04-04  1:04 [PATCH][RFC] Add a subset of -Warray-bounds warnings to C/C++ front ends Simon Baldwin
2008-04-04  9:59 ` Richard Guenther
2008-04-04 23:50   ` Simon Baldwin
2008-04-05  0:50     ` Andrew Pinski
2008-04-07 22:51       ` Simon Baldwin
2008-04-08  9:43         ` Richard Guenther
2008-04-08 15:39         ` Dirk Mueller
2008-04-08 15:21       ` Dirk Mueller
2008-04-10 18:05       ` Andrew Pinski
2008-04-08 19:42   ` Mark Mitchell
2008-04-11 20:37     ` Simon Baldwin
2008-04-15 19:18       ` Tom Tromey
2008-04-26 13:42       ` Simon Baldwin
2008-04-27 14:56         ` Mark Mitchell
2008-04-27 15:05           ` Joseph S. Myers
2008-05-01 19:07           ` Simon Baldwin
2008-05-02 12:51             ` H.J. Lu
2008-05-02 12:58               ` H.J. Lu
2008-05-02 14:06                 ` Mark Mitchell
2008-05-02 16:04                   ` H.J. Lu
2008-05-02 16:21                     ` Simon Baldwin
2008-05-02 16:35                       ` Mark Mitchell
2008-05-02 19:53                         ` Andrew Pinski
2008-05-02 20:01                           ` H.J. Lu
2008-05-02 20:04                             ` Simon Baldwin
2008-05-02 20:11                               ` H.J. Lu
2008-05-02 16:24                     ` Paul Koning
2008-04-08 16:07 ` Dirk Mueller

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).