Bug 60784 - Spurious -Wmissing-field-initializers warning for anonymous structure
Summary: Spurious -Wmissing-field-initializers warning for anonymous structure
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c (show other bugs)
Version: 4.8.2
: P3 normal
Target Milestone: 5.0
Assignee: Marek Polacek
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2014-04-07 22:23 UTC by Peter Wu
Modified: 2016-12-06 15:03 UTC (History)
0 users

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2014-04-08 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Peter Wu 2014-04-07 22:23:36 UTC
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)
Comment 1 Marek Polacek 2014-04-08 06:53:58 UTC
Confirmed.

.b = X is designated initializer and -Wmissing-field-initializers shouldn't warn for them.
Comment 2 Marek Polacek 2014-04-09 20:04:00 UTC
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; };
                   ^
Comment 3 Marek Polacek 2014-04-10 20:43:02 UTC
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)
Comment 4 Marek Polacek 2014-04-13 15:04:05 UTC
Potential fix: http://gcc.gnu.org/ml/gcc-patches/2014-04/msg00623.html
Comment 5 Marek Polacek 2014-05-02 05:41:10 UTC
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
Comment 6 Marek Polacek 2014-05-02 05:42:41 UTC
Should be fixed now.
Comment 7 Peter Wu 2014-12-12 10:30:59 UTC
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.
Comment 8 Peter Wu 2014-12-12 12:28:52 UTC
GCC 5 is OK, the question is whether 4.9 will or will not receive a fix?
Comment 9 Christian Bauer 2016-12-06 15:03:25 UTC
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.