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; }