Bug 94132 - Valid usage of flexible array member failing to compile
Summary: Valid usage of flexible array member failing to compile
Status: RESOLVED INVALID
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 10.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks: flexmembers
  Show dependency treegraph
 
Reported: 2020-03-11 02:59 UTC by Amir Ansari
Modified: 2020-03-11 14:47 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Amir Ansari 2020-03-11 02:59:51 UTC
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.
Comment 1 Andrew Pinski 2020-03-11 03:32:03 UTC
>Can we make this check more robust so valid usage isn't rejected? 

Why do you think it is valid?
Comment 2 Amir Ansari 2020-03-11 03:38:34 UTC
(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.
Comment 3 Richard Biener 2020-03-11 08:09:36 UTC
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?
Comment 4 Jonathan Wakely 2020-03-11 11:13:10 UTC
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.
Comment 5 Martin Sebor 2020-03-11 14:47:19 UTC
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.)