#include <stddef.h> struct S { int i; int j; }; struct R { int k; struct S a; }; struct Q { float k; struct S a; }; struct Q s; int __attribute__((noinline,noclone)) test1 (void *q) { struct S *b = (struct S *)((char *)q + sizeof (int)); s.a.i = 0; b->i = 3; return s.a.i; } int __attribute__((noinline,noclone)) test2 (void *q) { struct S *b = &((struct R *)q)->a; s.a.i = 0; b->i = 3; return s.a.i; } int __attribute__((noinline,noclone)) test3 (void *q) { s.a.i = 0; ((struct S *)((char *)q + sizeof (int)))->i = 3; return s.a.i; } extern void abort (void); int main() { if (sizeof (float) != sizeof (int) || offsetof (struct R, a) != sizeof (int) || offsetof (struct Q, a) != sizeof (int)) return 0; s.a.i = 1; s.a.j = 2; if (test1 ((void *)&s) != 3) abort (); s.a.i = 1; s.a.j = 2; if (test2 ((void *)&s) != 3) abort (); s.a.i = 1; s.a.j = 2; if (test3 ((void *)&s) != 3) abort (); return 0; }
is miscompiled (in test2 only, I believe I have fixed the other cases at some point by throttling down maybe_fold_offset_to_component_ref). We re-construct from q.1_2 = (struct R *) q_1(D); b_3 = &q.1_2->a; s.a.i = 0; b_3->i = 3; via forwprop struct R * q.1; <bb 2>: q.1_2 = (struct R *) q_1(D); s.a.i = 0; q.1_2->a.i = 3; and the oracle (or VOP construction in 4.3) believes that we can't access an object of type Q via a pointer to type R (which is correct). -- Summary: Bogus access re-construction from offset calculation Product: gcc Version: 4.6.0 Status: UNCONFIRMED Keywords: wrong-code Severity: normal Priority: P3 Component: tree-optimization AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: rguenth at gcc dot gnu dot org http://gcc.gnu.org/bugzilla/show_bug.cgi?id=44468