aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Biener <rguenther@suse.de>2015-04-16 12:03:11 +0000
committerRichard Biener <rguenth@gcc.gnu.org>2015-04-16 12:03:11 +0000
commitf8269ad4a97c7a4c950fcf42de24d6f145037e7e (patch)
treecf69ae8eeed6f2f7cfd0cbe284c8dd255c21717f
parent579cef8f39ea28afa93c2d84f959867a7caa1325 (diff)
downloadgcc-f8269ad4a97c7a4c950fcf42de24d6f145037e7e.zip
gcc-f8269ad4a97c7a4c950fcf42de24d6f145037e7e.tar.gz
gcc-f8269ad4a97c7a4c950fcf42de24d6f145037e7e.tar.bz2
re PR tree-optimization/64277 (Incorrect warning "array subscript is above array bounds")
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
-rw-r--r--gcc/ChangeLog9
-rw-r--r--gcc/testsuite/ChangeLog8
-rw-r--r--gcc/testsuite/c-c++-common/ubsan/bounds-4.c4
-rw-r--r--gcc/testsuite/c-c++-common/ubsan/bounds-6.c4
-rw-r--r--gcc/testsuite/gcc.dg/Warray-bounds-14.c28
-rw-r--r--gcc/testsuite/gcc.dg/Warray-bounds-15.c20
-rw-r--r--gcc/tree-vrp.c78
7 files changed, 96 insertions, 55 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 4b661d1..c4d0c15 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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.
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index f8e2279..5a217e7 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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.
diff --git a/gcc/testsuite/c-c++-common/ubsan/bounds-4.c b/gcc/testsuite/c-c++-common/ubsan/bounds-4.c
index 7748780..88e7e14 100644
--- a/gcc/testsuite/c-c++-common/ubsan/bounds-4.c
+++ b/gcc/testsuite/c-c++-common/ubsan/bounds-4.c
@@ -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;
}
diff --git a/gcc/testsuite/c-c++-common/ubsan/bounds-6.c b/gcc/testsuite/c-c++-common/ubsan/bounds-6.c
index aef2055..9523549 100644
--- a/gcc/testsuite/c-c++-common/ubsan/bounds-6.c
+++ b/gcc/testsuite/c-c++-common/ubsan/bounds-6.c
@@ -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
index 0000000..f3a33f9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Warray-bounds-14.c
@@ -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
index 0000000..f50e5ee
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Warray-bounds-15.c
@@ -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" } */
+}
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index 23e48b1..41d7316 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -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);
}
}
}