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; | ^~~~
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).
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.
(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.
>struct test t = {0}; Stopped warning in GCC 5. So maybe this is just on accident.
(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 ...
(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.
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.
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 {}).