Related to bug 68478, g++ accepts definitions of C flexible array members as an extension for compatibility. However, C doesn't intend to allow declaring arrays of structures containing flexible array members. Such uses are rejected by gcc (with a hard error), and diagnosed either as warnings (Clang) or hard errors (IBM XLC++) in C++ programs. However, as the test case below shows, g++ silently accepts such uses: $ cat z.cpp && /build/gcc-trunk-svn/gcc/xg++ -B /build/gcc-trunk-svn/gcc -Wall -Wextra -Wpedantic -O2 -S -o/dev/null z.cpp struct A { int n; int a []; }; struct A a[2]; // should be diagnosed/rejected z.cpp:3:12: warning: ISO C++ forbids zero-size array ‘a’ [-Wpedantic] int a []; ^
Bug 28865 provides useful background on this problem. GCC (in C mode) used to accept definitions of initialized array objects of structures with flexible array members. That feature was removed in response to bug 28865 which pointed out that the size of such objects (emitted into the assembly in the form of the .size directive) is incorrect. G++ 6.0 suffers from both of these problems because it accepts definitions of such objects. Prior versions rejected such code. The following test case demonstrates the consequences of this problem: $ cat t.c && /home/msebor/build/gcc-trunk-git/gcc/xgcc -B/home/msebor/build/gcc-trunk-git/gcc -Wall -Wextra -Wpedantic -std=c++11 -xc++ t.c && ./a.out struct S { char x; int y []; }; struct S s[2] = { { 1, { 2, 3 } }, { 4, { 5, 6 } } }; int main (void) { __builtin_printf ("sizeof s = %zu\n" "s[0] @%p = { %hhi, { %i, %i } }\n" "s[1] @%p = { %hhi, { %i, %i } }\n", sizeof (struct S), &s [0], s[0].x, s[0].y [0], s[0].y [1], &s [1], s[1].x, s[1].y [0], s[1].y [1]); if ( s [0].x != 1 || s [0].y [0] != 2 || s [0].y [1] != 3 || s [1].x != 4 || s [1].y [0] != 5 || s [1].y [1] != 6) __builtin_abort (); } t.c:6:1: warning: initialization of a flexible array member [-Wpedantic] }; ^ t.c:6:1: warning: initialization of a flexible array member [-Wpedantic] t.c: In function ‘int main()’: t.c:14:61: warning: format ‘%p’ expects argument of type ‘void*’, but argument 3 has type ‘S*’ [-Wformat=] &s [1], s[1].x, s[1].y [0], s[1].y [1]); ^ t.c:14:61: warning: format ‘%p’ expects argument of type ‘void*’, but argument 7 has type ‘S*’ [-Wformat=] sizeof s = 4 s[0] @0x601048 = { 1, { 2, 3 } } s[1] @0x60104c = { 2, { 3, 4 } } Aborted (core dumped)
*** Bug 78635 has been marked as a duplicate of this bug. ***
Jakub commented on 78635: I thought that such constructs are widely used though, I believe e.g. glibc used arrays of structs with flexible array members in several places. Maybe it has changed, I've lost track. So, before changing anything like that we'd need to make sure e.g. glibc still builds.
(In reply to Nathan Sidwell from comment #3) > Jakub commented on 78635: > I thought that such constructs are widely used though, I believe e.g. glibc > used arrays of structs with flexible array members in several places. Maybe > it > has changed, I've lost track. So, before changing anything like that we'd > need > to make sure e.g. glibc still builds. cc-ing him
if GCC rejects such arrays of trailing-array structs, and my assumption that glibc is in C, I don't think it can be using them. IMHO they don't make sense and a compile time error would be good.
I'm not sure about arrays of structs, but glibc uses [0] at end of struct in some cases where proper flexible array members would not be accepted. E.g. struct __gconv_info { size_t __nsteps; struct __gconv_step *__steps; __extension__ struct __gconv_step_data __data[0]; } which is then used as a non-last member of another structure.