------- Comment #5 from rguenth at gcc dot gnu dot org 2009-10-08 15:03 ------- What we can see after inlining is
<bb 2>: X[0][0] ={v} 12345; D.1614_1 = (long unsigned int *) &X[1]; *D.1614_1 ={v} 67890; D.1614_2 = (long unsigned int *) &X[1]; X.0_3 = (long unsigned int *) &X; D.1623_5 = *X.0_3; X[0][0] ={v} D.1623_5; D.1622_6 = *D.1614_2; X[1][0] ={v} D.1622_6; D.1623_7 = *X.0_3; if (D.1623_7 != 12345) goto <bb 4>; ... <bb 6>: D.1625_10 = X[0][1]; if (D.1625_10 != 67890) goto <bb 7>; else goto <bb 8>; so the final check is reading from X[0][1] but we only ever store to X[1][0]. So the testcase can be simplified to typedef unsigned long obj[1]; extern void abort (void); static void test_level2(obj X[]) { if (*X[1] != 67890) abort (); } int main() { obj X[2]; X[1][0] = 67890; test_level2(X); return 0; } or even to typedef unsigned long obj[1]; extern void abort (void); int main() { obj X[2]; X[1][0] = 67890; if (X[0][1] != 67890) abort (); return 0; } which will also fail with 4.2.4 (but still not 4.5.0). But that also raises the question of the validity again. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=41630