diff options
author | Richard Biener <rguenther@suse.de> | 2015-04-16 12:03:11 +0000 |
---|---|---|
committer | Richard Biener <rguenth@gcc.gnu.org> | 2015-04-16 12:03:11 +0000 |
commit | f8269ad4a97c7a4c950fcf42de24d6f145037e7e (patch) | |
tree | cf69ae8eeed6f2f7cfd0cbe284c8dd255c21717f /gcc/tree-vrp.c | |
parent | 579cef8f39ea28afa93c2d84f959867a7caa1325 (diff) | |
download | gcc-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
Diffstat (limited to 'gcc/tree-vrp.c')
-rw-r--r-- | gcc/tree-vrp.c | 78 |
1 files changed, 27 insertions, 51 deletions
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); } } } |