re PR middle-end/35593 (spurious warning "array subscript is below array bounds"...
authorRichard Guenther <rguenther@suse.de>
Sat, 15 Mar 2008 14:27:55 +0000 (14:27 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Sat, 15 Mar 2008 14:27:55 +0000 (14:27 +0000)
2008-03-15  Richard Guenther  <rguenther@suse.de>

PR middle-end/35593
* tree-ssa-ccp.c (maybe_fold_offset_to_array_ref): Make sure
to not produce negative array indices if not allowed.  Add
parameter to indicate that.
(maybe_fold_offset_to_component_ref): Allow negative array
indices only for the first member of a structure.
(maybe_fold_offset_to_reference): Allow negative array indices.
(maybe_fold_stmt_addition): Likewise.

* g++.dg/warn/Warray-bounds-3.C: New testcase.

From-SVN: r133249

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/warn/Warray-bounds-3.C [new file with mode: 0644]
gcc/tree-ssa-ccp.c

index c97c1a394a68763ab0056fb7c157f001e14b1429..b0e25a461bf2a1d77e8745eaacb6e0dff3b9394d 100644 (file)
@@ -1,3 +1,14 @@
+2008-03-15  Richard Guenther  <rguenther@suse.de>
+
+       PR middle-end/35593
+       * tree-ssa-ccp.c (maybe_fold_offset_to_array_ref): Make sure
+       to not produce negative array indices if not allowed.  Add
+       parameter to indicate that.
+       (maybe_fold_offset_to_component_ref): Allow negative array
+       indices only for the first member of a structure.
+       (maybe_fold_offset_to_reference): Allow negative array indices.
+       (maybe_fold_stmt_addition): Likewise.
+
 2008-03-15  Bjoern Haase  <bjoern.m.haase@web.de>
             Anatoly Sokolov <aesok@post.ru>
 
index ab02e686fc71bb3af6c9f0ee9d29e12c4d87568b..f453ce1c2c3076ad07746356f33f3b447c27dbe4 100644 (file)
@@ -1,3 +1,8 @@
+2008-03-15  Richard Guenther  <rguenther@suse.de>
+
+       PR middle-end/35593
+       * g++.dg/warn/Warray-bounds-3.C: New testcase.
+
 2008-03-15  Jerry DeLisle  <jvdelisle@gcc.gnu.org>
 
        PR testsuite/35478
diff --git a/gcc/testsuite/g++.dg/warn/Warray-bounds-3.C b/gcc/testsuite/g++.dg/warn/Warray-bounds-3.C
new file mode 100644 (file)
index 0000000..a858571
--- /dev/null
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wall" } */
+
+extern void function(void * x);
+
+struct A {
+    long x;
+    char d[0];
+};
+
+
+void test(A * a) {
+    function((char *)a - 4); /* { dg-bogus "below array bounds" } */
+}
+
index 7cefbf838933e67639407a12bef40907e9c2f33e..8b8a902169ee3a4d7e00510b61e0a9f12303d354 100644 (file)
@@ -1593,7 +1593,8 @@ widen_bitfield (tree val, tree field, tree var)
    is the desired result type.  */
 
 static tree
-maybe_fold_offset_to_array_ref (tree base, tree offset, tree orig_type)
+maybe_fold_offset_to_array_ref (tree base, tree offset, tree orig_type,
+                               bool allow_negative_idx)
 {
   tree min_idx, idx, idx_type, elt_offset = integer_zero_node;
   tree array_type, elt_type, elt_size;
@@ -1693,11 +1694,15 @@ maybe_fold_offset_to_array_ref (tree base, tree offset, tree orig_type)
   idx = fold_convert (idx_type, idx);
 
   /* We don't want to construct access past array bounds. For example
-     char *(c[4]);
-
-     c[3][2]; should not be simplified into (*c)[14] or tree-vrp will give false
-     warning.  */
-  if (domain_type && TYPE_MAX_VALUE (domain_type) 
+       char *(c[4]);
+       c[3][2];
+     should not be simplified into (*c)[14] or tree-vrp will
+     give false warnings.  The same is true for
+       struct A { long x; char d[0]; } *a;
+       (char *)a - 4;
+     which should be not folded to &a->d[-8].  */
+  if (domain_type
+      && TYPE_MAX_VALUE (domain_type) 
       && TREE_CODE (TYPE_MAX_VALUE (domain_type)) == INTEGER_CST)
     {
       tree up_bound = TYPE_MAX_VALUE (domain_type);
@@ -1709,6 +1714,17 @@ maybe_fold_offset_to_array_ref (tree base, tree offset, tree orig_type)
          && compare_tree_int (up_bound, 1) > 0)
        return NULL_TREE;
     }
+  if (domain_type
+      && TYPE_MIN_VALUE (domain_type))
+    {
+      if (!allow_negative_idx
+         && TREE_CODE (TYPE_MIN_VALUE (domain_type)) == INTEGER_CST
+         && tree_int_cst_lt (idx, TYPE_MIN_VALUE (domain_type)))
+       return NULL_TREE;
+    }
+  else if (!allow_negative_idx
+          && compare_tree_int (idx, 0) < 0)
+    return NULL_TREE;
 
   return build4 (ARRAY_REF, elt_type, base, idx, NULL_TREE, NULL_TREE);
 }
@@ -1805,7 +1821,8 @@ maybe_fold_offset_to_component_ref (tree record_type, tree base, tree offset,
       new_base = build3 (COMPONENT_REF, field_type, new_base, f, NULL_TREE);
 
       /* Recurse to possibly find the match.  */
-      ret = maybe_fold_offset_to_array_ref (new_base, t, orig_type);
+      ret = maybe_fold_offset_to_array_ref (new_base, t, orig_type,
+                                           f == TYPE_FIELDS (record_type));
       if (ret)
        return ret;
       ret = maybe_fold_offset_to_component_ref (field_type, new_base, t,
@@ -1827,7 +1844,8 @@ maybe_fold_offset_to_component_ref (tree record_type, tree base, tree offset,
     base = build1 (INDIRECT_REF, record_type, base);
   base = build3 (COMPONENT_REF, field_type, base, f, NULL_TREE);
 
-  t = maybe_fold_offset_to_array_ref (base, offset, orig_type);
+  t = maybe_fold_offset_to_array_ref (base, offset, orig_type,
+                                     f == TYPE_FIELDS (record_type));
   if (t)
     return t;
   return maybe_fold_offset_to_component_ref (field_type, base, offset,
@@ -1893,7 +1911,7 @@ maybe_fold_offset_to_reference (tree base, tree offset, tree orig_type)
     {
       if (base_is_ptr)
        base = build1 (INDIRECT_REF, type, base);
-      ret = maybe_fold_offset_to_array_ref (base, offset, orig_type);
+      ret = maybe_fold_offset_to_array_ref (base, offset, orig_type, true);
     }
   return ret;
 }
@@ -2070,7 +2088,7 @@ maybe_fold_stmt_addition (tree expr)
   ptd_type = TREE_TYPE (ptr_type);
 
   /* At which point we can try some of the same things as for indirects.  */
-  t = maybe_fold_offset_to_array_ref (op0, op1, ptd_type);
+  t = maybe_fold_offset_to_array_ref (op0, op1, ptd_type, true);
   if (!t)
     t = maybe_fold_offset_to_component_ref (TREE_TYPE (op0), op0, op1,
                                            ptd_type, false);