re PR middle-end/36902 (Array bound warning with dead code after optimization)
authorManuel López-Ibáñez <manu@gcc.gnu.org>
Sat, 18 Apr 2009 09:24:45 +0000 (09:24 +0000)
committerManuel López-Ibáñez <manu@gcc.gnu.org>
Sat, 18 Apr 2009 09:24:45 +0000 (09:24 +0000)
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

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/pr36902.c [new file with mode: 0644]
gcc/tree-vrp.c

index 02ebd50..046da0e 100644 (file)
@@ -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.
index c426912..a2449e8 100644 (file)
@@ -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 (file)
index 0000000..43a2d14
--- /dev/null
@@ -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;
+}
index cceea25..a68eba6 100644 (file)
@@ -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