When an anonymous structure gets initialized, gcc always starts complaining about the last field: ////////////////////////////////////////// gcc -Wextra warn.c -o /dev/null ////////////////////////////////////////// struct foo { struct { char a; char b; }; }; int main(void) { struct foo test = { .a = 1, .b = 2, }; return test.a == 1; } /////////////////////////////////////////// Output: warn.c: In function ‘main’: warn.c:12:9: warning: missing initializer for field ‘b’ of ‘struct <anonymous>’ [-Wmissing-field-initializers] .b = 2, ^ warn.c:5:14: note: ‘b’ declared here char b; ^ It gets even worse when adding more fields. For fun, add "char c;" between "char a;" and "char b;". The first warning mentions "c", but the line thereafter points to "b": warn.c: In function ‘main’: warn.c:13:9: warning: missing initializer for field ‘c’ of ‘struct <anonymous>’ [-Wmissing-field-initializers] .b = 2, ^ warn.c:5:14: note: ‘c’ declared here char c; ^ Expected result: no warnings for the first case. This is gcc-multilib 4.8.2-8 on Arch Linux x86_64. COLLECT_GCC=gcc COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-unknown-linux-gnu/4.8.2/lto-wrapper Target: x86_64-unknown-linux-gnu Configured with: /build/gcc-multilib/src/gcc-4.8-20140206/configure --prefix=/usr --libdir=/usr/lib --libexecdir=/usr/lib --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=https://bugs.archlinux.org/ --enable-languages=c,c++,ada,fortran,go,lto,objc,obj-c++ --enable-shared --enable-threads=posix --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-clocale=gnu --disable-libstdcxx-pch --disable-libssp --enable-gnu-unique-object --enable-linker-build-id --enable-cloog-backend=isl --disable-cloog-version-check --enable-lto --enable-plugin --enable-install-libiberty --with-linker-hash-style=gnu --enable-multilib --disable-werror --enable-checking=release Thread model: posix gcc version 4.8.2 20140206 (prerelease) (GCC)
Confirmed. .b = X is designated initializer and -Wmissing-field-initializers shouldn't warn for them.
It looks like this isn't about whether the struct is anonymous, we warn even on say: struct A { int a, b; }; struct B { struct A a; } b = { .a.a = 1, .a.b = 1 }; c.c:2:19: warning: missing initializer for field ‘b’ of ‘struct A’ [-Wmissing-field-initializers] struct B { struct A a; } b = { .a.a = 1, .a.b = 1 }; ^ c.c:1:19: note: ‘b’ declared here struct A { int a, b; }; ^
This regtested/bootstrapped patch fixes it, but I'm not fully confident it's the Right Place. The problem is that constructor_designated wasn't set properly when entering pop_init_level from c_parser_braced_init, since push_init_level called earlier set it to 0. diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c index 65aad45..9813698 100644 --- a/gcc/c/c-typeck.c +++ b/gcc/c/c-typeck.c @@ -7750,6 +7750,7 @@ set_init_label (tree fieldname, struct obstack * braced_init_obstack) do { constructor_fields = TREE_VALUE (field); + constructor_designated = 1; designator_depth++; designator_erroneous = 0; if (constructor_range_stack)
Potential fix: http://gcc.gnu.org/ml/gcc-patches/2014-04/msg00623.html
Author: mpolacek Date: Fri May 2 05:40:38 2014 New Revision: 209998 URL: http://gcc.gnu.org/viewcvs?rev=209998&root=gcc&view=rev Log: PR c/60784 * c-typeck.c (push_init_level): Set constructor_designated to p->designated for structures. * gcc.dg/pr60784.c: New test. Added: trunk/gcc/testsuite/gcc.dg/pr60784.c Modified: trunk/gcc/c/ChangeLog trunk/gcc/c/c-typeck.c trunk/gcc/testsuite/ChangeLog
Should be fixed now.
This bug is still present in GCC 4.9.2 and 4.9.3 (prerelease 20141210). Now building gcc-5-20141207 to verify. (Not sure whether this gets backported to 4.9.x, just checking.) ////////////////////////////////////////// gcc -Wextra bug.c -o /dev/null ////////////////////////////////////////// typedef struct HidppMessage { struct { int feature_index; int func; }; } HidppMessage; int main(void) { HidppMessage req = { .feature_index = 0xFF, .func = 1 }; return req.func; } ////////////////////////////////////////// Strange enough, replacing 0xFF by 0x00 hides the warning.
GCC 5 is OK, the question is whether 4.9 will or will not receive a fix?
There still appears to be a problem here, even with GCC 6.2.1 (gcc-6 (SUSE Linux) 6.2.1 20160826 on x86_64): ////////////////////////////////////////// gcc -Wextra warn.c -o /dev/null ////////////////////////////////////////// struct foo { char x; struct { char a; char b; }; }; int main(void) { struct foo test[1] = { [0].x = 1, [0].a = 2, [0].b = 3, }; return test[0].a == 2; } /////////////////////////////////////////// Output: warn.c: In function ‘main’: warn.c:12:9: warning: missing initializer for field ‘({anonymous})’ of ‘struct foo’ [-Wmissing-field-initializers] [0].a = 2, ^ warn.c:6:5: note: ‘({anonymous})’ declared here }; Interestingly, changing "[0].x = 1" to "[0].x = 0" makes the warning disappear.