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]

[PATCH] PR diagnostic/31227: Suppress some more -Warray-bounds warnings


Hi, 

Here's a followup patch that obsoletes the previous one that I posted a few 
days ago and that also fixes PR 31227. It was bootstrapped and regtested with 
no additional failures on i686-suse-linux. 

The fix is to trace the uses of SSA_NAMES which get addresses of array refs 
assigned. if they're modified further, not used, or used in multiple 
contexts, the warning is omitted. This is sort of a brute force hammer to 
avoid warnings about code which is frequently synthesized incorrectly from 
various optimising passes. 

The reason I didn't implement the suggested behaviour of tracing when the 
address of an array ref is derefed is pure complexity. it would require 
tracking variable ranges of all affected SSA_NAMES (could be a lot) and could 
still cause "false" warnings in contexts of multiple uses (which are 
generated by CSE). The only sane thing it could do with multiple uses is to 
omit the warning, which is just what the patch does now, just with a lot less 
overhead. 

Ok for trunk?


2007-03-21  Dirk Mueller  <dmueller@suse.de>

        PR diagnostic/31227
        * tree-vrp.c (check_array_bounds): Suppress warning
        about address exprs of array refs if it is unused
        or has more than one uses.

        * gcc.dg/Warray-bounds-3.c: New testcase.

--- tree-vrp.c
+++ tree-vrp.c
@@ -4092,51 +4092,64 @@ static tree
 check_array_bounds (tree *tp, int *walk_subtree, void *data)
 {
   tree t = *tp;
-  tree stmt = (tree)data;
+  tree stmt = (tree)data, use_stmt;
   location_t *location = EXPR_LOCUS (stmt);
+  use_operand_p op;
 
   *walk_subtree = TRUE;
 
   if (TREE_CODE (t) == ARRAY_REF)
     check_array_ref (t, location, false /*ignore_off_by_one*/);
-  else if (TREE_CODE (t) == ADDR_EXPR)
+
+  else if (TREE_CODE (t) != ADDR_EXPR)
+    return NULL_TREE;
+
+  t = TREE_OPERAND (t, 0);
+
+  while (*walk_subtree && handled_component_p (t))
     {
-       use_operand_p op;
-       tree use_stmt;
-       t = TREE_OPERAND (t, 0);
-
-       /* Don't warn on statements like
-
-          ssa_name = 500 + &array[-200]
-
-          or
-
-          ssa_name = &array[-200]
-          other_name = ssa_name + 300;
-
-          which are sometimes
-          produced by other optimizing passes.  */
-
-       if (TREE_CODE (stmt) == GIMPLE_MODIFY_STMT
-           && BINARY_CLASS_P (GIMPLE_STMT_OPERAND (stmt, 1)))
-         *walk_subtree = FALSE;
-
-       if (TREE_CODE (stmt) == GIMPLE_MODIFY_STMT
-           && TREE_CODE (GIMPLE_STMT_OPERAND (stmt, 0)) == SSA_NAME
-           && single_imm_use (GIMPLE_STMT_OPERAND (stmt, 0), &op, &use_stmt)
-           && TREE_CODE (use_stmt) == GIMPLE_MODIFY_STMT
-           && BINARY_CLASS_P (GIMPLE_STMT_OPERAND (use_stmt, 1)))
-         *walk_subtree = FALSE;
-
-       while (*walk_subtree && handled_component_p (t))
-         {
-           if (TREE_CODE (t) == ARRAY_REF)
-             check_array_ref (t, location, true /*ignore_off_by_one*/);
-           t = TREE_OPERAND (t, 0);
-         }
-       *walk_subtree = FALSE;
+      if (TREE_CODE (t) == ARRAY_REF)
+        {
+	  use_stmt = stmt;
+	  /* avoid warning if the result is not used,
+	     modified afterwards
+	     or used in multiple contexts.  */
+	  while (*walk_subtree && use_stmt)
+	  {
+	    if (TREE_CODE (use_stmt) == GIMPLE_MODIFY_STMT
+		&& TREE_CODE (GIMPLE_STMT_OPERAND (use_stmt, 0)) == SSA_NAME
+		&& (has_zero_uses (GIMPLE_STMT_OPERAND (use_stmt, 0))
+		    || BINARY_CLASS_P (GIMPLE_STMT_OPERAND (use_stmt, 1))))
+	      {
+		*walk_subtree = FALSE;
+		break;
+	      }
+
+	    if (TREE_CODE (use_stmt) == PHI_NODE)
+	      {
+		*walk_subtree = FALSE;
+		break;
+	      }
+
+	    if (TREE_CODE (use_stmt) == GIMPLE_MODIFY_STMT
+		&& TREE_CODE (GIMPLE_STMT_OPERAND (use_stmt, 0)) == SSA_NAME)
+	      {
+		if (single_imm_use (GIMPLE_STMT_OPERAND (use_stmt, 0),
+				    &op, &use_stmt))
+		  continue;
+		/* more than one use. In benefit of doubt.. */
+		*walk_subtree = FALSE;
+	      }
+
+	    break;
+	  }
+	  if (*walk_subtree)
+	    check_array_ref (t, location, true /*ignore_off_by_one*/);
+	}
+      t = TREE_OPERAND (t, 0);
     }
 
+  *walk_subtree = FALSE;
   return NULL_TREE;
 }
 
--- testsuite/gcc.dg/Warray-bounds-3.c
+++ testsuite/gcc.dg/Warray-bounds-3.c
@@ -0,0 +1,95 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -Warray-bounds" } */
+/* based on PR 31227 */
+
+typedef __SIZE_TYPE__ size_t;
+
+extern size_t strlen (const char *);
+
+struct iovec
+{
+  void *iov_base;
+  size_t iov_len;
+};
+
+struct S
+{
+  const char *abday[7];
+  const char *day[7];
+  const char *abmon[12];
+  const char *mon[12];
+  const char *am_pm[2];
+};
+
+extern void foo (size_t, struct iovec *);
+
+void
+bar (struct S *time)
+{
+  struct iovec iov[43];
+  size_t cnt;
+  iov[0].iov_base = (void *) "abc";
+  iov[0].iov_len = 3;
+
+  iov[1].iov_base = (void *) "def";
+  iov[1].iov_len = 3;
+
+  for (cnt = 0; cnt <= 7; ++cnt)
+    {
+      iov[2 + cnt].iov_base = (void *) (time->abday[cnt] ?: "");
+      iov[2 + cnt].iov_len = strlen (iov[2 + cnt].iov_base) + 1;
+    }
+
+  for (; cnt <= 14; ++cnt)
+    {
+      iov[2 + cnt].iov_base = (void *) (time->day[cnt - 7] ?: "");
+      iov[2 + cnt].iov_len = strlen (iov[2 + cnt].iov_base) + 1;
+    }
+
+  for (; cnt <= 26; ++cnt)
+    {
+      iov[2 + cnt].iov_base = (void *) (time->abmon[cnt - 14] ?: "");
+      iov[2 + cnt].iov_len = strlen (iov[2 + cnt].iov_base) + 1;
+    }
+
+  for (; cnt <= 38; ++cnt)
+    {
+      iov[2 + cnt].iov_base = (void *) (time->mon[cnt - 26] ?: "");
+      iov[2 + cnt].iov_len = strlen (iov[2 + cnt].iov_base) + 1;
+    }
+
+  for (; cnt <= 40; ++cnt)
+    {
+      iov[2 + cnt].iov_base =  (void *) (time->am_pm[cnt - 38] ?: "");
+      iov[2 + cnt].iov_len = strlen (iov[2 + cnt].iov_base) + 1;
+    }
+
+  foo (2 + cnt, iov);
+}
+
+struct malloc_chunk {
+  long prev_size;
+  long size;
+  struct malloc_chunk* fd;
+  struct malloc_chunk* bk;
+};
+typedef struct malloc_chunk* mchunkptr;
+struct malloc_state {
+  mchunkptr        top;
+  mchunkptr        last_remainder;
+  mchunkptr        bins[128 * 2 - 2];
+};
+#define bin_at(m, i) \
+  (mchunkptr) (((char *) &((m)->bins[((i) - 1) * 2]))                         
\
+             - __builtin_offsetof (struct malloc_chunk, fd))
+
+void malloc_init_state(struct malloc_state *av)
+{
+  int     i;
+  mchunkptr bin;
+
+  for (i = 1; i < 128; ++i) {
+    bin = bin_at(av,i);
+    bin->fd = bin->bk = bin;
+  }
+}


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