This patch addresses PR 53119 (-Wmissing-braces wrongly warns about universal zero initializer {0}). As a result, initializations in C of the form struct foo a = { 0 }; will not trigger warnings from -Wmissing-braces or -Wmissing-field-initializers.
The detection for constructor_zeroinit has been changed. Instead of examining constructor_elements, which gives false negatives, each element is now examined as it is processed. The warning for missing braces is then moved to pop_init_level, where it can benefit from constructor_zeroinit. Bootstrapped and regtested on x86_64 linux, with added test case. If this is approved, could someone commit it for me, as I do not have access? S. Gilles 2014-06-01 S. Gilles <sgil...@umd.edu> gcc/ChangeLog: PR c/53119 c/ * c-typeck.c (push_init_level, process_init_element, pop_init_level): Correct check for zero initialization, move missing brace warning to respect zero initialization. * gcc.dg/pr53119.c: New testcase. Index: gcc/c/c-typeck.c =================================================================== --- gcc/c/c-typeck.c (revision 211081) +++ gcc/c/c-typeck.c (working copy) @@ -74,9 +74,9 @@ if expr.original_code == SIZEOF_EXPR. */ tree c_last_sizeof_arg; -/* Nonzero if we've already printed a "missing braces around initializer" - message within this initializer. */ -static int missing_braces_mentioned; +/* Nonzero if we might need to print a "missing braces around + initializer" message within this initializer. */ +static int found_missing_braces; static int require_constant_value; static int require_constant_elements; @@ -6858,6 +6858,9 @@ /* 1 if this constructor is erroneous so far. */ static int constructor_erroneous; +/* 1 if this constructor is the universal zero initializer { 0 } */ +static int constructor_zeroinit; + /* Structure for managing pending initializer elements, organized as an AVL tree. */ @@ -7019,7 +7022,7 @@ constructor_stack = 0; constructor_range_stack = 0; - missing_braces_mentioned = 0; + found_missing_braces = 0; spelling_base = 0; spelling_size = 0; @@ -7114,6 +7117,7 @@ constructor_type = type; constructor_incremental = 1; constructor_designated = 0; + constructor_zeroinit = 1; designator_depth = 0; designator_erroneous = 0; @@ -7317,12 +7321,8 @@ set_nonincremental_init (braced_init_obstack); } - if (implicit == 1 && warn_missing_braces && !missing_braces_mentioned) - { - missing_braces_mentioned = 1; - warning_init (input_location, OPT_Wmissing_braces, - "missing braces around initializer"); - } + if (implicit == 1) + found_missing_braces = 1; if (TREE_CODE (constructor_type) == RECORD_TYPE || TREE_CODE (constructor_type) == UNION_TYPE) @@ -7455,6 +7455,14 @@ } } + /* Warn when some structs are initialized with direct aggregation. */ + if (!implicit && found_missing_braces && warn_missing_braces + && !constructor_zeroinit) + { + warning_init (input_location, OPT_Wmissing_braces, + "missing braces around initializer"); + } + /* Warn when some struct elements are implicitly initialized to zero. */ if (warn_missing_field_initializers && constructor_type @@ -7461,10 +7469,6 @@ && TREE_CODE (constructor_type) == RECORD_TYPE && constructor_unfilled_fields) { - bool constructor_zeroinit = - (vec_safe_length (constructor_elements) == 1 - && integer_zerop ((*constructor_elements)[0].value)); - /* Do not warn for flexible array members or zero-length arrays. */ while (constructor_unfilled_fields && (!DECL_SIZE (constructor_unfilled_fields) @@ -8594,6 +8598,11 @@ designator_depth = 0; designator_erroneous = 0; + if (!implicit && value.value && !integer_zerop (value.value)) + { + constructor_zeroinit = 0; + } + /* Handle superfluous braces around string cst as in char x[] = {"foo"}; */ if (string_flag Index: gcc/testsuite/gcc.dg/pr53119.c =================================================================== --- gcc/testsuite/gcc.dg/pr53119.c (revision 0) +++ gcc/testsuite/gcc.dg/pr53119.c (working copy) @@ -0,0 +1,29 @@ + +/* { dg-do compile } */ + +/* { dg-options "-Wmissing-braces -Wmissing-field-initializers" } */ + +struct a { + int x; + int y; +}; + +struct b { + struct a w; + struct a z; +}; + +int main (void) +{ + struct a az = { 0 }; + struct a anz = { 1 }; /* { dg-warning "missing initializer for" } */ + + struct b bz = { 0 }; + struct b bnz = { 1, 2, 3, 4 }; /* { dg-warning "missing braces" } */ + + struct b extra = { 0, 0 }; + + return 0; +} + +/* { dg-excess-errors "note" } */