summaryrefslogtreecommitdiff
path: root/gcc/tree-ssa-ccp.c
diff options
context:
space:
mode:
authorrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>2008-03-15 14:27:55 +0000
committerrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>2008-03-15 14:27:55 +0000
commitb74882296eb0d172225dc797dad731849bc538be (patch)
tree280eea0f927f26121b5402f767c4c4a84f40d518 /gcc/tree-ssa-ccp.c
parent90ef72692e5e0bb9bab009ce24437d499bec43f8 (diff)
downloadgcc-b74882296eb0d172225dc797dad731849bc538be.tar.gz
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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@133249 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/tree-ssa-ccp.c')
-rw-r--r--gcc/tree-ssa-ccp.c38
1 files changed, 28 insertions, 10 deletions
diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c
index 7cefbf83893..8b8a902169e 100644
--- a/gcc/tree-ssa-ccp.c
+++ b/gcc/tree-ssa-ccp.c
@@ -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);