web-dev-qa-db-fra.com

Est-il sage d'ignorer l'avertissement "-Wmissing-braces" de gcc / clang?

Considérez le programme suivant:

#include <array>

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

La première initialisation entraîne des avertissements sur gcc 4.7.2 ...

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

... et le bruit 3.1

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

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

Il existe deux façons de gérer l'avertissement:

  1. Il suffit de l'éteindre
  2. Corrige le code, donc le compilateur est content

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

47
Philipp Claßen

-Wmissing-braces ne sera plus activé dans le GCC -Wall (pour le mode C++), à partir de la version 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 du code tel que

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

Cependant, à mon humble avis, cela est déjà suffisamment bien géré par -Wmissing-field-initializers, qui ne vous avertit pas de votre code d'origine.

46
user743382

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

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

où initializer-list est une liste séparée par des virgules de jusqu'à N éléments dont les types sont convertibles en T

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

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

Lorsque nous regardons la sous-section 1 de 14882: 2011 8.5 [dcl.init], nous voyons qu'une "liste d'initialisation" peut éventuellement contenir une "clause d'initialisation", qui elle-même peut être une "liste d'initiation contreventée". Donc, dans les deux cas, cela devrait être correct. Bien que basé sur la spécification, je pense personnellement que les accolades simples ne devraient pas produire un avertissement du compilateur pour une liste d'initialisation std :: array, et les accolades doubles sont excessives.

8

Clang 6.0 supprime l'avertissement concernant les accolades manquantes. Le journal svn indique:

Supprimez l'avertissement -Wmissing-braces lors de l'initialisation d'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 de fonctionner par la norme, est complètement idiomatique, et l'alternative "suggérée" de Clang n'était pas valide techniquement.

Je voudrais donc omettre les accolades et désactiver -Wmissing-braces pour Clang antérieur à 6.0 s'il doit être pris en charge.

4
proski

Lorsque vous ignorez l'avertissement Clang avec -Wno-missing-braces, Je recommanderais d'activer -Wmissing-field-initializers (Ou utiliser -Wextra, qui l'inclut également). Sinon, vous manquez un avertissement utile comme dans cet exemple:

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

À titre de 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 désactiver l'avertissement sans perdre d'autres avertissements utiles
  • GCC ne se plaint pas dans l'original std::array<int, 1> x = { 0 }; exemple, il n'est donc pas nécessaire de désactiver les avertissements. Cependant, je recommanderais d'activer -Wmissing-field-initializers (Ou utiliser -Wextra), car il n'est pas activé par -Wall.
3
Philipp Claßen