Bug 69697 - incorrect runtime initialization of static flexible array members
Summary: incorrect runtime initialization of static flexible array members
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 6.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: wrong-code
Depends on:
Blocks: flexmembers
  Show dependency treegraph
 
Reported: 2016-02-05 22:03 UTC by Martin Sebor
Modified: 2019-01-07 17:38 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail: 5.3.1, 6.3.0, 7.0
Last reconfirmed: 2017-03-27 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Martin Sebor 2016-02-05 22:03:18 UTC
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, } }
Comment 1 Martin Sebor 2017-03-27 20:42:03 UTC
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, } }
Comment 2 Eric Gallager 2018-09-22 03:32:34 UTC
(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, } }
Comment 3 Bernd Edlinger 2019-01-07 17:09:24 UTC
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
Comment 4 Bernd Edlinger 2019-01-07 17:38:02 UTC
Fixed on trunk.