Bug 68489 - arrays of flexible array members are silently accepted
Summary: arrays of flexible array members are silently accepted
Status: NEW
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: accepts-invalid
: 78635 (view as bug list)
Depends on:
Blocks: flexmembers
  Show dependency treegraph
 
Reported: 2015-11-23 00:35 UTC by Martin Sebor
Modified: 2021-11-12 08:25 UTC (History)
6 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail: 6.0
Last reconfirmed: 2021-11-12 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Martin Sebor 2015-11-23 00:35:56 UTC
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 [];
            ^
Comment 1 Martin Sebor 2016-02-01 20:56:49 UTC
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)
Comment 2 Nathan Sidwell 2016-12-05 20:06:32 UTC
*** Bug 78635 has been marked as a duplicate of this bug. ***
Comment 3 Nathan Sidwell 2016-12-05 20:56:07 UTC
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.
Comment 4 Eric Gallager 2019-05-29 20:48:27 UTC
(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
Comment 5 Nathan Sidwell 2019-05-30 12:16:31 UTC
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.
Comment 6 jsm-csl@polyomino.org.uk 2019-05-30 23:47:47 UTC
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.