PR middle-end/92341 - missing -Warray-bounds indexing past the end of a compound...
authorMartin Sebor <msebor@redhat.com>
Tue, 5 Nov 2019 16:20:44 +0000 (16:20 +0000)
committerMartin Sebor <msebor@gcc.gnu.org>
Tue, 5 Nov 2019 16:20:44 +0000 (09:20 -0700)
PR middle-end/92341 - missing -Warray-bounds indexing past the end of a compound literal
PR middle-end/82612 - missing -Warray-bounds on a non-zero offset from the address of a non-array object

gcc/testsuite/ChangeLog:

PR middle-end/92341
PR middle-end/82612
* g++.dg/warn/Warray-bounds-4.C: Adjust text of expected warning.
* gcc.dg/Warray-bounds-53.c: New test.
* gcc.dg/Warray-bounds-54.c: New test.

gcc/ChangeLog:

PR middle-end/92341
PR middle-end/82612
* tree-sra.c (get_access_for_expr): Fail for out-of-bounds offsets.
* tree-vrp.c (vrp_prop::check_array_ref): Correct index and text
of message printed in a warning for empty arrays.
(vrp_prop::check_mem_ref): Also handle function parameters and
empty arrays.

From-SVN: r277851

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/warn/Warray-bounds-4.C
gcc/testsuite/gcc.dg/Warray-bounds-53.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/Warray-bounds-54.c [new file with mode: 0644]
gcc/tree-sra.c
gcc/tree-vrp.c

index 21304fd..18247e7 100644 (file)
@@ -1,3 +1,13 @@
+2019-11-04  Martin Sebor  <msebor@redhat.com>
+
+       PR middle-end/92341
+       PR middle-end/82612
+       * tree-sra.c (get_access_for_expr): Fail for out-of-bounds offsets.
+       * tree-vrp.c (vrp_prop::check_array_ref): Correct index and text
+       of message printed in a warning for empty arrays.
+       (vrp_prop::check_mem_ref): Also handle function parameters and
+       empty arrays.
+
 2019-11-05  Richard Biener  <rguenther@suse.de>
 
        PR tree-optimization/92371
index 725cfa5..248d180 100644 (file)
@@ -1,3 +1,11 @@
+2019-11-04  Martin Sebor  <msebor@redhat.com>
+
+       PR middle-end/92341
+       PR middle-end/82612
+       * g++.dg/warn/Warray-bounds-4.C: Adjust text of expected warning.
+       * gcc.dg/Warray-bounds-53.c: New test.
+       * gcc.dg/Warray-bounds-54.c: New test.
+
 2019-11-05  Richard Biener  <rguenther@suse.de>
 
        PR tree-optimization/92371
index a4c4383..874aeee 100644 (file)
@@ -23,7 +23,7 @@ public:
   virtual void set(unsigned long index, char value) { contents[index] = value; }
   virtual char& operator[] (unsigned long index) { return contents[index]; }
 
-  FixedString() { contents[0] = '\0'; } // { dg-warning "above array bounds" }
+  FixedString() { contents[0] = '\0'; } // { dg-warning "\\\[-Warray-bounds" }
 };
 
 void print_length (const String& string);
diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-53.c b/gcc/testsuite/gcc.dg/Warray-bounds-53.c
new file mode 100644 (file)
index 0000000..0f06222
--- /dev/null
@@ -0,0 +1,97 @@
+/* PR middle-end/92341 - missing -Warray-bounds indexing past the end
+   of a compound literal
+   { dg-do compile }
+   { dg-options "-O2 -Wall -ftrack-macro-expansion=0" } */
+
+#include "range.h"
+
+#define INT_MAX    __INT_MAX__
+#define INT_MIN    (-__INT_MAX__ - 1)
+
+void sink (int, ...);
+
+
+#define T(...) sink (__LINE__, (__VA_ARGS__))
+
+
+void direct_idx_cst (void)
+{
+  T ((int[]){ }[-1]);           // { dg-warning "array subscript -1 is outside array bounds of 'int\\\[0]'" }
+  T ((int[]){ }[0]);            // { dg-warning "array subscript 0 is outside array bounds of 'int\\\[0]'" }
+  T ((int[]){ }[1]);            // { dg-warning "array subscript 1 is outside array bounds of 'int\\\[0]'" }
+
+  T ((int[]){ 1 }[-1]);         // { dg-warning "array subscript -1 is below array bounds of 'int\\\[1]'" }
+  T ((int[]){ 1 }[0]);
+  T ((int[]){ 1 }[1]);          // { dg-warning "array subscript 1 is above array bounds of 'int\\\[1]'" }
+  T ((int[]){ 1 }[INT_MIN]);    // { dg-warning "array subscript -\[0-9\]+ is below array bounds of 'int\\\[1]'" }
+  T ((int[]){ 1 }[INT_MAX]);    // { dg-warning "array subscript \[0-9\]+ is above array bounds of 'int\\\[1]'" }
+  T ((int[]){ 1 }[SIZE_MAX]);   // { dg-warning "array subscript \[0-9\]+ is above array bounds of 'int\\\[1]'" }
+}
+
+
+void direct_idx_var (int i)
+{
+  T ((char[]){ }[i]);           // { dg-warning "array subscript i is outside array bounds of 'char\\\[0]'" }
+  T ((int[]){ }[i]);            // { dg-warning "array subscript i is outside array bounds of 'int\\\[0]'" }
+}
+
+
+void direct_idx_range (void)
+{
+  ptrdiff_t i = SR (-2, -1);
+
+  T ((int[]){ 1 }[i]);          // { dg-warning "array subscript \[ \n\r]+ is outside array bounds of 'int\\\[0]'" "pr?????" { xfail *-*-* } }
+}
+
+
+#undef T
+#define T(idx, ...) do {                       \
+    int *p = (__VA_ARGS__);                    \
+    sink (p[idx]);                             \
+  } while (0)
+
+void ptr_idx_cst (void)
+{
+  T (-1, (int[]){ });           // { dg-warning "array subscript -1 is outside array bounds of 'int\\\[0]'" }
+  T ( 0, (int[]){ });           // { dg-warning "array subscript 0 is outside array bounds of 'int\\\[0]'" }
+  T (+1, (int[]){ });           // { dg-warning "array subscript 1 is outside array bounds of 'int\\\[0]'" }
+
+  T (-1, (int[]){ 1 });         // { dg-warning "array subscript -1 is outside array bounds of 'int\\\[1]'" }
+  T ( 0, (int[]){ 1 });
+  T (+1, (int[]){ 1 });         // { dg-warning "array subscript 1 is outside array bounds of 'int\\\[1]'" }
+  T (INT_MIN, (int[]){ 1 });    // { dg-warning "array subscript -\[0-9\]+ is outside array bounds of 'int\\\[1]'" "pr92381" { xfail ilp32 } }
+  T (INT_MAX, (int[]){ 1 });    // { dg-warning "array subscript \[0-9\]+ is outside array bounds of 'int\\\[1]'" "pr92381" { xfail ilp32 } }
+  // { dg-warning "array subscript -\[0-9\]+ is outside array bounds of 'int\\\[1]'" "" { target ilp32 } .-1 }
+  T (SIZE_MAX, (int[]){ 1 });   // { dg-warning "array subscript -?\[0-9\]+ is outside array bounds of 'int\\\[1]'" }
+}
+
+
+void ptr_idx_var (int i)
+{
+  T (i, (int[]){ });            // { dg-warning "array subscript \[^\n\r\]+ is outside array bounds of 'int\\\[0]'" }
+  T (i, (int[]){ 1 });
+  T (i, (int[]){ i, 1 });
+}
+
+void ptr_idx_range (void)
+{
+  ptrdiff_t i = SR (-2, -1);
+
+  T (i, (int[]){ });            // { dg-warning "array subscript \\\[-2, -1] is outside array bounds of 'int\\\[0]'" }
+  T (i, (int[]){ 1 });          // { dg-warning "array subscript \\\[-2, -1] is outside array bounds of 'int\\\[1]'" }
+  T (i, (int[]){ i });          // { dg-warning "array subscript \\\[-2, -1] is outside array bounds of 'int\\\[1]'" }
+
+  i = SR (0, 1);
+
+  T (i, (int[]){ });            // { dg-warning "array subscript \\\[0, 1] is outside array bounds of 'int\\\[0]'" }
+  T (i, (int[]){ 1 });
+
+  i = SR (1, 2);
+  T (i, (int[]){ 1 });          // { dg-warning "array subscript \\\[1, 2] is outside array bounds of 'int\\\[1]'" }
+
+  i = SR (2, 3);
+  T (i, (int[]){ 1, 2, 3 });
+
+  i = SR (3, 4);
+  T (i, (int[]){ 2, 3, 4 });          // { dg-warning "array subscript \\\[3, 4] is outside array bounds of 'int\\\[3]'" }
+}
diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-54.c b/gcc/testsuite/gcc.dg/Warray-bounds-54.c
new file mode 100644 (file)
index 0000000..644fcd0
--- /dev/null
@@ -0,0 +1,24 @@
+/* PR middle-end/82612 - missing -Warray-bounds on a non-zero offset
+   from the address of a non-array object
+   { dg-do compile }
+   { dg-options "-O2 -Wall" } */
+
+int i;
+int f0 (void)
+{
+  int *p = &i;
+  return p[2];      // { dg-warning "-Warray-bounds" }
+}
+
+int f1 (void)
+{
+  int i;
+  int *p = &i;
+  return p[2];      // { dg-warning "-Warray-bounds" }
+}
+
+int f2 (int i)
+{
+  int *p = &i;
+  return p[2];      // { dg-warning "-Warray-bounds" }
+}
index 3f10423..4486269 100644 (file)
@@ -3068,6 +3068,13 @@ get_access_for_expr (tree expr)
       || !DECL_P (base))
     return NULL;
 
+  if (tree basesize = DECL_SIZE (base))
+    {
+      poly_int64 sz = tree_to_poly_int64 (basesize);
+      if (offset < 0 || known_le (sz, offset))
+       return NULL;
+    }
+
   if (!bitmap_bit_p (candidate_bitmap, DECL_UID (base)))
     return NULL;
 
index 1328707..940ed9c 100644 (file)
@@ -4083,18 +4083,18 @@ bool
 vrp_prop::check_array_ref (location_t location, tree ref,
                           bool ignore_off_by_one)
 {
-  tree low_sub, up_sub;
-  tree low_bound, up_bound, up_bound_p1;
-
   if (TREE_NO_WARNING (ref))
     return false;
 
-  low_sub = up_sub = TREE_OPERAND (ref, 1);
-  up_bound = array_ref_up_bound (ref);
+  tree low_sub = TREE_OPERAND (ref, 1);
+  tree up_sub = low_sub;
+  tree up_bound = array_ref_up_bound (ref);
 
   /* Set for accesses to interior zero-length arrays.  */
   bool interior_zero_len = false;
 
+  tree up_bound_p1;
+
   if (!up_bound
       || TREE_CODE (up_bound) != INTEGER_CST
       || (warn_array_bounds < 2
@@ -4148,7 +4148,7 @@ vrp_prop::check_array_ref (location_t location, tree ref,
     up_bound_p1 = int_const_binop (PLUS_EXPR, up_bound,
                                   build_int_cst (TREE_TYPE (up_bound), 1));
 
-  low_bound = array_ref_low_bound (ref);
+  tree low_bound = array_ref_low_bound (ref);
 
   tree artype = TREE_TYPE (TREE_OPERAND (ref, 0));
 
@@ -4157,8 +4157,8 @@ vrp_prop::check_array_ref (location_t location, tree ref,
   /* Empty array.  */
   if (up_bound && tree_int_cst_equal (low_bound, up_bound_p1))
     warned = warning_at (location, OPT_Warray_bounds,
-                        "array subscript %E is above array bounds of %qT",
-                        low_bound, artype);
+                        "array subscript %E is outside array bounds of %qT",
+                        low_sub, artype);
 
   const value_range_equiv *vr = NULL;
   if (TREE_CODE (low_sub) == SSA_NAME)
@@ -4372,6 +4372,7 @@ vrp_prop::check_mem_ref (location_t location, tree ref,
     {
       arg = TREE_OPERAND (arg, 0);
       if (TREE_CODE (arg) != STRING_CST
+         && TREE_CODE (arg) != PARM_DECL
          && TREE_CODE (arg) != VAR_DECL)
        return false;
     }
@@ -4455,7 +4456,9 @@ vrp_prop::check_mem_ref (location_t location, tree ref,
   if (ignore_off_by_one)
     ubound += 1;
 
-  if (offrange[0] >= ubound || offrange[1] < arrbounds[0])
+  if (arrbounds[0] == arrbounds[1]
+      || offrange[0] >= ubound
+      || offrange[1] < arrbounds[0])
     {
       /* Treat a reference to a non-array object as one to an array
         of a single element.  */