c: -Wmissing-field-initializers and designated inits [PR82283, PR84685]
authorMarek Polacek <polacek@redhat.com>
Tue, 22 Mar 2022 18:37:02 +0000 (14:37 -0400)
committerMarek Polacek <polacek@redhat.com>
Tue, 22 Mar 2022 20:40:40 +0000 (16:40 -0400)
commit4b7d9f8f51bd96d290aac230c71e501fcb6b21a6
tree26583f7173616f5b0545172c3b209370f989c4de
parent774ab2edcb5f3a24ed3a5cffd1143bd49a69f1ee
c: -Wmissing-field-initializers and designated inits [PR82283, PR84685]

This patch fixes two kinds of wrong -Wmissing-field-initializers
warnings.  Our docs say that this warning "does not warn about designated
initializers", but we give a warning for

1) the array case:

  struct S {
    struct N {
      int a;
      int b;
    } c[1];
  } d = {
    .c[0].a = 1,
    .c[0].b = 1, // missing initializer for field 'b' of 'struct N'
  };

we warn because push_init_level, when constructing an array, clears
constructor_designated (which the warning relies on), and we forget
that we were in a designated initializer context.  Fixed by the
push_init_level hunk; and

2) the compound literal case:

  struct T {
    int a;
    int *b;
    int c;
  };

  struct T t = { .b = (int[]){1} }; // missing initializer for field 'c' of 'struct T'

where set_designator properly sets constructor_designated to 1, but the
compound literal causes us to create a whole new initializer_stack in
start_init, which clears constructor_designated.  Then, after we've parsed
the compound literal, finish_init flushes the initializer_stack entry,
but doesn't restore constructor_designated, so we forget we were in
a designated initializer context, which causes the bogus warning.  (The
designated flag is also tracked in constructor_stack, but in this case,
we didn't perform push_init_level between set_designator and start_init
so it wasn't saved anywhere.)

PR c/82283
PR c/84685

gcc/c/ChangeLog:

* c-typeck.cc (struct initializer_stack): Add 'designated' member.
(start_init): Set it.
(finish_init): Restore constructor_designated.
(push_init_level): Set constructor_designated to the value of
constructor_designated in the upper constructor_stack.

gcc/testsuite/ChangeLog:

* gcc.dg/Wmissing-field-initializers-1.c: New test.
* gcc.dg/Wmissing-field-initializers-2.c: New test.
* gcc.dg/Wmissing-field-initializers-3.c: New test.
* gcc.dg/Wmissing-field-initializers-4.c: New test.
* gcc.dg/Wmissing-field-initializers-5.c: New test.
gcc/c/c-typeck.cc
gcc/testsuite/gcc.dg/Wmissing-field-initializers-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/Wmissing-field-initializers-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/Wmissing-field-initializers-3.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/Wmissing-field-initializers-4.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/Wmissing-field-initializers-5.c [new file with mode: 0644]