Is it wise to ignore gcc/clang's "-Wmissing-braces" warning?
Asked Answered
P

4

56

Consider the following program:

#include <array>

int main()
{
  std::array<int, 1> x = { 0 }; // warning!
  x = { { 0 } }; // no warning
  return 0;
}

The first initialization leads to warnings on gcc 4.7.2...

main.cpp:5:22: warning: unused variable ‘x’ [-Wunused-variable]

... and clang 3.1

main.cpp:5:28: warning: suggest braces around initialization of subobject [-Wmissing-braces]
  std::array<int, 1> x = { 0 };

As far as the standard goes, there should be no difference between double or single curly braces, at least in this example.

There are two ways to deal with the warning:

  1. Just turn it off
  2. Fix the code, so the compiler is happy

What do you propose? IMHO, the double curly expression looks somewhat ugly. On the other hand, the warning might detect real problems in more complicated examples. Do you know an example where the warning would have helped you?

Pointsman answered 16/12, 2012 at 20:31 Comment(2)
Because std::array is an aggregate. See this [thread][1]. [1]: #16341618Atheist
Just to inform: for disabling this warning, one should add -Wno-missing-braces on clangUndertrump
R
53

-Wmissing-braces will no longer be enabled in GCC's -Wall (for C++ mode), as of 4.8, for precisely the reason you describe. For current versions of GCC, either disable or ignore the warning, the code you have is written the way it should be.

The warning is probably meant to cover code such as

struct A { int a; int b; };
struct B { A a; int b; };
B b = {
  1,
  2 // initialises b.a.b, not b.b
};

However, IMHO, that is already handled well enough by -Wmissing-field-initializers, which does not warn about your original code.

Rahn answered 16/12, 2012 at 20:59 Comment(5)
The warning used to cover at least the C case where people wrote int x[2][2] = {0} when they should have written {{0}}.Godfearing
@jørgensen Why should they? In C, {0} is the initializer that works for all types, and is used more than strictly necessary because of that. It's perfectly valid, it's obvious what it means, so why should is cause a warning?Rahn
Clang still warns about this issue, but has a similar bug open, see llvm.org/bugs/show_bug.cgi?id=21629Mingy
Can you clarify your comment 'initialises b.a.b, not b.b'. I mean, the statement B b = {1, 2} initializes b.a.a to 1, b.a.b to 2 and b.b to 0. The initialization of b.b is due to C11, 6.7.9 (21) (i.e. '[..], the remainder of the aggregate shall be initialized implicitly the same as objects that have static storage duration.'). Thus, in that example, everything is initialized.Caylor
@Caylor I meant for the comment to apply to the 2. Is it clearer like this?Rahn
N
8

I get the same warning in Xcode 6.1.1 (the current version as of March 9, 2015). When I add the extra braces around each subobject I get an error. When I add an extra set of braces around the entire initialization list then the warning goes away. According to the standard specification 14882:2011 23.3.2.1 [array.overview] subsection 2 explicitly states

array<T, N> a = { initializer-list };

where initializer-list is a comma-separated list of up to N elements whose types are convertible to T

result of code in Xcode 6.1.1 (below)

array<int, 2> key1 = {1, 2}; // warning: suggest braces around initialization of subobject

array<int, 2> key2 = { {1}, {2} }; // error: no viable overload =

array<int, 2> key3 = array<int, 2> { {1}, {2} }; // error: excess elements in struct initializer

array<int, 2> key4 = { {1, 2} }; // no warning and no error

When we look at 14882:2011 8.5 [dcl.init] subsection 1 we see that an 'initializer-list' can optionally contain an 'initializer-clause', which itself can be a 'braced-init-list'. So either way should be correct. Though based on the spec I personally think single braces shouldn't output a compiler warning for a std::array initializer-list, and double braces is overkill.

Nata answered 9/3, 2015 at 7:5 Comment(0)
P
5

Clang 6.0 suppresses the warning about missing braces. The svn log says:

Suppress -Wmissing-braces warning when aggregate-initializing a struct with a single field that is itself an aggregate. In C++, such initialization of std::array types is guaranteed to work by the standard, is completely idiomatic, and the "suggested" alternative from Clang was technically invalid.

So I would omit the braces and disable -Wmissing-braces for Clang prior to 6.0 if it needs to be supported.

Pegasus answered 24/1, 2018 at 2:18 Comment(1)
That is good to hear. For reference, here is the source of the statement: reviews.llvm.org/rL314838Moor
P
3

When ignoring the Clang warning with -Wno-missing-braces, I would recommend to enable -Wmissing-field-initializers (or use -Wextra, which also includes it). Otherwise, you miss a useful warning like in this example:

#include <cstdio>

struct A
{
  int i;
  int arr[2];
  int j;
};

void print(const A& a)
{
  printf("i=%d, arr={%d,%d}, j=%d\n", a.i, a.arr[0], a.arr[1], a.j);
}

int main() {
  A a = {1, 2, 3}; // this is the critical line
  print(a); // output: i=1, arr={2,3}, j=0

  A b = {1, {2}, 3};
  print(b); // output: i=1, arr={2,0}, j=3

  A c = {1, {2,0}, 3};
  print(c); // output: i=1, arr={2,0}, j=3

  return 0;
}
$ clang++ -Wall example.cpp
example.cpp:16:13: warning: suggest braces around initialization of
      subobject [-Wmissing-braces]
  A a = {1, 2, 3};
            ^~~~
            {   }
1 warning generated.

$ clang++ -Wall -Wno-missing-braces example.cpp
(no warnings)

$ clang++ -Wall -Wno-missing-braces -Wmissing-field-initializers example.cpp
example.cpp:16:17: warning: missing field 'j' initializer
      [-Wmissing-field-initializers]
  A a = {1, 2, 3};
                ^
1 warning generated.

$ clang++ --version
clang version 3.8.1 (tags/RELEASE_381/final)

For comparison, this is what GCC does:

$ g++ -Wall -Wextra example.cpp
(no warning)

$ g++ -Wall -Wmissing-field-initializers example.cpp
example.cpp: In function ‘int main()’
example.cpp:16:17: warning: missing initializer for member ‘A::j’ [-Wmissing-field-initializers]
   A a = {1, 2, 3};
                 ^

In summary:

  • For Clang, I would recommend -Wno-missing-braces -Wmissing-field-initializers to silence the warning without loosing other useful warnings
  • GCC does not complain in the original std::array<int, 1> x = { 0 }; example, so there is no need to disable any warnings. However, I would recommend to enable -Wmissing-field-initializers (or use -Wextra), as it is not enabled by -Wall.
Pointsman answered 29/8, 2016 at 15:26 Comment(2)
Can you use -Wno-missing-braces with -Wall ? I.e. "all except no-missing-braces"?Flawy
@DavidDoria Yes you canManolo

© 2022 - 2024 — McMap. All rights reserved.