Est-il judicieux d’ignorer l’avertissement «-Wmissing-braces» de gcc / clang?

Considérons le programme suivant:

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

La première initialisation conduit à des avertissements sur gcc 4.7.2 …

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

… et clang 3.1

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

En ce qui concerne la norme, il ne devrait y avoir aucune différence entre les accolades doubles ou simples, du moins dans cet exemple.

Il y a deux manières de gérer l’avertissement:

  1. Juste éteindre
  2. Corrige le code pour que le compilateur soit content

Que proposez vous? À mon humble avis, la double expression bouclée semble un peu moche. D’un autre côté, l’avertissement pourrait détecter des problèmes réels dans des exemples plus complexes. Connaissez-vous un exemple où l’avertissement vous aurait aidé?

-Wmissing-braces ne sera plus activé dans -Wall (pour le mode C ++) de GCC, à partir de 4.8, précisément pour la raison que vous décrivez. Pour les versions actuelles de GCC, désactivez ou ignorez l’avertissement, le code que vous avez est écrit comme il se doit.

L’avertissement est probablement destiné à couvrir un code tel que

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

Cependant, à -Wmissing-field-initializers , cela est déjà assez bien géré par -Wmissing-field-initializers , qui ne prévient pas de votre code d’origine.

Je reçois le même avertissement dans Xcode 6.1.1 (la version actuelle au 9 mars 2015). Lorsque j’ajoute les accolades supplémentaires autour de chaque sous-object, j’obtiens une erreur. Lorsque j’ajoute un ensemble supplémentaire d’accolades autour de la liste d’initialisation complète, l’avertissement disparaît. Selon la spécification standard 14882: 2011 23.3.2.1 [array.overview], la sous-section 2 indique explicitement

 array a = { initializer-list }; 

où initializer-list est une liste séparée par des virgules d’un maximum de N éléments dont les types sont convertibles en T

résultat du code dans Xcode 6.1.1 (ci-dessous)

 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 

Lorsque nous regardons 14882: 2011 8.5 [dcl.init] sous-section 1, nous voyons qu’une “liste d’initialisation” peut éventuellement contenir une “clause d’initialisation”, qui peut elle-même être une “liste d’initiation”. Donc, les deux devraient être corrects. Bien que basé sur la spécification, je pense personnellement que les accolades simples ne devraient pas générer d’avertissement du compilateur pour une liste d’initialisation std :: array, et que les accolades doubles sont excessives.

En ignorant l’avertissement Clang avec -Wno-missing-braces , je recommande d’activer les -Wmissing-field-initializers -Wextra (ou d’utiliser -Wextra , qui l’inclut également). Sinon, vous manquez un avertissement utile comme dans cet exemple:

 #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) 

Pour comparaison, voici ce que fait GCC:

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

En résumé:

  • Pour Clang, je recommanderais -Wno-missing-braces -Wmissing-field-initializers pour faire taire l’avertissement sans perdre d’autres avertissements utiles
  • GCC ne se plaint pas dans le std::array x = { 0 }; Par exemple, il n’est pas nécessaire de désactiver les avertissements. Cependant, je vous recommande d’activer les -Wmissing-field-initializers (ou d’utiliser -Wextra ), car il n’est pas activé par -Wall .

Clang 6.0 supprime l’avertissement concernant les accolades manquantes. Le journal svn dit:

Supprimer l’avertissement -Wmissing-braces lors de l’initialisation par agrégat d’une structure avec un seul champ qui est lui-même un agrégat. En C ++, une telle initialisation des types std :: array est garantie par le standard, elle est complètement idiomatique et l’alternative “suggérée” de Clang était techniquement invalide.

Donc je voudrais omettre les accolades et désactiver -Wmissing-braces pour Clang avant 6.0 si cela doit être supporté.