This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

PR middle-end/36902 Array bound warning with dead code after optimization


Bootstrapped and regression tested on x86_64-unknown-linux-gnu with
--enable-languages=all,obj-c++ --enable-decimal-float.

This could be improved further by:

* Marking the edges to be removed in some way, so we don't have to
search in the list to_remove_edges.
* Considering BBs that have more than one incoming edge.
* Augmenting get_value_range to handle integer constants (or constants
in general).
* Augmenting find_case_label_range to handle more efficiently the case
where i == j.

Nonetheless, the current patch is enough to fix the PR. I could
include the above proposals in the comments.

OK for trunk?

2008-10-26  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.
Index: gcc/tree-vrp.c
===================================================================
--- gcc/tree-vrp.c	(revision 141361)
+++ gcc/tree-vrp.c	(working copy)
@@ -4874,11 +4874,11 @@ insert_range_assertions (void)
    range. If the array subscript is a RANGE, warn if it is
    non-overlapping with valid range.
    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;
   tree low_bound, up_bound = array_ref_up_bound (ref);
 
@@ -4913,12 +4913,12 @@ check_array_ref (tree ref, const locatio
       if (TREE_CODE (up_sub) == INTEGER_CST
           && tree_int_cst_lt (up_bound, up_sub)
           && 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;
         }
     }
   else if (TREE_CODE (up_sub) == INTEGER_CST
            && tree_int_cst_lt (up_bound, up_sub)
@@ -4928,28 +4928,28 @@ check_array_ref (tree ref, const locatio
                                                         up_bound,
                                                         integer_one_node,
                                                         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;
     }
 }
 
 /* Searches if the expr T, located at LOCATION computes
    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)
     {
       gimple g = SSA_NAME_DEF_STMT (t);
 
@@ -4993,15 +4993,15 @@ check_array_bounds (tree *tp, int *walk_
   const location_t *location = (const location_t *) wi->info;
 
   *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;
 
   return NULL_TREE;
@@ -5019,13 +5019,27 @@ check_all_array_refs (void)
   FOR_EACH_BB (bb)
     {
       /* 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));
 
 	if (ls && gimple_code (ls) == GIMPLE_COND
 	    && ((gimple_cond_false_p (ls)
@@ -5035,11 +5049,10 @@ check_all_array_refs (void)
 	  continue;
       }
       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;
 
 	  if (is_gimple_call (stmt))
@@ -5047,17 +5060,18 @@ check_all_array_refs (void)
 	      size_t i;
 	      size_t n = gimple_call_num_args (stmt);
 	      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,
 			      &wi);
 	    }
@@ -5753,11 +5767,11 @@ vrp_visit_cond_stmt (gimple stmt, edge *
    [START_IDX, n - 1] where n is the size of VEC.
 
    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
    returned. */
 
@@ -6726,23 +6740,39 @@ simplify_switch_using_ranges (gimple stm
   edge_iterator ei;
   size_t i = 0, j = 0, n, n2;
   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
       && j == n - 1
       && take_default)
Index: gcc/testsuite/gcc.dg/pr36902.c
===================================================================
--- gcc/testsuite/gcc.dg/pr36902.c	(revision 0)
+++ gcc/testsuite/gcc.dg/pr36902.c	(revision 0)
@@ -0,0 +1,35 @@
+/* PR middle-end/36902 Array bound warning with dead code after optimization */
+/* { dg-do compile } */
+/* { dg-options "-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;
+}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]