Until gcc 9.2.0, the following usage was correct: struct S { int size; int data[]; }; struct { S s; int data[16]; } var; From 9.2.1 onwards, this no longer compiles because the checking has gotten stricter: <source>:3:9: error: flexible array member 'S::data' not at end of 'struct<unnamed>' 3 | int data[]; | ^~~~ <source>:8:9: note: next member 'int <unnamed struct>::data [16]' declared here 8 | int data[16]; Funnily, the following workaround circumvents the check: struct { union { struct { S s; int data[16]; }; }; } var; Can we make this check more robust so valid usage isn't rejected? I will leave it up to the experts to find the solution, but it would be easy for me to use an attribute such as [[space_follows]] to tell the compiler that valid space follows this member.
>Can we make this check more robust so valid usage isn't rejected? Why do you think it is valid?
(In reply to Andrew Pinski from comment #1) > >Can we make this check more robust so valid usage isn't rejected? > > Why do you think it is valid? Because I know the flexible array member data isn't dangling. I have allocated space immediately following the member that I would like to use. It has been working perfectly in previous versions. I understand there could be alignment concerns and if that is the case I am happy to declare it packed. Finally, the workaround gives the same outcome by typing some more code.
I guess at _least_ [[no_unique_address]] would be needed but then who knows how exactly previous behavior was in this regard? Martin, you tightened the checks (I agree to those), any input?
https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html "A structure containing a flexible array member, or a union containing such a structure (possibly recursively), may not be a member of a structure or an element of an array. (However, these uses are permitted by GCC as extensions.)" The C++ compiler implements the stricter rule from ISO C, not the extension. (In reply to Amir Ansari from comment #2) > Because I know the flexible array member data isn't dangling. I have > allocated space immediately following the member that I would like to use. That's not how you're supposed to do it. You're supposed to dynamically allocate space for the struct and space after it, not place it inside a larger structute. > It has been working perfectly in previous versions. I'd say it's actually been undefined because G++ allowed pretty much any nonsense in terms of flexible array members.
Right, the code is invalid according to the C rules. It's accepted by the C front end with a pedantic warning. It's intentionally rejected by the C++ front-end which supports fewer of the GCC extensions. The zero-length array extension can be used in this context instead, though accessing elements of the zero-length array may be diagnosed. (In both cases, GCC assumes that the array doesn't overlap other members so accesses to its elements are undefined.)