|  | // PR c++/90947 - Simple lookup table of array of strings is miscompiled | 
|  | // { dg-do compile } | 
|  | // { dg-options "-O1 -fdump-tree-optimized" } | 
|  |  | 
|  | #define assert(expr) ((expr) ? (void)0 : __builtin_abort ()) | 
|  |  | 
|  | void pr90947 (void) | 
|  | { | 
|  | int vecsize = 4; | 
|  | int index = 0; | 
|  | static const char *a[4][4] = | 
|  | { | 
|  | { ".x", ".y", ".z", ".w" }, | 
|  | { ".xy", ".yz", ".zw", 0 }, | 
|  | { ".xyz", ".yzw", 0, 0 }, | 
|  | { "", 0, 0, 0 }, | 
|  | }; | 
|  |  | 
|  | assert (vecsize >= 1 && vecsize <= 4); | 
|  | assert (index >= 0 && index < 4); | 
|  | assert (a[vecsize - 1][index]); | 
|  | } | 
|  |  | 
|  | void f_a1_1 (void) | 
|  | { | 
|  | { | 
|  | const char* a[1][1] = { { 0 } }; | 
|  | assert (0 == a[0][0]); | 
|  | } | 
|  | { | 
|  | const char* a[1][1] = { { "" } }; | 
|  | assert ('\0' == *a[0][0]); | 
|  | } | 
|  | } | 
|  |  | 
|  | void f_a2_1 (void) | 
|  | { | 
|  | { | 
|  | const char* a[2][1] = { { "" }, { "" } }; | 
|  | assert ('\0' == *a[0][0] && '\0' == *a[1][0]); | 
|  | } | 
|  | { | 
|  | const char* a[2][1] = { { 0 }, { "" } }; | 
|  | assert (0 == a[0][0] && '\0' == *a[1][0]); | 
|  | } | 
|  | { | 
|  | const char* a[2][1] = { { }, { "" } }; | 
|  | assert (0 == a[0][0] && '\0' == *a[1][0]); | 
|  | } | 
|  | } | 
|  |  | 
|  | void f_a2_2 (void) | 
|  | { | 
|  | { | 
|  | const char* a[2][2] = { { "", "" }, { "", "" } }; | 
|  | assert ('\0' == *a[0][0] && '\0' == *a[0][1]); | 
|  | assert ('\0' == *a[1][0] && '\0' == *a[1][1]); | 
|  | } | 
|  | { | 
|  | const char* a[2][2] = { { "", "" }, { "", 0 } }; | 
|  | assert ('\0' == *a[0][0] && '\0' == *a[0][1]); | 
|  | assert ('\0' == *a[1][0] && 0 == a[1][1]); | 
|  | } | 
|  | { | 
|  | const char* a[2][2] = { { "", "" }, { "" } }; | 
|  | assert ('\0' == *a[0][0] && '\0' == *a[0][1]); | 
|  | assert ('\0' == *a[1][0] && 0 == a[1][1]); | 
|  | } | 
|  | { | 
|  | const char* a[2][2] = { { "", "" }, { 0, "" } }; | 
|  | assert ('\0' == *a[0][0] && '\0' == *a[0][1]); | 
|  | assert (0 == a[1][0] && '\0' == *a[1][1]); | 
|  | } | 
|  | { | 
|  | const char* a[2][2] = { { "", 0 }, { 0, "" } }; | 
|  | assert ('\0' == *a[0][0] && 0 == a[0][1]); | 
|  | assert (0 == a[1][0] && '\0' == *a[1][1]); | 
|  | } | 
|  | { | 
|  | const char* a[2][2] = { { 0, 0 }, { 0, "" } }; | 
|  | assert (0 == a[0][0] && 0 == a[0][1]); | 
|  | assert (0 == a[1][0] && '\0' == *a[1][1]); | 
|  | } | 
|  | { | 
|  | const char* a[2][2] = { { 0 }, { 0, "" } }; | 
|  | assert (0 == a[0][0] && 0 == a[0][1]); | 
|  | assert (0 == a[1][0] && '\0' == *a[1][1]); | 
|  | } | 
|  | { | 
|  | const char* a[2][2] = { { }, { 0, "" } }; | 
|  | assert (0 == a[0][0] && 0 == a[0][1]); | 
|  | assert (0 == a[1][0] && '\0' == *a[1][1]); | 
|  | } | 
|  | } | 
|  |  | 
|  | void f_a2_2_2 (void) | 
|  | { | 
|  | { | 
|  | const char* a[2][2][2] = | 
|  | { { { "", "" }, { "", "" } }, { { "", "" }, { "", "" } } }; | 
|  |  | 
|  | assert ('\0' == *a[0][0][0] && '\0' == *a[0][0][1]); | 
|  | assert ('\0' == *a[0][1][0] && '\0' == *a[0][1][1]); | 
|  | assert ('\0' == *a[1][0][0] && '\0' == *a[1][0][1]); | 
|  | assert ('\0' == *a[1][1][0] && '\0' == *a[1][1][1]); | 
|  | } | 
|  |  | 
|  | { | 
|  | const char* a[2][2][2] = | 
|  | { { { "", "" }, { "", "" } }, { { "", "" }, { 0, "" } } }; | 
|  |  | 
|  | assert ('\0' == *a[0][0][0] && '\0' == *a[0][0][1]); | 
|  | assert ('\0' == *a[0][1][0] && '\0' == *a[0][1][1]); | 
|  | assert ('\0' == *a[1][0][0] && '\0' == *a[1][0][1]); | 
|  | assert (0 == a[1][1][0] && '\0' == *a[1][1][1]); | 
|  | } | 
|  |  | 
|  | { | 
|  | const char* a[2][2][2] = | 
|  | { { { "", "" }, { "", "" } }, { { 0, 0 }, { 0, "" } } }; | 
|  |  | 
|  | assert ('\0' == *a[0][0][0] && '\0' == *a[0][0][1]); | 
|  | assert ('\0' == *a[0][1][0] && '\0' == *a[0][1][1]); | 
|  | assert (0 == a[1][0][0] && 0 == a[1][0][1]); | 
|  | assert (0 == a[1][1][0] && '\0' == *a[1][1][1]); | 
|  | } | 
|  |  | 
|  | { | 
|  | const char* a[2][2][2] = | 
|  | { { { "", "" }, { 0, 0 } }, { { 0, 0 }, { 0, "" } } }; | 
|  |  | 
|  | assert ('\0' == *a[0][0][0] && '\0' == *a[0][0][1]); | 
|  | assert (0 == a[0][1][0] && 0 == a[0][1][1]); | 
|  | assert (0 == a[1][0][0] && 0 == a[1][0][1]); | 
|  | assert (0 == a[1][1][0] && '\0' == *a[1][1][1]); | 
|  | } | 
|  |  | 
|  | { | 
|  | const char* a[2][2][2] = | 
|  | { { { 0, 0 }, { 0, 0 } }, { { 0, 0 }, { 0, "" } } }; | 
|  |  | 
|  | assert (0 == a[0][0][0] && 0 == a[0][0][1]); | 
|  | assert (0 == a[0][1][0] && 0 == a[0][1][1]); | 
|  | assert (0 == a[1][0][0] && 0 == a[1][0][1]); | 
|  | assert (0 == a[1][1][0] && '\0' == *a[1][1][1]); | 
|  | } | 
|  |  | 
|  | { | 
|  | const char* a[2][2][2] = | 
|  | { { { }, { } }, { { }, { 0, "" } } }; | 
|  |  | 
|  | assert (0 == a[0][0][0] && 0 == a[0][0][1]); | 
|  | assert (0 == a[0][1][0] && 0 == a[0][1][1]); | 
|  | assert (0 == a[1][0][0] && 0 == a[1][0][1]); | 
|  | assert (0 == a[1][1][0] && '\0' == *a[1][1][1]); | 
|  | } | 
|  | } | 
|  |  | 
|  | void f_sa2_2_2 (void) | 
|  | { | 
|  | struct S { const char a[2], *s, c; }; | 
|  |  | 
|  | { | 
|  | const struct S a[2][2][2] = { | 
|  | { }, | 
|  | { | 
|  | { { }, { "", "" } }, | 
|  | { } | 
|  | } | 
|  | }; | 
|  |  | 
|  | assert ('\0' == *a[0][0][0].a && 0 == a[0][0][0].s && 0 == a[0][0][0].c); | 
|  | assert ('\0' == *a[0][0][1].a && 0 == a[0][0][1].s && 0 == a[0][0][1].c); | 
|  | assert ('\0' == *a[0][1][0].a && 0 == a[0][1][0].s && 0 == a[0][1][0].c); | 
|  | assert ('\0' == *a[0][1][1].a && 0 == a[0][1][1].s && 0 == a[0][1][1].c); | 
|  |  | 
|  | assert ('\0' == *a[1][0][0].a && 0 == a[1][0][0].s && 0 == a[1][0][0].c); | 
|  | assert ('\0' == *a[1][0][1].a && '\0' == *a[1][0][1].s && 0 == a[1][0][1].c); | 
|  | assert ('\0' == *a[1][1][0].a && 0 == a[1][1][0].s && 0 == a[1][1][0].c); | 
|  | assert ('\0' == *a[1][1][1].a && 0 == a[1][1][1].s && 0 == a[1][1][1].c); | 
|  | } | 
|  |  | 
|  | { | 
|  | const struct S a[2][2][2] = { | 
|  | { }, | 
|  | { | 
|  | { { } }, | 
|  | { { "", "" } } | 
|  | } | 
|  | }; | 
|  |  | 
|  | assert ('\0' == *a[0][0][0].a && 0 == a[0][0][0].s); | 
|  | assert ('\0' == *a[0][0][1].a && 0 == a[0][0][1].s); | 
|  | assert ('\0' == *a[0][1][0].a && 0 == a[0][1][0].s); | 
|  | assert ('\0' == *a[0][1][1].a && 0 == a[0][1][1].s); | 
|  |  | 
|  | assert ('\0' == *a[1][0][0].a && 0 == a[1][0][0].s); | 
|  | assert ('\0' == *a[1][0][1].a && 0 == a[1][0][1].s); | 
|  | assert ('\0' == *a[1][1][0].a && '\0' == *a[1][1][0].s); | 
|  | assert ('\0' == *a[1][1][1].a && 0 == a[1][1][1].s); | 
|  | } | 
|  |  | 
|  | { | 
|  | const struct S a[2][2][2] = { | 
|  | { }, | 
|  | { | 
|  | { { }, { } }, | 
|  | { { }, { "", "", 0 } } | 
|  | } | 
|  | }; | 
|  |  | 
|  | assert ('\0' == *a[0][0][0].a && 0 == a[0][0][0].s); | 
|  | assert ('\0' == *a[0][0][1].a && 0 == a[0][0][1].s); | 
|  | assert ('\0' == *a[0][1][0].a && 0 == a[0][1][0].s); | 
|  | assert ('\0' == *a[0][1][1].a && 0 == a[0][1][1].s); | 
|  |  | 
|  | assert ('\0' == *a[1][0][0].a && 0 == a[1][0][0].s); | 
|  | assert ('\0' == *a[1][0][1].a && 0 == a[1][0][1].s); | 
|  | assert ('\0' == *a[1][1][0].a && 0 == a[1][1][0].s); | 
|  | assert ('\0' == *a[1][1][1].a && '\0' == *a[1][1][1].s); | 
|  | } | 
|  |  | 
|  | { | 
|  | const struct S a[2][2][2] = { | 
|  | { | 
|  | { { { 0 }, 0, 0 }, { { 0 } , 0, 0 } }, | 
|  | { { { 0 }, 0, 0 }, { { 0 } , 0, 0 } }, | 
|  | }, | 
|  | { | 
|  | { { { 0 }, 0, 0 }, { { 0 } , 0, 0 } }, | 
|  | { { }, { "", "", 0 } } | 
|  | } | 
|  | }; | 
|  |  | 
|  | assert ('\0' == *a[0][0][0].a && 0 == a[0][0][0].s); | 
|  | assert ('\0' == *a[0][0][1].a && 0 == a[0][0][1].s); | 
|  | assert ('\0' == *a[0][1][0].a && 0 == a[0][1][0].s); | 
|  | assert ('\0' == *a[0][1][1].a && 0 == a[0][1][1].s); | 
|  |  | 
|  | assert ('\0' == *a[1][0][0].a && 0 == a[1][0][0].s); | 
|  | assert ('\0' == *a[1][0][1].a && 0 == a[1][0][1].s); | 
|  | assert ('\0' == *a[1][1][0].a && 0 == a[1][1][0].s); | 
|  | assert ('\0' == *a[1][1][1].a && '\0' == *a[1][1][1].s); | 
|  | } | 
|  | } | 
|  |  | 
|  | // { dg-final { scan-tree-dump-not "abort" "optimized" } } |