Closes #95379.
gcc/ChangeLog:
* doc/extend.texi: Document { 0 } as a special case for the
designated_init attribute.
gcc/c/ChangeLog:
* c-typeck.c (struct location_list): New type.
(struct initializer_stack): Add positional_init_locs for
-Wdesignated-init warnings.
(start_init): Initialize initializer_stack->positional_init_locs
to NULL.
(finish_init): Free initializer_stack->positional_init_locs.
(pop_init_level): Move -Wdesignated-init warning here from
process_init_element so that we can treat { 0 } specially.
(process_init_element): Instead of warning on -Wdesignated-init
here, remember a list of locations where we should warn and do the
actual warning in pop_init_level.
gcc/testsuite/ChangeLog:
* gcc.dg/Wdesignated-init.c: Add tests for ignoring { 0 }.
---
Note: Please see the discussion here[1] before applying this
patch. Also note that this patch does not implement a
-Wno-designated-init flag, but that shouldn't be too hard to
implement.
[1] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95379
gcc/ChangeLog | 5 +++
gcc/c/ChangeLog | 14 +++++++
gcc/c/c-typeck.c | 55 +++++++++++++++++++++++--
gcc/doc/extend.texi | 4 ++
gcc/testsuite/ChangeLog | 4 ++
gcc/testsuite/gcc.dg/Wdesignated-init.c | 3 ++
6 files changed, 81 insertions(+), 4 deletions(-)
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 3fc8a8e55cc..0249f965c4f 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,8 @@
+2020-06-03 Asher Gordon <[email protected]>
+
+ * doc/extend.texi: Document { 0 } as a special case for the
+ designated_init attribute.
+
2020-06-02 Felix Yang <[email protected]>
PR target/95459
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
index 7efb6bfc544..0a6cf36bad7 100644
--- a/gcc/c/ChangeLog
+++ b/gcc/c/ChangeLog
@@ -1,3 +1,17 @@
+2020-06-03 Asher Gordon <[email protected]>
+
+ * c-typeck.c (struct location_list): New type.
+ (struct initializer_stack): Add positional_init_locs for
+ -Wdesignated-init warnings.
+ (start_init): Initialize initializer_stack->positional_init_locs
+ to NULL.
+ (finish_init): Free initializer_stack->positional_init_locs.
+ (pop_init_level): Move -Wdesignated-init warning here from
+ process_init_element so that we can treat { 0 } specially.
+ (process_init_element): Instead of warning on -Wdesignated-init
+ here, remember a list of locations where we should warn and do the
+ actual warning in pop_init_level.
+
2020-05-28 Nicolas Bértolo <[email protected]>
* Make-lang.in: Remove extra slash.
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index 385bf3a1c7b..6273a7ce2d7 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -8179,6 +8179,13 @@ struct constructor_range_stack
static struct constructor_range_stack *constructor_range_stack;
+/* A list of locations. */
+
+struct location_list {
+ struct location_list *next;
+ location_t loc;
+};
+
/* This stack records separate initializers that are nested.
Nested initializers can't happen in ANSI C, but GNU C allows them
in cases like { ... (struct foo) { ... } ... }. */
@@ -8197,6 +8204,7 @@ struct initializer_stack
char require_constant_value;
char require_constant_elements;
rich_location *missing_brace_richloc;
+ struct location_list *positional_init_locs;
};
static struct initializer_stack *initializer_stack;
@@ -8222,6 +8230,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->positional_init_locs = NULL;
initializer_stack = p;
constructor_decl = decl;
@@ -8287,6 +8296,13 @@ finish_init (void)
spelling_size = p->spelling_size;
constructor_top_level = p->top_level;
initializer_stack = p->next;
+
+ while (p->positional_init_locs)
+ {
+ struct location_list *list = p->positional_init_locs;
+ p->positional_init_locs = list->next;
+ free (list);
+ }
free (p);
}
@@ -8744,6 +8760,22 @@ pop_init_level (location_t loc, int implicit,
}
}
+ /* Warn when positional initializers are used for a structure with
+ the designated_init attribute, but make an exception for { 0 }. */
+ while (initializer_stack->positional_init_locs)
+ {
+ struct location_list *loc = initializer_stack->positional_init_locs;
+
+ if (!constructor_zeroinit)
+ warning_init (loc->loc,
+ OPT_Wdesignated_init,
+ "positional initialization of field in %<struct%> "
+ "declared with %<designated_init%> attribute");
+
+ initializer_stack->positional_init_locs = loc->next;
+ free(loc);
+ }
+
/* Pad out the end of the structure. */
if (p->replacement_value.value)
/* If this closes a superfluous brace pair,
@@ -9975,10 +10007,25 @@ process_init_element (location_t loc, struct c_expr
value, bool implicit,
&& TREE_CODE (constructor_type) == RECORD_TYPE
&& lookup_attribute ("designated_init",
TYPE_ATTRIBUTES (constructor_type)))
- warning_init (loc,
- OPT_Wdesignated_init,
- "positional initialization of field "
- "in %<struct%> declared with %<designated_init%> attribute");
+ {
+ struct location_list *new_loc;
+
+ /* Remember where we got a positional initializer so we can warn
+ if it initializes a field of a structure with the
+ designated_init attribute. */
+ new_loc = XNEW (struct location_list);
+ new_loc->next = NULL;
+ new_loc->loc = loc;
+ if (initializer_stack->positional_init_locs)
+ {
+ struct location_list *last = initializer_stack->positional_init_locs;
+ while (last->next)
+ last++;
+ last->next = new_loc;
+ }
+ else
+ initializer_stack->positional_init_locs = new_loc;
+ }
/* If we've exhausted any levels that didn't have braces,
pop them now. */
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index cced19d2018..a3c5059a8b0 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -8093,6 +8093,10 @@ attribute is to allow the programmer to indicate that a
structure's
layout may change, and that therefore relying on positional
initialization will result in future breakage.
+Note that the universal zero initializer, @code{@{ 0 @}}, is considered
+a special case and will not produce a warning when used to initialize a
+structure with the @code{designated_init} attribute.
+
GCC emits warnings based on this attribute by default; use
@option{-Wno-designated-init} to suppress them.
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 23f21cc8f4d..9c39195ba21 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2020-06-03 Asher Gordon <[email protected]>
+
+ * gcc.dg/Wdesignated-init.c: Add tests for ignoring { 0 }.
+
2020-06-02 David Malcolm <[email protected]>
PR jit/95426
diff --git a/gcc/testsuite/gcc.dg/Wdesignated-init.c
b/gcc/testsuite/gcc.dg/Wdesignated-init.c
index b9ca572206c..adb7949df55 100644
--- a/gcc/testsuite/gcc.dg/Wdesignated-init.c
+++ b/gcc/testsuite/gcc.dg/Wdesignated-init.c
@@ -24,6 +24,9 @@ struct Des {
struct Des d1 = { 5, 5 }; /* { dg-warning "(positional|near initialization)" }
*/
struct Des d2 = { .x = 5, .y = 5 };
struct Des d3 = { .x = 5, 5 }; /* { dg-warning "(positional|near
initialization)" } */
+struct Des d4 = { 0 };
+struct Des d5 = { 5 }; /* { dg-warning "(positional|near initialization)" } */
+struct Des d6 = { 0, 0 }; /* { dg-warning "(positional|near initialization)" }
*/
struct Des fd1 (void)
{
--
2.26.2