diff options
author | Marek Polacek <polacek@redhat.com> | 2022-03-22 14:37:02 -0400 |
---|---|---|
committer | Marek Polacek <polacek@redhat.com> | 2022-03-22 16:40:40 -0400 |
commit | 4b7d9f8f51bd96d290aac230c71e501fcb6b21a6 (patch) | |
tree | 26583f7173616f5b0545172c3b209370f989c4de /gcc/c | |
parent | 774ab2edcb5f3a24ed3a5cffd1143bd49a69f1ee (diff) | |
download | gcc-4b7d9f8f51bd96d290aac230c71e501fcb6b21a6.tar.gz |
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.
Diffstat (limited to 'gcc/c')
-rw-r--r-- | gcc/c/c-typeck.cc | 10 |
1 files changed, 6 insertions, 4 deletions
diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc index c0812de84b4..6c4af5e4cde 100644 --- a/gcc/c/c-typeck.cc +++ b/gcc/c/c-typeck.cc @@ -8438,6 +8438,7 @@ struct initializer_stack char top_level; char require_constant_value; char require_constant_elements; + char designated; rich_location *missing_brace_richloc; }; @@ -8464,6 +8465,7 @@ start_init (tree decl, tree asmspec_tree ATTRIBUTE_UNUSED, int top_level, p->top_level = constructor_top_level; p->next = initializer_stack; p->missing_brace_richloc = richloc; + p->designated = constructor_designated; initializer_stack = p; constructor_decl = decl; @@ -8522,6 +8524,7 @@ finish_init (void) require_constant_value = p->require_constant_value; require_constant_elements = p->require_constant_elements; constructor_stack = p->constructor_stack; + constructor_designated = p->designated; constructor_range_stack = p->constructor_range_stack; constructor_elements = p->elements; spelling = p->spelling; @@ -8731,7 +8734,9 @@ push_init_level (location_t loc, int implicit, constructor_depth = SPELLING_DEPTH (); constructor_elements = NULL; constructor_incremental = 1; - constructor_designated = 0; + /* If the upper initializer is designated, then mark this as + designated too to prevent bogus warnings. */ + constructor_designated = p->designated; constructor_pending_elts = 0; if (!implicit) { @@ -8756,9 +8761,6 @@ push_init_level (location_t loc, int implicit, push_member_name (constructor_fields); constructor_depth++; } - /* If upper initializer is designated, then mark this as - designated too to prevent bogus warnings. */ - constructor_designated = p->designated; } else if (TREE_CODE (constructor_type) == ARRAY_TYPE) { |