aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog5
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/20080604-1.c32
-rw-r--r--gcc/tree-ssa-structalias.c44
4 files changed, 53 insertions, 32 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 0932c9a..0cb236d 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,8 @@
+2008-06-04 Richard Guenther <rguenther@suse.de>
+
+ * tree-ssa-structalias.c (handle_ptr_arith): Correctly handle
+ negative or non-representable offsets.
+
2008-06-03 H.J. Lu <hongjiu.lu@intel.com>
* config/i386/i386.c (ix86_gen_leave): New.
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 536462e..d43613a 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2008-06-04 Richard Guenther <rguenther@suse.de>
+
+ * gcc.c-torture/execute/20080604-1.c: New testcase.
+
2008-06-03 Andy Hutchinson <hutchinsonandy@aim.com>
PR/34880
diff --git a/gcc/testsuite/gcc.c-torture/execute/20080604-1.c b/gcc/testsuite/gcc.c-torture/execute/20080604-1.c
new file mode 100644
index 0000000..5ba35cb
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/20080604-1.c
@@ -0,0 +1,32 @@
+struct barstruct { char const* some_string; } x;
+extern void abort (void);
+void __attribute__((noinline))
+foo(void)
+{
+ if (!x.some_string)
+ abort ();
+}
+void baz(int b)
+{
+ struct barstruct bar;
+ struct barstruct* barptr;
+ if (b)
+ barptr = &bar;
+ else
+ {
+ barptr = &x + 1;
+ barptr = barptr - 1;
+ }
+ barptr->some_string = "Everything OK";
+ foo();
+ barptr->some_string = "Everything OK";
+}
+int main()
+{
+ x.some_string = (void *)0;
+ baz(0);
+ if (!x.some_string)
+ abort ();
+ return 0;
+}
+
diff --git a/gcc/tree-ssa-structalias.c b/gcc/tree-ssa-structalias.c
index 0e42214..570c173 100644
--- a/gcc/tree-ssa-structalias.c
+++ b/gcc/tree-ssa-structalias.c
@@ -3531,8 +3531,7 @@ handle_ptr_arith (VEC (ce_s, heap) *lhsc, tree expr)
unsigned int i = 0;
unsigned int j = 0;
VEC (ce_s, heap) *temp = NULL;
- unsigned int rhsoffset = 0;
- bool unknown_addend = false;
+ unsigned HOST_WIDE_INT rhsunitoffset, rhsoffset;
if (TREE_CODE (expr) != POINTER_PLUS_EXPR)
return false;
@@ -3541,13 +3540,18 @@ handle_ptr_arith (VEC (ce_s, heap) *lhsc, tree expr)
op1 = TREE_OPERAND (expr, 1);
gcc_assert (POINTER_TYPE_P (TREE_TYPE (op0)));
- get_constraint_for (op0, &temp);
+ /* If the offset is not a non-negative integer constant that fits
+ in a HOST_WIDE_INT, we cannot handle it here. */
+ if (!host_integerp (op1, 1))
+ return false;
- /* Handle non-constants by making constraints from integer. */
- if (TREE_CODE (op1) == INTEGER_CST)
- rhsoffset = TREE_INT_CST_LOW (op1) * BITS_PER_UNIT;
- else
- unknown_addend = true;
+ /* Make sure the bit-offset also fits. */
+ rhsunitoffset = TREE_INT_CST_LOW (op1);
+ rhsoffset = rhsunitoffset * BITS_PER_UNIT;
+ if (rhsunitoffset != rhsoffset / BITS_PER_UNIT)
+ return false;
+
+ get_constraint_for (op0, &temp);
for (i = 0; VEC_iterate (ce_s, lhsc, i, c); i++)
for (j = 0; VEC_iterate (ce_s, temp, j, c2); j++)
@@ -3564,30 +3568,6 @@ handle_ptr_arith (VEC (ce_s, heap) *lhsc, tree expr)
c2->var = temp->id;
c2->offset = 0;
}
- else if (unknown_addend)
- {
- /* Can't handle *a + integer where integer is unknown. */
- if (c2->type != SCALAR)
- {
- struct constraint_expr intc;
- intc.var = integer_id;
- intc.offset = 0;
- intc.type = SCALAR;
- process_constraint (new_constraint (*c, intc));
- }
- else
- {
- /* We known it lives somewhere within c2->var. */
- varinfo_t tmp = get_varinfo (c2->var);
- for (; tmp; tmp = tmp->next)
- {
- struct constraint_expr tmpc = *c2;
- c2->var = tmp->id;
- c2->offset = 0;
- process_constraint (new_constraint (*c, tmpc));
- }
- }
- }
else
c2->offset = rhsoffset;
process_constraint (new_constraint (*c, *c2));