2012-12-16 8 views
41

Si consideri il seguente programma:È prudente ignorare l'avviso "-Smissing-braces" di gcc/clang?

#include <array> 

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

La prima inizializzazione porta ad avvertenze sui gcc 4.7.2 ...

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

... e clang 3,1

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

Per quanto come va lo standard, non ci dovrebbe essere alcuna differenza tra parentesi graffe doppie o singole, almeno in questo esempio.

Ci sono due modi per affrontare con l'avvertimento:

  1. Basta spegnerlo
  2. correggere il codice, in modo che il compilatore è felice

Cosa proponi? IMHO, la doppia espressione riccia sembra un po 'brutta. D'altra parte, l'avviso potrebbe rilevare problemi reali in esempi più complicati. Conoscete un esempio in cui l'avvertimento vi avrebbe aiutato?

+0

Perché std :: array è un aggregato. Vedere questo [thread] [1]. [1]: http://stackoverflow.com/questions/16341118/whats-the-correct-way-to-initialize-a-member-array-with-an-initializer-list –

+0

Solo per informa: per disabilitare questo avviso, si dovrebbe aggiungere -Chiuscole mancanti su clang –

risposta

41

-Wmissing-braces will no longer be enabled in GCC's -Wall (for C++ mode), as of 4.8, for precisely the reason you describe. Per le versioni correnti di GCC, disattivare o ignorare l'avviso, il codice che si è scritto è come dovrebbe essere.

L'avvertimento è probabilmente intesa coprire codice come

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

Tuttavia, secondo me, che è già gestita abbastanza bene da -Wmissing-field-initializers, che non mettere in guardia circa il vostro codice originale.

+1

L'avviso usato per coprire almeno il caso C in cui le persone hanno scritto 'int x [2] [2] = {0}' quando avrebbero dovuto scritto '{{0}}'. –

+7

@ jørgensen Perché dovrebbero? In C, '{0}' è l'inizializzatore che funziona per tutti i tipi e viene usato più del necessario per via di ciò. È perfettamente valido, è ovvio che cosa significa, quindi perché dovrebbe causare un avvertimento? – hvd

+0

Clang continua a segnalare questo problema, ma ha un bug simile aperto, vedi http://llvm.org/bugs/show_bug.cgi?id=21629 – usr1234567

6

Ricevo lo stesso avviso in Xcode 6.1.1 (la versione corrente a partire dal 9 marzo 2015). Quando aggiungo le parentesi graffe extra attorno a ogni suboject ottengo un errore. Quando aggiungo un set extra di parentesi graffe attorno all'intero elenco di inizializzazione, l'avviso scompare. In base alla specifica standard 14882: 2011 23.3.2.1 [array.overview] comma 2 afferma esplicitamente

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

dove inizializzatore-list è un elenco separato da virgole di un massimo di N elementi i cui tipi sono convertibili in T

risultato di codice in Xcode 6.1.1 (in basso)

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 

Quando guardiamo 14882: 2011 8.5 [dcl.init] sottosezione 1 vediamo che un 'initializer-list' può opzionalmente contenere una 'clausola di inizializzazione', che a sua volta può essere una 'parentesi di parentesi'. Quindi in entrambi i casi dovrebbe essere corretto. Sebbene basato sulle specifiche, personalmente ritengo che le singole parentesi non debbano generare un avviso del compilatore per un elenco di inizializzatore di std :: array, e le doppie parentesi è eccessivo.

3

Quando si ignora l'avviso Clang con -Wno-missing-braces, si consiglia di abilitare -Wmissing-field-initializers (o utilizzare -Wextra, che lo include anche).In caso contrario, si perde un avvertimento utile come in questo esempio:

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

Per fare un confronto, questo è ciò che GCC fa:

$ 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 sintesi:

  • Per Clang, Vorrei raccomandare -Wno-missing-braces -Wmissing-field-initializers per tacitare l'avviso senza perdere altri utili avvisi
  • GCC non si lamenta nell'esempio originale std::array<int, 1> x = { 0 };, quindi non è necessario disabilitare alcun avviso. Tuttavia, ti consigliamo di abilitare -Wmissing-field-initializers (o utilizzare -Wextra), poiché non è abilitato da -Wall.
+0

Puoi usare '-Wno-missing-braces' con' -Wall'? Cioè "tutto tranne le bretelle mancanti"? –

+0

@DavidDoria Sì, è possibile – romeric

2

Il clang 6.0 che verrà rilasciato presto sopprimerà l'avviso relativo alle parentesi mancanti. Il registro svn dice:

Sopprimere: avviso di parentesi graffe durante l'aggregazione: inizializzazione di una struttura con un singolo campo che è esso stesso un aggregato. In C++, tale inizializzazione dei tipi di std :: array è garantita per funzionare secondo lo standard, è completamente idiomatica e l'alternativa "suggerita" da Clang era tecnicamente non valida.

Quindi vorrei omettere le parentesi e disabilitare -Wmissing-braces per Clang prima di 6.0.

+1

È bello ascoltare. Per riferimento, ecco la fonte della dichiarazione: https://reviews.llvm.org/rL314838 –

Problemi correlati