This is the mail archive of the mailing list for the GCC project.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Bug with compound literal initializer?

On 03/25/2015 10:09 AM, Martin Sebor wrote:
On 03/24/2015 03:26 PM, Alexey Neyman wrote:

I am seeing a strange behavior when a compound initializer is used in a
structure initialization. A test case:

struct s {
     int y;
     unsigned long *x;

struct s foo = {
     .y = 25,
     .x = (unsigned long [SZ]){},

If SZ is zero, the initializer for .y (".y = 25") member is dropped as

I'm having trouble finding support for any expectation in this
case. When SZ is zero, the source code above is invalid in C
not only because it attempts to create an array with zero
elements but also because it doesn't provide any initializers
for the initializer-list. Strictly speaking, it's required to
be diagnosed but at runtime it has undefined behavior.

This unit test is an excerpt from a bigger array where the compound literal was a statically allocated bitmap. Some of the members of the array may not need such a bitmap, depending on a configuration - and the size of this bitmap was initialized to zero. I didn't expect to see other structure members' initializers go away, though.

What's even worse that this bug not only deletes the .y initializer - it also drops initializers in other array members. E.g., for:

struct s foo[] = {
    { .y = 25, .x = (unsigned long [0]){}, },
    { .y = 37, .x = (unsigned long [1]){}, },

GCC generates:

    .type    foo, @object
    .size    foo, 16
    .zero    16

Regarding undefined behavior: this object has static storage, so I think 6.7.9-10 from C11 should apply:

"... If an object that has static or thread storage duration is not initialized explicitly, then:
â if it has pointer type, it is initialized to a null pointer;
â if it has arithmetic type, it is initialized to (positive or unsigned) zero; â if it is an aggregate, every member is initialized (recursively) according to these rules,
and any padding is initialized to zero bits;
â if it is a union, the first named member is initialized (recursively) according to these
rules, and any padding is initialized to zero bits;"

It's unclear from the GCC manual (or from the apparent absence
of tests for this construct in the test suite) that the code
is intended to do something meaningful in GCC. The compiler
supports zero size arrays as an extension when declaring such
objects as the last members of structs. But in this case, the
code attempts to create an unnanmed temporary array of zero
elements which, IMO, makes no sense. At the same time, I
wouldn't expect gcc to simply omit the initialization for
foo.x. I suggest to open a gcc bug for it.
Point taken on zero-sized array being GCC extension, but I would argue that since GCC permits zero-sized arrays, it should also permit empty initializer-list as an initializer for such arrays. And indeed, with -Wall it complains about neither zero-sized array nor empty initializer-list, and with -Wpedantic it complains about them both.


PS This is the output what I get with gcc 5.0:

$ cat u.c && gcc -Wall -Wextra -Wpedantic -std=c11 -ansi u.c && ./a.out
u.c:7:5: warning: ISO C90 forbids specifying subobject to initialize [-Wpedantic] u.c:8:5: warning: ISO C90 forbids specifying subobject to initialize [-Wpedantic]
u.c:8:29: warning: ISO C90 forbids compound literals [-Wpedantic]
Isn't it strange that C90 warnings are emitted in presence of -std=c11? I don't get these C90 warnings with 4.9.1 if I specify -std=c99 or -stc=c11.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]