Similar to bug 69696, G++ accepts the questionable program below but emits incorrect code overlaying the flexible array member over the variable j. This can be seen in the generated assembly file (below). The underlying problem is that G++ emits a .size directive that corresponds to the size of the type as opposed to the ultimate size of the object (or its largest initializer). This was fixed in the C front end via bug 28865. .globl i .bss .align 4 .type i, @object .size i, 4 i: .zero 4 .globl a .align 4 .type a, @object .size a, 4 a: .zero 4 .globl j .align 4 .type j, @object .size j, 4 j: .zero 4 G++ should either reject such code with an error or it should lay down the global variables consecutively. $ cat x.c && /home/msebor/build/gcc-trunk-svn/gcc/xgcc -B/home/msebor/build/gcc-trunk-svn/gcc -Wall -Wextra -Wpedantic -std=c++14 -xc++ x.c && ./a.out int i; struct A { int n, a[]; } a = i ? A({ 1, { 2 } }) : A({ 2, { 3, 4 } }); int j; int main () { __builtin_printf ("i = %i, j = %i, a = { %i, { ", i, j, a.n); for (int i = 0; i != a.n; ++i) __builtin_printf ("%i, ", a.a[i]); __builtin_printf ("} }\n"); } x.c:2:48: warning: initialization of a flexible array member [-Wpedantic] struct A { int n, a[]; } a = i ? A({ 1, { 2 } }) : A({ 2, { 3, 4 } }); ^ x.c:2:69: warning: initialization of a flexible array member [-Wpedantic] struct A { int n, a[]; } a = i ? A({ 1, { 2 } }) : A({ 2, { 3, 4 } }); ^ i = 0, j = 3, a = { 2, { 3, 4, } }
Confirming. To make things worse, the program output changes between -O0 and -O1: $ (for o in 0 1 2 3; do gcc -O$o -Wall -Wextra y.C && ./a.out; done) i = 0, j = 3, a = { 2, { 3, 4, } } i = 3, j = 0, a = { 2, { 3, 4, } } i = 3, j = 0, a = { 2, { 3, 4, } } i = 3, j = 0, a = { 2, { 3, 4, } }
(In reply to Martin Sebor from comment #1) > Confirming. To make things worse, the program output changes between -O0 > and -O1: > > $ (for o in 0 1 2 3; do gcc -O$o -Wall -Wextra y.C && ./a.out; done) > i = 0, j = 3, a = { 2, { 3, 4, } } > i = 3, j = 0, a = { 2, { 3, 4, } } > i = 3, j = 0, a = { 2, { 3, 4, } } > i = 3, j = 0, a = { 2, { 3, 4, } } I tested some additional optimization levels; -O0 is still the only different one: $ (for o in 0 1 2 3 g s fast; do /usr/local/bin/gcc -O${o} -Wall -Wextra -std=c++14 -xc++ -o 69697_O${o}.exe 69697.c && printf "./69697_O${o}.exe: " && ./69697_O${o}.exe; done) ./69697_O0.exe: i = 0, j = 3, a = { 2, { 3, 4, } } ./69697_O1.exe: i = 3, j = 0, a = { 2, { 3, 4, } } ./69697_O2.exe: i = 3, j = 0, a = { 2, { 3, 4, } } ./69697_O3.exe: i = 3, j = 0, a = { 2, { 3, 4, } } ./69697_Og.exe: i = 3, j = 0, a = { 2, { 3, 4, } } ./69697_Os.exe: i = 3, j = 0, a = { 2, { 3, 4, } } ./69697_Ofast.exe: i = 3, j = 0, a = { 2, { 3, 4, } }
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.