É sensato ignorar o aviso “-Wmissing-braces” do gcc / clang?

Considere o seguinte programa:

#include  int main() { std::array x = { 0 }; // warning! x = { { 0 } }; // no warning return 0; } 

A primeira boot leva a avisos no gcc 4.7.2 …

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

… e clang

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

No que diz respeito ao padrão, não deve haver diferença entre chaves duplas ou simples, pelo menos neste exemplo.

Existem duas maneiras de lidar com o aviso:

  1. Basta desligá-lo
  2. Corrigir o código, então o compilador está feliz

O que você propõe? IMHO, a expressão dupla encaracolada parece um pouco feia. Por outro lado, o aviso pode detectar problemas reais em exemplos mais complicados. Você conhece um exemplo em que o aviso teria ajudado você?

-Wmissing-braces não serão mais ativadas no GCC ( -Wall (para o modo C ++), a partir de 4.8, exatamente pelo motivo que você descreve. Para as versões atuais do GCC, desativar ou ignorar o aviso, o código que você tem está escrito da maneira que deveria ser.

O aviso provavelmente serve para cobrir códigos como

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

No entanto, IMHO, que já é tratado bem o suficiente por -Wmissing-field-initializers , que não avisa sobre o seu código original.

Eu recebo o mesmo aviso no Xcode 6.1.1 (a versão atual em 9 de março de 2015). Quando eu adiciono as chaves extras em torno de cada subobject, recebo um erro. Quando adiciono um conjunto extra de chaves em toda a lista de boot, o aviso desaparece. De acordo com a especificação padrão 14882: 2011 23.3.2.1 [array.overview] a subseção 2 declara explicitamente

 array a = { initializer-list }; 

onde initializer-list é uma lista separada por vírgulas de até N elementos cujos tipos são conversíveis em T

resultado do código no Xcode 6.1.1 (abaixo)

 array key1 = {1, 2}; // warning: suggest braces around initialization of subobject array key2 = { {1}, {2} }; // error: no viable overload = array key3 = array { {1}, {2} }; // error: excess elements in struct initializer array key4 = { {1, 2} }; // no warning and no error 

Quando olhamos para a subsecção 1 do 14882: 2011 8.5 [dcl.init], vemos que uma ‘lista-inicializadora’ pode, opcionalmente, conter uma cláusula ‘initializer-clause’, que por si só pode ser uma ‘braced-init-list’. Então, qualquer um dos caminhos deve estar correto. Embora baseado na especificação, eu pessoalmente acho que chaves únicas não devem produzir um aviso de compilador para uma lista de boot std :: array, e chaves duplas são exageradas.

Ao ignorar o aviso de Clang com -Wno-missing-braces , recomendo habilitar -Wmissing-field-initializers (ou usar -Wextra , que também inclui). Caso contrário, você perderá um aviso útil como neste exemplo:

 #include  struct A { int i; int arr[2]; int j; }; void print(const A& a) { printf("i=%d, arr={%d,%d}, j=%d\n", ai, a.arr[0], a.arr[1], aj); } 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) 

Para comparação, é isso que o GCC faz:

 $ 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}; ^ 

Em suma:

  • Para o Clang, eu recomendaria -Wno-missing-braces -Wmissing-field-initializers para silenciar o aviso sem perder outros avisos úteis
  • O GCC não reclama no std::array x = { 0 }; Por exemplo, não há necessidade de desativar nenhum aviso. No entanto, eu recomendaria habilitar -Wmissing-field-initializers (ou usar -Wextra ), já que ele não é habilitado por -Wall .

Clang 6.0 suprime o aviso sobre falta de chaves. O svn log diz:

Suprimir -Wearing-chaves de aviso quando agregado de boot de uma estrutura com um único campo que é em si um agregado. Em C ++, tal boot dos tipos std :: array tem a garantia de funcionar pelo padrão, é completamente idiomática, e a alternativa “sugerida” do Clang era tecnicamente inválida.

Então eu -Wmissing-braces as chaves e desabilitaria -Wmissing-braces para o Clang antes da 6.0 se precisar de suporte.