diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 4a2611a3806..796653212ae 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2010-11-02 Richard Guenther + + PR tree-optimization/46149 + * tree-ssa-structalias.c (get_constraint_for_1): Properly handle + non-indirect MEM_REF variants. + 2010-11-02 Richard Guenther PR tree-optimization/46216 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 32fedf6b43c..d7135d88c2d 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2010-11-02 Richard Guenther + + PR tree-optimization/46149 + * g++.dg/torture/pr46149.C: New testcase. + 2010-11-02 Richard Guenther PR tree-optimization/46216 diff --git a/gcc/testsuite/g++.dg/torture/pr46149.C b/gcc/testsuite/g++.dg/torture/pr46149.C new file mode 100644 index 00000000000..bdc3d770412 --- /dev/null +++ b/gcc/testsuite/g++.dg/torture/pr46149.C @@ -0,0 +1,51 @@ +// { dg-do run } +// { dg-options "-fno-tree-sra" } + +struct S +{ + S ():p ((char *) __builtin_calloc (1, 1)) + { + } + char *p; +}; + +template < class T > struct A +{ + A (const S & __m1, const T & __m2):m1 (__m1), m2 (__m2) + { + } + const S & m1; + const T & m2; +}; + +struct B:A < S > +{ + B (const S & __v):A < S > (__v, __v) + { + } +}; + +struct C:A < B > +{ + C (const S & __e1, const B & __e2):A < B > (__e1, __e2) + { + } +}; + +struct D +{ + D (const C & __c):c (__c) + { + } + const C c; +}; + +int +main () +{ + S s; + B b (s); + C c (s, b); + D d (c); + return d.c.m2.m2.p[0]; +} diff --git a/gcc/tree-ssa-structalias.c b/gcc/tree-ssa-structalias.c index ed05178c23d..315bef6f0da 100644 --- a/gcc/tree-ssa-structalias.c +++ b/gcc/tree-ssa-structalias.c @@ -3339,9 +3339,41 @@ get_constraint_for_1 (tree t, VEC (ce_s, heap) **results, bool address_p, { case MEM_REF: { + struct constraint_expr *c; + varinfo_t vi, curr; tree off = double_int_to_tree (sizetype, mem_ref_offset (t)); get_constraint_for_ptr_offset (TREE_OPERAND (t, 0), off, results); do_deref (results); + + /* If we are not taking the address then make sure to process + all subvariables we might access. */ + c = VEC_last (ce_s, *results); + if (address_p + || c->type != SCALAR) + return; + + vi = get_varinfo (c->var); + curr = vi->next; + if (!vi->is_full_var + && curr) + { + unsigned HOST_WIDE_INT size; + if (host_integerp (TYPE_SIZE (TREE_TYPE (t)), 1)) + size = TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (t))); + else + size = -1; + for (; curr; curr = curr->next) + { + if (curr->offset - vi->offset < size) + { + struct constraint_expr cs = *c; + cs.var = curr->id; + VEC_safe_push (ce_s, heap, *results, &cs); + } + else + break; + } + } return; } case ARRAY_REF: