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
This commit is contained in:
parent
0e097268ba
commit
92ef7fb19a
4 changed files with 135 additions and 25 deletions
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
61
gcc/testsuite/gcc.dg/pr36902.c
Normal file
61
gcc/testsuite/gcc.dg/pr36902.c
Normal file
|
@ -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;
|
||||
}
|
|
@ -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)
|
||||
if (TREE_CODE (op) == SSA_NAME)
|
||||
{
|
||||
vr = get_value_range (op);
|
||||
|
||||
/* We can only handle integer ranges. */
|
||||
if (vr->type != VR_RANGE
|
||||
|| symbolic_range_p (vr))
|
||||
return false;
|
||||
|
||||
/* 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;
|
||||
|
||||
vr = get_value_range (op);
|
||||
|
||||
/* We can only handle integer ranges. */
|
||||
if (vr->type != VR_RANGE
|
||||
|| symbolic_range_p (vr))
|
||||
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
|
||||
|
|
Loading…
Add table
Reference in a new issue