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
parent 0e097268
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> 2009-04-18 Adam Nemet <anemet@caviumnetworks.com>
* config/mips/mips.c (mips_final_postscan_insn): Make it static. * config/mips/mips.c (mips_final_postscan_insn): Make it static.
......
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> 2009-04-17 Diego Novillo <dnovillo@google.com>
* gcc.c-torture/execute/builtins/strlen-3.c: Fix ODR * gcc.c-torture/execute/builtins/strlen-3.c: Fix ODR
......
/* 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) ...@@ -4996,7 +4996,7 @@ insert_range_assertions (void)
IGNORE_OFF_BY_ONE is true if the ARRAY_REF is inside a ADDR_EXPR. */ IGNORE_OFF_BY_ONE is true if the ARRAY_REF is inside a ADDR_EXPR. */
static void 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; value_range_t* vr = NULL;
tree low_sub, up_sub; tree low_sub, up_sub;
...@@ -5035,8 +5035,8 @@ check_array_ref (tree ref, const location_t *location, bool ignore_off_by_one) ...@@ -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_CODE (low_sub) == INTEGER_CST
&& tree_int_cst_lt (low_sub, low_bound)) && tree_int_cst_lt (low_sub, low_bound))
{ {
warning (OPT_Warray_bounds, warning_at (location, OPT_Warray_bounds,
"%Harray subscript is outside array bounds", location); "array subscript is outside array bounds");
TREE_NO_WARNING (ref) = 1; TREE_NO_WARNING (ref) = 1;
} }
} }
...@@ -5050,15 +5050,15 @@ check_array_ref (tree ref, const location_t *location, bool ignore_off_by_one) ...@@ -5050,15 +5050,15 @@ check_array_ref (tree ref, const location_t *location, bool ignore_off_by_one)
0), 0),
up_sub))) up_sub)))
{ {
warning (OPT_Warray_bounds, "%Harray subscript is above array bounds", warning_at (location, OPT_Warray_bounds,
location); "array subscript is above array bounds");
TREE_NO_WARNING (ref) = 1; TREE_NO_WARNING (ref) = 1;
} }
else if (TREE_CODE (low_sub) == INTEGER_CST else if (TREE_CODE (low_sub) == INTEGER_CST
&& tree_int_cst_lt (low_sub, low_bound)) && tree_int_cst_lt (low_sub, low_bound))
{ {
warning (OPT_Warray_bounds, "%Harray subscript is below array bounds", warning_at (location, OPT_Warray_bounds,
location); "array subscript is below array bounds");
TREE_NO_WARNING (ref) = 1; TREE_NO_WARNING (ref) = 1;
} }
} }
...@@ -5067,7 +5067,7 @@ check_array_ref (tree ref, const location_t *location, bool ignore_off_by_one) ...@@ -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. */ address of an ARRAY_REF, and call check_array_ref on it. */
static void 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) while (TREE_CODE (t) == SSA_NAME)
{ {
...@@ -5115,11 +5115,11 @@ check_array_bounds (tree *tp, int *walk_subtree, void *data) ...@@ -5115,11 +5115,11 @@ check_array_bounds (tree *tp, int *walk_subtree, void *data)
*walk_subtree = TRUE; *walk_subtree = TRUE;
if (TREE_CODE (t) == ARRAY_REF) 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 if (TREE_CODE (t) == INDIRECT_REF
|| (TREE_CODE (t) == RETURN_EXPR && TREE_OPERAND (t, 0))) || (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) if (TREE_CODE (t) == ADDR_EXPR)
*walk_subtree = FALSE; *walk_subtree = FALSE;
...@@ -5141,9 +5141,23 @@ check_all_array_refs (void) ...@@ -5141,9 +5141,23 @@ check_all_array_refs (void)
/* Skip bb's that are clearly unreachable. */ /* Skip bb's that are clearly unreachable. */
if (single_pred_p (bb)) 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; 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))) if (!gsi_end_p (gsi_last_bb (pred_bb)))
ls = gsi_stmt (gsi_last_bb (pred_bb)); ls = gsi_stmt (gsi_last_bb (pred_bb));
...@@ -5157,7 +5171,6 @@ check_all_array_refs (void) ...@@ -5157,7 +5171,6 @@ check_all_array_refs (void)
for (si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si)) for (si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si))
{ {
gimple stmt = gsi_stmt (si); gimple stmt = gsi_stmt (si);
const location_t *location = gimple_location_ptr (stmt);
struct walk_stmt_info wi; struct walk_stmt_info wi;
if (!gimple_has_location (stmt)) if (!gimple_has_location (stmt))
continue; continue;
...@@ -5169,13 +5182,14 @@ check_all_array_refs (void) ...@@ -5169,13 +5182,14 @@ check_all_array_refs (void)
for (i = 0; i < n; i++) for (i = 0; i < n; i++)
{ {
tree arg = gimple_call_arg (stmt, i); tree arg = gimple_call_arg (stmt, i);
search_for_addr_array (arg, location); search_for_addr_array (arg, gimple_location (stmt));
} }
} }
else else
{ {
memset (&wi, 0, sizeof (wi)); 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), walk_gimple_op (gsi_stmt (si),
check_array_bounds, check_array_bounds,
...@@ -5875,7 +5889,7 @@ vrp_visit_cond_stmt (gimple stmt, edge *taken_edge_p) ...@@ -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 If there is a CASE_LABEL for VAL, its index is placed in IDX and true is
returned. 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. 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 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) ...@@ -6860,19 +6874,35 @@ simplify_switch_using_ranges (gimple stmt)
tree vec2; tree vec2;
switch_update su; switch_update su;
if (TREE_CODE (op) != SSA_NAME) if (TREE_CODE (op) == SSA_NAME)
return false; {
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. */ /* Find case label for min/max of the value range. */
if (vr->type != VR_RANGE take_default = !find_case_label_range (stmt, vr->min, vr->max, &i, &j);
|| symbolic_range_p (vr)) }
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; return false;
/* Find case label for min/max of the value range. */
n = gimple_switch_num_labels (stmt); 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. */ /* Bail out if this is just all edges taken. */
if (i == 1 if (i == 1
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment