diff options
-rw-r--r-- | gcc/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/testsuite/gcc.c-torture/execute/20080604-1.c | 32 | ||||
-rw-r--r-- | gcc/tree-ssa-structalias.c | 44 |
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)); |