Bug 53119 - -Wmissing-braces wrongly warns about universal zero initializer {0}
Summary: -Wmissing-braces wrongly warns about universal zero initializer {0}
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c (show other bugs)
Version: unknown
: P3 enhancement
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2012-04-25 17:04 UTC by Rich Felker
Modified: 2015-03-16 04:32 UTC (History)
10 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2012-05-03 00:00:00


Attachments
minimal test case (66 bytes, text/plain)
2012-04-25 18:32 UTC, Rich Felker
Details
backported fix for gcc 4.7.4 (1.38 KB, application/x-download)
2014-08-03 17:39 UTC, Rose Garcia
Details
backported fix for gcc 4.8.3 (1.37 KB, application/x-download)
2014-08-03 19:33 UTC, Rose Garcia
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Rich Felker 2012-04-25 17:04:23 UTC
In C, {0} is the universal zero initializer equivalent to C++'s {} (the latter being invalid in C). It is necessary to use whenever you want a zero-initialized object of a complete but conceptually-opaque or implementation-defined type. The classic example in the C standard library is mbstate_t:

mbstate_t state = { 0 }; /* correctly zero-initialized */

versus the common but nonportable:

mbstate_t state;
memset(&state, 0, sizeof state);

In this case, gcc -Wbraces (which is included in -Wall) actively discourages the programmer from writing the correct form of the code by throwing ugly warnings.

Note that if you want to eliminate warnings and write portable code, the *only* way to zero-initialize an object like this is:

static const mbstate_t zero_state;
mbstate_t state = zero_state;

(i.e. creating an extra object of static storage duration to be implicitly zero initialized).

The same reasoning applies to any structures provided by third-party libraries which must be allocated by the calling application and zero-initialized, but whose definitions are intended to be considered as opaque.

To fix the issue, GCC should simply special-case {0} as always-valid and suppress warnings for it, while leaving in effect all other behaviors of -Wbraces.
Comment 1 Manuel López-Ibáñez 2012-04-25 17:53:25 UTC
Where did you get your compiler?

-Wbraces is not a valid option in the original GCC.

http://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html#Warning-Options
Comment 2 Rich Felker 2012-04-25 18:01:41 UTC
Sorry, I wrote the bug report without GCC in front of me. The correct name for the warning option is -Wmissing-braces.
Comment 3 Manuel López-Ibáñez 2012-04-25 18:12:29 UTC
I can't get reproduce this.

Could you provide a small reproducible testcase?
Plus the info asked here: http://gcc.gnu.org/bugs/#need
Comment 4 Rich Felker 2012-04-25 18:32:08 UTC
Created attachment 27242 [details]
minimal test case

Glibc's mbstate_t is defined as a struct whose first element is an int (not another struct/union/array), so the warning does not happen there. I'm uploading a minimal example case with an explicitly defined struct.
Comment 5 Manuel López-Ibáñez 2012-04-25 22:13:11 UTC
It seems to me you are right. However, I cannot see how to check for ={0} at the point of the warning.

Joseph, any ideas? This part of the C FE is ancient.
Comment 6 joseph@codesourcery.com 2012-04-26 10:37:26 UTC
On Wed, 25 Apr 2012, manu at gcc dot gnu.org wrote:

> It seems to me you are right. However, I cannot see how to check for ={0} at
> the point of the warning.
> 
> Joseph, any ideas? This part of the C FE is ancient.

In general I think Jakub is more expert on the code for handling 
initializers than I am.
Comment 7 Manuel López-Ibáñez 2012-04-26 10:46:11 UTC
(In reply to comment #6)
> On Wed, 25 Apr 2012, manu at gcc dot gnu.org wrote:
> 
> > It seems to me you are right. However, I cannot see how to check for ={0} at
> > the point of the warning.
> > 
> > Joseph, any ideas? This part of the C FE is ancient.
> 
> In general I think Jakub is more expert on the code for handling 
> initializers than I am.

OK, but do you agree that the warning should be silenced always for ={0}?

Jakub, do you have any pointers for this? At the point of the warning "value" is null, so I am not sure how to check for ={0}. There is a boolean zeroinit later, 

        bool constructor_zeroinit =
         (VEC_length (constructor_elt, constructor_elements) == 1
          && integer_zerop
              (VEC_index (constructor_elt, constructor_elements, 0)->value));

but this vector is not initialized in this case.
Comment 8 joseph@codesourcery.com 2012-04-26 10:50:38 UTC
On Thu, 26 Apr 2012, manu at gcc dot gnu.org wrote:

> OK, but do you agree that the warning should be silenced always for ={0}?

Yes, I think that makes sense.
Comment 9 Manuel López-Ibáñez 2012-05-03 17:54:37 UTC
Maybe related PR25137 

Confirmed by Joseph. Any help welcome!
Comment 10 JamesH 2013-08-14 11:36:08 UTC
I'd like to add that this is a definite problem when moving a codebase from a different compiler to gcc. I'm having to individually fix up ={0} cases to match the content of the structure being initialised, which is a PITA, and I think against the C standard which I believe allows ={0} as a default zero initialiser for structs of whatever content.

Therefore, is there any progress on this bug?
Comment 11 Manuel López-Ibáñez 2013-09-07 18:15:20 UTC
(In reply to JamesH from comment #10)
> 
> Therefore, is there any progress on this bug?

I wouldn't expect any soon, unless new developers join GCC development and decide to work on the C FE. Any takers?
Comment 12 Jeffrey A. Law 2014-06-05 19:36:34 UTC
Author: law
Date: Thu Jun  5 19:36:03 2014
New Revision: 211289

URL: http://gcc.gnu.org/viewcvs?rev=211289&root=gcc&view=rev
Log:
2014-06-05  S. Gilles  <sgilles@terpmail.umd.edu>

	PR c/53119
	* 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.

	PR c/53119
	* gcc.dg/pr53119.c: New testcase.

Added:
    trunk/gcc/testsuite/gcc.dg/pr53119.c
Modified:
    trunk/gcc/c/ChangeLog
    trunk/gcc/c/c-typeck.c
    trunk/gcc/testsuite/ChangeLog
Comment 13 nightstrike 2014-06-06 00:50:25 UTC
This is related to https://gcc.gnu.org/bugzilla/show_bug.cgi?id=36750

Can someone update the see also field?

Also, can this change be applied to c++ as well? Initializing a c struct in c++ code exhibits the same behavior.
Comment 14 Rich Felker 2014-06-06 00:57:03 UTC
In C++, the correct zero initializer is {}, not {0}. I'm not an expert in C++ but I think {0} in C++ might even be a constraint violation unless the brace level happens to match.
Comment 15 Marek Polacek 2014-06-06 05:01:03 UTC
Should be fixed.
Comment 16 Rose Garcia 2014-08-03 17:39:47 UTC
Created attachment 33228 [details]
backported fix for gcc 4.7.4

backported fix for gcc 4.7.4 attached. was tested building about 500 packages, no regressions have been detected.
Comment 17 Marek Polacek 2014-08-03 17:58:48 UTC
I'm sorry, GCC 4.7 branch is already closed.
Comment 18 Rose Garcia 2014-08-03 19:33:41 UTC
Created attachment 33229 [details]
backported fix for gcc 4.8.3

oh, is that so? that's unfortunate, as gcc > 4.7 requires a C++ compiler to bootstrap a C compiler.

either way, attaching a backport to gcc 4.8.3.
unlike the previous backport it wasn't heavily tested, but it seemed to do the right thing in some simple testcases; and there was only one minor change needed to get the upstream patch to apply (different argument count for init_warning()).
Comment 19 roger pack 2015-01-21 18:57:29 UTC
Has this been applied yet? (If yes, in which version of gcc?) Seems to be a popular problem, if it's this: 
http://stackoverflow.com/questions/13746033/how-to-repair-warning-missing-braces-around-initializer
Comment 20 Marek Polacek 2015-01-21 19:29:19 UTC
Sorry, the patch hasn't been applied to 4.9 nor 4.8 branch yet, and I don't think it should be backported as-is, because just today I found out that the patch contains a bug; see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64709
Comment 21 Askar Safin 2015-02-07 00:24:34 UTC
Same bug in clang: http://llvm.org/bugs/show_bug.cgi?id=21689
Related bug in POSIX: http://austingroupbugs.net/view.php?id=918

And I think this bug should be fixed even in C++, just because we should have some uniform way to initialize addrinfo and mbstate_t in both C and C++ :)
(And gcc 4.9.2 emits warning for C++ but not for C)
Comment 22 Rich Felker 2015-02-07 00:31:00 UTC
The warning is probably correct for C++ because C++ has "{}" as its universal zero initializer, and "{0}" may not (unsure about this; I'm not a C++ expert) even be valid as an initializer for some C++ types. Comments from others more experienced in C++ would be welcome.
Comment 23 Askar Safin 2015-02-07 01:02:39 UTC
Please remove {0} warning at least in cases where {0} is obviously OK (such as addrinfo)
Comment 24 nightstrike 2015-03-16 04:32:17 UTC
(In reply to Marek Polacek from comment #20)
> Sorry, the patch hasn't been applied to 4.9 nor 4.8 branch yet, and I don't
> think it should be backported as-is, because just today I found out that the
> patch contains a bug; see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64709

Now that PR64709 is fixed, could you please backport both to 4.9 (and possibly 4.8)?