aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Guenther <rguenther@suse.de>2007-04-27 11:42:43 +0000
committerRichard Biener <rguenth@gcc.gnu.org>2007-04-27 11:42:43 +0000
commit891fc5e9f1b6a88f9147b68e670f0cc172acfe21 (patch)
treef5c0aaa63c85a8e22468cb5c55ee2f5e9507d027
parent8c74fb06c66b569a26f93c0d569d4437fdcfd415 (diff)
downloadgcc-891fc5e9f1b6a88f9147b68e670f0cc172acfe21.zip
gcc-891fc5e9f1b6a88f9147b68e670f0cc172acfe21.tar.gz
gcc-891fc5e9f1b6a88f9147b68e670f0cc172acfe21.tar.bz2
re PR tree-optimization/31715 (Array calculation done incorrectly)
2007-04-27 Richard Guenther <rguenther@suse.de> PR tree-optimization/31715 * tree-ssa-ccp.c (maybe_fold_offset_to_array_ref): Make sure to do computation on the offset in an appropriate signed type. * gcc.dg/Warray-bounds-4.c: New testcase. From-SVN: r124216
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.dg/Warray-bounds-4.c17
-rw-r--r--gcc/tree-ssa-ccp.c37
4 files changed, 53 insertions, 13 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index d562339..0e4f987 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,10 @@
+2007-04-27 Richard Guenther <rguenther@suse.de>
+
+ PR tree-optimization/31715
+ * tree-ssa-ccp.c (maybe_fold_offset_to_array_ref): Make
+ sure to do computation on the offset in an appropriate
+ signed type.
+
2007-04-27 Richard Sandiford <richard@codesourcery.com>
* reload.h (elimination_target_reg_p): Declare.
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 40c811b..c9e601e 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2007-04-27 Richard Guenther <rguenther@suse.de>
+
+ PR tree-optimization/31715
+ * gcc.dg/Warray-bounds-4.c: New testcase.
+
2007-04-26 Ian Lance Taylor <iant@google.com>
PR target/28675
diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-4.c b/gcc/testsuite/gcc.dg/Warray-bounds-4.c
new file mode 100644
index 0000000..71526f2
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Warray-bounds-4.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wall" } */
+
+typedef unsigned int DWORD;
+
+static void g(DWORD * p, int n)
+{
+ int i;
+
+ for (i = 0; i < n && !p[n - 1]; i++); /* { dg-bogus "subscript is above array bounds" } */
+}
+
+void f() {
+ DWORD arr[8];
+
+ g(arr, 4);
+}
diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c
index 530dee0..9c9d847 100644
--- a/gcc/tree-ssa-ccp.c
+++ b/gcc/tree-ssa-ccp.c
@@ -1550,7 +1550,7 @@ widen_bitfield (tree val, tree field, tree var)
static tree
maybe_fold_offset_to_array_ref (tree base, tree offset, tree orig_type)
{
- tree min_idx, idx, elt_offset = integer_zero_node;
+ tree min_idx, idx, idx_type, elt_offset = integer_zero_node;
tree array_type, elt_type, elt_size;
/* If BASE is an ARRAY_REF, we can pick up another offset (this time
@@ -1578,7 +1578,10 @@ maybe_fold_offset_to_array_ref (tree base, tree offset, tree orig_type)
elt_type = TREE_TYPE (array_type);
if (!lang_hooks.types_compatible_p (orig_type, elt_type))
return NULL_TREE;
-
+
+ /* Use signed size type for intermediate computation on the index. */
+ idx_type = signed_type_for (size_type_node);
+
/* If OFFSET and ELT_OFFSET are zero, we don't care about the size of the
element type (so we can use the alignment if it's not constant).
Otherwise, compute the offset as an index by using a division. If the
@@ -1589,42 +1592,47 @@ maybe_fold_offset_to_array_ref (tree base, tree offset, tree orig_type)
if (TREE_CODE (elt_size) != INTEGER_CST)
elt_size = size_int (TYPE_ALIGN (elt_type));
- idx = integer_zero_node;
+ idx = build_int_cst (idx_type, 0);
}
else
{
unsigned HOST_WIDE_INT lquo, lrem;
HOST_WIDE_INT hquo, hrem;
+ double_int soffset;
+ /* The final array offset should be signed, so we need
+ to sign-extend the (possibly pointer) offset here
+ and use signed division. */
+ soffset = double_int_sext (tree_to_double_int (offset),
+ TYPE_PRECISION (TREE_TYPE (offset)));
if (TREE_CODE (elt_size) != INTEGER_CST
- || div_and_round_double (TRUNC_DIV_EXPR, 1,
- TREE_INT_CST_LOW (offset),
- TREE_INT_CST_HIGH (offset),
+ || div_and_round_double (TRUNC_DIV_EXPR, 0,
+ soffset.low, soffset.high,
TREE_INT_CST_LOW (elt_size),
TREE_INT_CST_HIGH (elt_size),
&lquo, &hquo, &lrem, &hrem)
|| lrem || hrem)
return NULL_TREE;
- idx = build_int_cst_wide (TREE_TYPE (offset), lquo, hquo);
+ idx = build_int_cst_wide (idx_type, lquo, hquo);
}
/* Assume the low bound is zero. If there is a domain type, get the
low bound, if any, convert the index into that type, and add the
low bound. */
- min_idx = integer_zero_node;
+ min_idx = build_int_cst (idx_type, 0);
if (TYPE_DOMAIN (array_type))
{
- if (TYPE_MIN_VALUE (TYPE_DOMAIN (array_type)))
- min_idx = TYPE_MIN_VALUE (TYPE_DOMAIN (array_type));
+ idx_type = TYPE_DOMAIN (array_type);
+ if (TYPE_MIN_VALUE (idx_type))
+ min_idx = TYPE_MIN_VALUE (idx_type);
else
- min_idx = fold_convert (TYPE_DOMAIN (array_type), min_idx);
+ min_idx = fold_convert (idx_type, min_idx);
if (TREE_CODE (min_idx) != INTEGER_CST)
return NULL_TREE;
- idx = fold_convert (TYPE_DOMAIN (array_type), idx);
- elt_offset = fold_convert (TYPE_DOMAIN (array_type), elt_offset);
+ elt_offset = fold_convert (idx_type, elt_offset);
}
if (!integer_zerop (min_idx))
@@ -1632,6 +1640,9 @@ maybe_fold_offset_to_array_ref (tree base, tree offset, tree orig_type)
if (!integer_zerop (elt_offset))
idx = int_const_binop (PLUS_EXPR, idx, elt_offset, 0);
+ /* Make sure to possibly truncate late after offsetting. */
+ idx = fold_convert (idx_type, idx);
+
return build4 (ARRAY_REF, orig_type, base, idx, NULL_TREE, NULL_TREE);
}