diff options
author | Manuel López-Ibáñez <manu@gcc.gnu.org> | 2009-04-18 09:24:45 +0000 |
---|---|---|
committer | Manuel López-Ibáñez <manu@gcc.gnu.org> | 2009-04-18 09:24:45 +0000 |
commit | 92ef7fb19a5111b98e86eb7c59d1a1d759ac1ec2 (patch) | |
tree | eac4cee15a78ad544b9a96b83862fb6e75037cb9 /gcc | |
parent | 0e097268ba02d44bba29eb8e3955cde6e9bd5c7f (diff) | |
download | gcc-92ef7fb19a5111b98e86eb7c59d1a1d759ac1ec2.zip gcc-92ef7fb19a5111b98e86eb7c59d1a1d759ac1ec2.tar.gz gcc-92ef7fb19a5111b98e86eb7c59d1a1d759ac1ec2.tar.bz2 |
re PR middle-end/36902 (Array bound warning with dead code after optimization)
2009-04-18 Manuel López-Ibáñez <manu@gcc.gnu.org>
PR middle-end/36902
* tree-vrp.c (check_array_ref): Pass a location_t instead of a
pointer. Use warning_at instead of warning.
(search_for_addr_array): Likewise.
(check_array_bounds): Likewise.
(check_all_array_refs): Check that the incoming edge is not in the
list of edges to be removed.
(check_all_array_refs): Avoid the temporal pointer.
(vrp_visit_cond_stmt): Fix typo.
(simplify_switch_using_ranges): Handle the case where the switch
index is an integer constant.
testsuite/
* gcc.dg/pr36902.c: New.
From-SVN: r146305
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 14 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/pr36902.c | 61 | ||||
-rw-r--r-- | gcc/tree-vrp.c | 76 |
4 files changed, 133 insertions, 23 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 02ebd50..046da0e 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,17 @@ +2009-04-18 Manuel López-Ibáñez <manu@gcc.gnu.org> + + PR middle-end/36902 + * tree-vrp.c (check_array_ref): Pass a location_t instead of a + pointer. Use warning_at instead of warning. + (search_for_addr_array): Likewise. + (check_array_bounds): Likewise. + (check_all_array_refs): Check that the incoming edge is not in the + list of edges to be removed. + (check_all_array_refs): Avoid the temporal pointer. + (vrp_visit_cond_stmt): Fix typo. + (simplify_switch_using_ranges): Handle the case where the switch + index is an integer constant. + 2009-04-18 Adam Nemet <anemet@caviumnetworks.com> * config/mips/mips.c (mips_final_postscan_insn): Make it static. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index c4269123..a2449e8 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2009-04-18 Manuel López-Ibáñez <manu@gcc.gnu.org> + + PR middle-end/36902 + * gcc.dg/pr36902.c: New. + 2009-04-17 Diego Novillo <dnovillo@google.com> * gcc.c-torture/execute/builtins/strlen-3.c: Fix ODR diff --git a/gcc/testsuite/gcc.dg/pr36902.c b/gcc/testsuite/gcc.dg/pr36902.c new file mode 100644 index 0000000..43a2d14 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr36902.c @@ -0,0 +1,61 @@ +/* PR middle-end/36902 Array bound warning with dead code after optimization */ +/* { dg-do compile } */ +/* { dg-options "-O2 -Warray-bounds -Wall -Wextra" } */ +typedef unsigned char __u8; +typedef unsigned short __u16; + +static inline unsigned char * +foo(unsigned char * to, const unsigned char * from, int n) +{ + switch ( n ) + { + case 3: + *to = *from; + break; + case 5: + to[4] = from [4]; + break; + } + return to; +} + +struct { + int size_of_select; + unsigned char pcr_select[4]; +} sel; + +int bar(void) +{ + static unsigned char buf[64]; + + sel.size_of_select = 3; + foo(buf, sel.pcr_select, sel.size_of_select); + + return 1; +} + + +static inline unsigned char * +foo2(unsigned char * to, const unsigned char * from, int n) +{ + switch ( n ) + { + case 3: + *to = *from; + break; + case 5: + to[4] = from [4]; /* { dg-warning "array subscript is above array bounds" } */ + break; + } + return to; +} + +int baz(void) +{ + static unsigned char buf[64]; + + sel.size_of_select = 5; + foo2(buf, sel.pcr_select, sel.size_of_select); + + return 1; +} diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index cceea25..a68eba6 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -4996,7 +4996,7 @@ insert_range_assertions (void) IGNORE_OFF_BY_ONE is true if the ARRAY_REF is inside a ADDR_EXPR. */ static void -check_array_ref (tree ref, const location_t *location, bool ignore_off_by_one) +check_array_ref (tree ref, location_t location, bool ignore_off_by_one) { value_range_t* vr = NULL; tree low_sub, up_sub; @@ -5035,8 +5035,8 @@ check_array_ref (tree ref, const location_t *location, bool ignore_off_by_one) && TREE_CODE (low_sub) == INTEGER_CST && tree_int_cst_lt (low_sub, low_bound)) { - warning (OPT_Warray_bounds, - "%Harray subscript is outside array bounds", location); + warning_at (location, OPT_Warray_bounds, + "array subscript is outside array bounds"); TREE_NO_WARNING (ref) = 1; } } @@ -5050,15 +5050,15 @@ check_array_ref (tree ref, const location_t *location, bool ignore_off_by_one) 0), up_sub))) { - warning (OPT_Warray_bounds, "%Harray subscript is above array bounds", - location); + warning_at (location, OPT_Warray_bounds, + "array subscript is above array bounds"); TREE_NO_WARNING (ref) = 1; } else if (TREE_CODE (low_sub) == INTEGER_CST && tree_int_cst_lt (low_sub, low_bound)) { - warning (OPT_Warray_bounds, "%Harray subscript is below array bounds", - location); + warning_at (location, OPT_Warray_bounds, + "array subscript is below array bounds"); TREE_NO_WARNING (ref) = 1; } } @@ -5067,7 +5067,7 @@ check_array_ref (tree ref, const location_t *location, bool ignore_off_by_one) address of an ARRAY_REF, and call check_array_ref on it. */ static void -search_for_addr_array (tree t, const location_t *location) +search_for_addr_array (tree t, location_t location) { while (TREE_CODE (t) == SSA_NAME) { @@ -5115,11 +5115,11 @@ check_array_bounds (tree *tp, int *walk_subtree, void *data) *walk_subtree = TRUE; if (TREE_CODE (t) == ARRAY_REF) - check_array_ref (t, location, false /*ignore_off_by_one*/); + check_array_ref (t, *location, false /*ignore_off_by_one*/); if (TREE_CODE (t) == INDIRECT_REF || (TREE_CODE (t) == RETURN_EXPR && TREE_OPERAND (t, 0))) - search_for_addr_array (TREE_OPERAND (t, 0), location); + search_for_addr_array (TREE_OPERAND (t, 0), *location); if (TREE_CODE (t) == ADDR_EXPR) *walk_subtree = FALSE; @@ -5141,9 +5141,23 @@ check_all_array_refs (void) /* Skip bb's that are clearly unreachable. */ if (single_pred_p (bb)) { - basic_block pred_bb = EDGE_PRED (bb, 0)->src; + int i; + bool reachable = true; + edge e2; + edge e = EDGE_PRED (bb, 0); + basic_block pred_bb = e->src; gimple ls = NULL; + for (i = 0; VEC_iterate (edge, to_remove_edges, i, e2); ++i) + if (e == e2) + { + reachable = false; + break; + } + + if (!reachable) + continue; + if (!gsi_end_p (gsi_last_bb (pred_bb))) ls = gsi_stmt (gsi_last_bb (pred_bb)); @@ -5157,7 +5171,6 @@ check_all_array_refs (void) for (si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si)) { gimple stmt = gsi_stmt (si); - const location_t *location = gimple_location_ptr (stmt); struct walk_stmt_info wi; if (!gimple_has_location (stmt)) continue; @@ -5169,13 +5182,14 @@ check_all_array_refs (void) for (i = 0; i < n; i++) { tree arg = gimple_call_arg (stmt, i); - search_for_addr_array (arg, location); + search_for_addr_array (arg, gimple_location (stmt)); } } else { memset (&wi, 0, sizeof (wi)); - wi.info = CONST_CAST (void *, (const void *) location); + wi.info = CONST_CAST (void *, (const void *) + gimple_location_ptr (stmt)); walk_gimple_op (gsi_stmt (si), check_array_bounds, @@ -5875,7 +5889,7 @@ vrp_visit_cond_stmt (gimple stmt, edge *taken_edge_p) If there is a CASE_LABEL for VAL, its index is placed in IDX and true is returned. - If there is no CASE_LABEL for VAL and the is one that is larger than VAL, + If there is no CASE_LABEL for VAL and there is one that is larger than VAL, it is placed in IDX and false is returned. If VAL is larger than any CASE_LABEL, n is placed on IDX and false is @@ -6860,19 +6874,35 @@ simplify_switch_using_ranges (gimple stmt) tree vec2; switch_update su; - if (TREE_CODE (op) != SSA_NAME) - return false; + if (TREE_CODE (op) == SSA_NAME) + { + vr = get_value_range (op); - vr = get_value_range (op); + /* We can only handle integer ranges. */ + if (vr->type != VR_RANGE + || symbolic_range_p (vr)) + return false; - /* We can only handle integer ranges. */ - if (vr->type != VR_RANGE - || symbolic_range_p (vr)) + /* Find case label for min/max of the value range. */ + take_default = !find_case_label_range (stmt, vr->min, vr->max, &i, &j); + } + else if (TREE_CODE (op) == INTEGER_CST) + { + take_default = !find_case_label_index (stmt, 1, op, &i); + if (take_default) + { + i = 1; + j = 0; + } + else + { + j = i; + } + } + else return false; - /* Find case label for min/max of the value range. */ n = gimple_switch_num_labels (stmt); - take_default = !find_case_label_range (stmt, vr->min, vr->max, &i, &j); /* Bail out if this is just all edges taken. */ if (i == 1 |