summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog14
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.dg/pr36902.c61
-rw-r--r--gcc/tree-vrp.c76
4 files changed, 133 insertions, 23 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 02ebd507190..046da0e45db 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 c4269123182..a2449e8ebd4 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 00000000000..43a2d14f981
--- /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 cceea2549a3..a68eba60504 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