As pointed in the following discussion https://gcc.gnu.org/ml/gcc-patches/2016-02/msg00420.html, g++ allows local structs with flexible array members to be initialized on definition but then allocates the arrays in a way that overlaps other local variables, leading to data corruption. In C mode, GCC rejects initialization of such structs (this was done to fix bug 28865). G++ should either also reject initialiation of such structs, or it should do it without this overlapping problem. Note that bug 68489 is also related to this problem, as is bug 69338. The following test case shows that while structures containing flexible array members and having static or thread storage duration are initialized correctly, those having automatic storage duration are not. $ cat t.c && /build/gcc-trunk/gcc/xgcc -B /build/gcc-trunk/gcc -Wall -Wextra -Wpedantic -xc++ t.c && ./a.out enum { X = 12345678, Y = 87654321 }; struct A { int n, a []; }; struct A a0 = { 1, { 2, 3, 4 } }; void print (const int *i, struct A *a, const int *j) { __builtin_printf ("\ni = %i\n" "a = { %i, { %i, %i, %i }\n" "j = %i\n", *i, a->n, a->a[0], a->a[1], a->a[2], *j); if (*i != X || *j != Y || a->a[0] != 2 || a->a[1] != 3 || a->a[2] != 4) __builtin_abort (); } int main () { { static int i = X; static struct A a = { 1, { 2, 3, 4 } }; static int j = Y; print (&i, &a, &j); } { __thread int i = X; __thread struct A a = { 1, { 2, 3, 4 } }; __thread int j = Y; print (&i, &a, &j); } { int i = X; struct A a = { 1, { 2, 3, 4 } }; int j = Y; print (&i, &a, &j); } } t.c:4:32: warning: initialization of a flexible array member [-Wpedantic] struct A a0 = { 1, { 2, 3, 4 } }; ^ t.c: In function ‘int main()’: t.c:22:46: warning: initialization of a flexible array member [-Wpedantic] static struct A a = { 1, { 2, 3, 4 } }; ^ t.c:28:22: warning: function-scope ‘i’ implicitly auto and declared ‘__thread’ __thread int i = X; ^ t.c:29:27: warning: function-scope ‘a’ implicitly auto and declared ‘__thread’ __thread struct A a = { 1, { 2, 3, 4 } }; ^ t.c:29:48: warning: initialization of a flexible array member [-Wpedantic] __thread struct A a = { 1, { 2, 3, 4 } }; ^ t.c:30:22: warning: function-scope ‘j’ implicitly auto and declared ‘__thread’ __thread int j = Y; ^ t.c:36:39: warning: initialization of a flexible array member [-Wpedantic] struct A a = { 1, { 2, 3, 4 } }; ^ i = 12345678 a = { 1, { 2, 3, 4 } j = 87654321 i = 12345678 a = { 1, { 2, 3, 4 } j = 87654321 i = 4 a = { 1, { 2, 3, 4 } j = 87654321 Aborted (core dumped)
This problem seems to have always existed in C++.
I get slightly different output, but same basic problem: $ /usr/local/bin/g++ -Wall -Wextra -Wpedantic -xc++ -o 69696.exe 69696.c 69696.c:3:22: warning: ISO C++ forbids flexible array member ‘a’ [-Wpedantic] struct A { int n, a []; }; ^ 69696.c:4:32: warning: initialization of a flexible array member [-Wpedantic] struct A a0 = { 1, { 2, 3, 4 } }; ^ 69696.c: In function ‘int main()’: 69696.c:22:46: warning: initialization of a flexible array member [-Wpedantic] static struct A a = { 1, { 2, 3, 4 } }; ^ 69696.c:28:22: warning: function-scope ‘i’ implicitly auto and declared ‘__thread’ __thread int i = X; ^ 69696.c:29:27: warning: function-scope ‘a’ implicitly auto and declared ‘__thread’ __thread struct A a = { 1, { 2, 3, 4 } }; ^ 69696.c:29:48: warning: initialization of a flexible array member [-Wpedantic] __thread struct A a = { 1, { 2, 3, 4 } }; ^ 69696.c:30:22: warning: function-scope ‘j’ implicitly auto and declared ‘__thread’ __thread int j = Y; ^ 69696.c:36:39: warning: initialization of a flexible array member [-Wpedantic] struct A a = { 1, { 2, 3, 4 } }; ^ $ ./69696.exe i = 12345678 a = { 1, { 2, 3, 4 } j = 87654321 i = 12345678 a = { 1, { 0, 0, 4194928 } j = 87654321 Abort trap $ Also, as a separate issue, the "implicitly auto and declared __thread" warning should have its own separate flag controlling it.
Author: edlinger Date: Mon Jan 7 17:08:51 2019 New Revision: 267653 URL: https://gcc.gnu.org/viewcvs?rev=267653&root=gcc&view=rev Log: PR c++/88261 PR c++/69338 PR c++/69696 PR c++/69697 * cp-tree.h (LOOKUP_ALLOW_FLEXARRAY_INIT): New flag value. * typeck2.c (digest_init_r): Raise an error for non-static initialization of a flexible array member. (process_init_constructor, massage_init_elt, process_init_constructor_array, process_init_constructor_record, process_init_constructor_union, process_init_constructor): Add the flags parameter and pass it thru. (store_init_value): Pass LOOKUP_ALLOW_FLEXARRAY_INIT parameter to digest_init_flags for static decls. gcc/testsuite: 2019-01-07 Bernd Edlinger <bernd.edlinger@hotmail.de> PR c++/88261 PR c++/69338 PR c++/69696 PR c++/69697 * gcc.dg/array-6.c: Move from here ... * c-c++-common/array-6.c: ... to here and add some more test coverage. * g++.dg/pr69338.C: New test. * g++.dg/pr69697.C: Likewise. * g++.dg/ext/flexary32.C: Likewise. * g++.dg/ext/flexary3.C: Adjust test. * g++.dg/ext/flexary12.C: Likewise. * g++.dg/ext/flexary13.C: Likewise. * g++.dg/ext/flexary15.C: Likewise. * g++.dg/warn/Wplacement-new-size-1.C: Likewise. * g++.dg/warn/Wplacement-new-size-2.C: Likewise. * g++.dg/warn/Wplacement-new-size-6.C: Likewise. Added: trunk/gcc/testsuite/c-c++-common/array-6.c - copied, changed from r267652, trunk/gcc/testsuite/gcc.dg/array-6.c trunk/gcc/testsuite/g++.dg/ext/flexary32.C trunk/gcc/testsuite/g++.dg/pr69338.C trunk/gcc/testsuite/g++.dg/pr69697.C Removed: trunk/gcc/testsuite/gcc.dg/array-6.c Modified: trunk/gcc/cp/ChangeLog trunk/gcc/cp/cp-tree.h trunk/gcc/cp/typeck2.c trunk/gcc/testsuite/ChangeLog trunk/gcc/testsuite/g++.dg/ext/flexary12.C trunk/gcc/testsuite/g++.dg/ext/flexary13.C trunk/gcc/testsuite/g++.dg/ext/flexary15.C trunk/gcc/testsuite/g++.dg/ext/flexary3.C trunk/gcc/testsuite/g++.dg/warn/Wplacement-new-size-1.C trunk/gcc/testsuite/g++.dg/warn/Wplacement-new-size-2.C trunk/gcc/testsuite/g++.dg/warn/Wplacement-new-size-6.C
Fixed on trunk.