Bug 120511 - Initializer warning on universal zero initializer for array element with double member
Summary: Initializer warning on universal zero initializer for array element with doub...
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: c (show other bugs)
Version: 15.1.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: diagnostic
Depends on:
Blocks:
 
Reported: 2025-06-02 20:00 UTC by Chris Leonard
Modified: 2025-06-04 16:59 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail: 3.4.6
Last reconfirmed: 2025-06-02 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Chris Leonard 2025-06-02 20:00:02 UTC
The following C source causes an erroneous -Wmissing-field-initializers warning on the penultimate line (with a universal zero initializer):

        struct test {
                double val;
                int flag;
        };
        
        struct test test[] = {
                {.val = 1,      .flag = 0},
                {.val = 2,      .flag = 1},
                {0}
        };

The warning is not generated if I try the above code with the member val declared as an int instead of a double.  Likewise it does not occur if I use a single struct instead of an array.  It seems that a combination of an initial floating-point type member, and trying to universal-zero-initialize one of the array elements, triggers this erroneous warning.

Demonstrated with GCC version 15.1.0, built from released source tarball on a Debian system.  This also happens on GCC 12 and 13 for Debian/Ubuntu.

Command: "gcc-15 -W gcc-init-bug.c -c".  Output below:

        gcc-init-bug.c:9:9: warning: missing initializer for field ‘flag’ of ‘struct test’ [-Wmissing-field-initializers]
            9 |         {0}
              |         ^
        gcc-init-bug.c:3:13: note: ‘flag’ declared here
            3 |         int flag;
              |             ^~~~
Comment 1 Drea Pinski 2025-06-02 20:09:59 UTC
I think this is on purpose, here there is an array, so the "universal zero initializer" is not checked.

Note for C23, you could just use `{}` (the manual needs to be updated for that).
Comment 2 Chris Leonard 2025-06-02 20:18:03 UTC
Note that the exact same code using an int instead of a double has no warning.  So either the code using int needs a warning, or this code needs no warning.

Elements in an array of structs should be initialised the same way any individual struct would be initialised, and that's the behaviour when the first element is not a floating-point type.
Comment 3 Chris Leonard 2025-06-02 20:19:19 UTC
(In reply to Chris Leonard from comment #2)
> Note that the exact same code using an int instead of a double has no
> warning.  So either the code using int needs a warning, or this code needs
> no warning.
> 
> Elements in an array of structs should be initialised the same way any
> individual struct would be initialised, and that's the behaviour when the
> first element is not a floating-point type.

...when the first member* is not a floating-point type.
Comment 4 Drea Pinski 2025-06-02 20:21:40 UTC
>struct test t = {0};

Stopped warning in GCC 5. So maybe this is just on accident.
Comment 5 Drea Pinski 2025-06-02 20:26:17 UTC
(In reply to Andrew Pinski from comment #4)
> >struct test t = {0};
> 
> Stopped warning in GCC 5. So maybe this is just on accident.

Looks like that was PR 53119. It looks like it didn't fix the internal usage or the outer most usage of "universal zero init".

Then again in C23, {} should be used ...
Comment 6 Chris Leonard 2025-06-02 20:43:39 UTC
(In reply to Andrew Pinski from comment #5)
> (In reply to Andrew Pinski from comment #4)
> > >struct test t = {0};
> > 
> > Stopped warning in GCC 5. So maybe this is just on accident.
> 
> Looks like that was PR 53119. It looks like it didn't fix the internal usage
> or the outer most usage of "universal zero init".
> 
> Then again in C23, {} should be used ...

I think everyone can agree that C++, GNU C and C23's syntax for this `{}` is better.  But I believe most existing C code uses the convention GCC refers to as "universal zero initializer", whether or not it's currently built with `-std=c23`, because `{0}` was the best we had in standard C until very recently.
Comment 7 Chris Leonard 2025-06-02 22:11:09 UTC
The function `process_init_element` in source file gcc/c/c-typeck.cc clears `constructor_zeroinit` if `!integer_zerop (value.value)`.

The problem is triggered by using a floating-point type for the initial member instead of an integer, so maybe this is related.  Should we check `!zerop (value.value)` instead?

Apologies, I would try this myself but my current machine takes about 10 hours to build GCC, and I deleted my build files to save disk space.
Comment 8 Joseph S. Myers 2025-06-03 17:15:37 UTC
Note that for *decimal* floating-point types, {0} should arguably not be considered a universal zero initializer (it produces a DFP zero with quantum exponent 0, whereas (positive) 0 with the least possible quantum exponent has a representation with all bits 0 and is what results from {}).