Come attivare (letteralmente) TUTTI gli avvisi di GCC?


194

Vorrei abilitare - letteralmente - TUTTI gli avvisi che GCC ha. (Penseresti che sarebbe facile ...)

  • Penseresti che -Wallpotrebbe fare il trucco, ma no! Ancora bisogno -Wextra.

  • Penseresti che -Wextrapotrebbe fare il trucco, ma no! Non tutti gli avvisi elencati qui (ad esempio -Wshadow) sono abilitati da questo. E non ho ancora idea se questo elenco sia completo.

Come faccio a dire a GCC di abilitare (no if's, and's, oppure but's!) Tutti gli avvisi che ha?


27
@Arafangion: non capisco cosa sia "poco chiaro" sulla domanda - sì, vorrei attivare tutti gli avvisi applicabili al mio codice, non importa quanto pedanti. Per quanto riguarda il motivo, è molto semplice: ho trovato alcuni degli avvisi che non sono attivati ​​da -Wall o -Wextra per essere utili, e quindi voglio provare il resto per vedere se posso migliorare il mio codice. E 'così semplice.
user541686

12
@JoachimPileborg: "Che cosa vuoi che il compilatore ti avverta?" Potenziali errori e / o cattivo stile? Voglio dire, se avessi saputo tutti gli avvertimenti esatti, li avrei semplicemente attivati ​​manualmente, senza bisogno di porre la domanda. Se la risposta è davvero "devi cercare il codice sorgente per trovarli tutti", per favore pubblicalo come risposta!
user541686

56
offerte clang 3.1 -Weverything.
Alexandre Hamez,

5
@Arafangion Bene, la domanda è taggata in C ++ quindi ... :)
Qualche programmatore amico,

5
@JoachimPileborg E ora c'è (finalmente) un modo automatizzato per estrarre gli avvisi dalla fonte: github.com/barro/compiler-warnings
Kyle Strand,

Risposte:


129

Non puoi.

Il manuale di GCC 4.4.0 è completo solo per quella versione, ma elenca tutti i possibili avvisi per 4.4.0. Non sono tutti nella pagina a cui ti colleghi, ad esempio alcune opzioni specifiche della lingua sono nelle pagine per le opzioni C ++ o Obj-C. Per trovarli tutto è meglio guardare il Riepilogo opzioni

L'accensione di tutto includerebbe ciò-Wdouble-promotion che è rilevante solo per le CPU con un'unità a virgola mobile a precisione singola a 32 bit che implementa floatnell'hardware, ma emula doublenel software. Fare calcoli come doubleuserebbe l'emulazione del software ed essere più lento. Questo è rilevante per alcune CPU integrate, ma completamente irrilevante per le moderne CPU desktop con supporto hardware per virgola mobile a 64 bit.

Un altro avvertimento che di solito non è utile è -Wtraditionalche mette in guardia su un codice perfettamente ben formato che ha un significato diverso (o non funziona) nelle "string " "concatenation"definizioni di funzioni C, ad esempio o ISO C tradizionali ! Ti interessa davvero la compatibilità con i compilatori di 30 anni? Vuoi davvero un avvertimento per la scrittura int inc(int i) { return i+1; }?

Penso che -Weffc++sia troppo rumoroso per essere utile, si basa sulla prima edizione obsoleta di Effective C ++ e mette in guardia su costrutti che sono perfettamente validi C ++ (e per i quali le linee guida sono cambiate nelle successive edizioni del libro.) Non voglio essere avvertito che non avevo inizializzato un std::stringmembro nel mio costruttore; ha un costruttore predefinito che fa esattamente quello che voglio, perché dovrei scrivere m_str()per chiamarlo? Gli -Weffc++avvertimenti che potrebbero essere utili sono troppo difficili da rilevare con precisione dal compilatore (dando falsi negativi), e quelli che non sono utili, come l'inizializzazione esplicita di tutti i membri, producono solo troppo rumore, dando falsi positivi.

Luc Danton ha fornito un ottimo esempio di avvertimenti inutili -Waggregate-returnche non hanno quasi mai senso per il codice C ++.

cioè non vuoi davvero tutti gli avvertimenti, pensi solo di farlo.

Consulta il manuale, leggi su di essi, decidi quale potresti voler abilitare, provali. Leggere comunque il manuale del compilatore è una buona cosa TM , prendere una scorciatoia e abilitare avvertimenti che non capisci non è una buona idea, soprattutto se si vuole evitare RTFM.

Chiunque accenda tutto, probabilmente lo sta facendo o perché è all'oscuro perché o un capo dai capelli a punta ha detto "nessun avvertimento".

Alcuni avvertimenti sono importanti, altri no. Devi discriminare o rovinare il tuo programma. Si consideri, ad esempio, -Wdouble-promotion. Se stai lavorando su un sistema incorporato, potresti volerlo; se stai lavorando su un sistema desktop probabilmente non lo fai. E tu vuoi -Wtraditional? Ne dubito.

Modifica: vedere anche -Wall-all per abilitare tutti gli avvisi chiusi come WONTFIX.

Modifica 2: in risposta al reclamo di DevSolar sui makefile che necessitano di usare avvisi diversi a seconda della versione del compilatore, se -Wall -Wextranon è adatto, non è difficile usare CFLAG specifici del compilatore e specifici della versione:

compiler_name := $(notdir $(CC))
ifeq ($(compiler_name),gcc)
compiler_version := $(basename $(shell $(CC) -dumpversion))
endif
ifeq ($(compile_name),clang)
compiler_version := $(shell $(CC) --version | awk 'NR==1{print $$3}')
endif
# ...
wflags.gcc.base := -Wall -Wextra
wflags.gcc.4.7 := -Wzero-as-null-pointer-constant
wflags.gcc.4.8 := $(wflags.gcc.4.7)
wflags.clang.base := -Wall -Wextra
wflags.clang.3.2 := -Weverything
CFLAGS += $(wflags.$(compiler_name).base) $(wflags.$(compiler_name).$(compiler_version))

38
"Sfoglia il manuale, leggi su di loro, decidi quale potresti voler abilitare, provali." Il problema qui sono i passaggi che hai lasciato fuori: "Visita nuovamente il manuale per ogni versione del compilatore e adatta il tuo elenco di avvisi perché stanno cambiando. Fai in modo che i tuoi Makefile controllino la versione esatta del compilatore e utilizzino un altro elenco di avvisi per ciascuno di essi ". Abbiamo livelli di ottimizzazione mantenuti dal manutentore; perché non potrebbero essere disturbati a fornire lo stesso servizio per gli avvisi?
DevSolar

17
@JonathanWakely: ho i miei progetti e GCC non è tra questi. Indico una debolezza nel loro prodotto. O lo risolvono o accettano la colpa per non averlo fatto, ma non dipende da me ripararlo per loro, OSS sia dannato.
DevSolar,

14
@JonathanWakely: "Se vuoi qualcosa, chiedilo, non lamentarti ." - Non sono obbligato a partecipare al progetto GCC per criticarlo, soprattutto se il numero 31573 è già stato contrassegnato come WONTFIX. Ciò mette questo argomento dal "chiedi informazioni" al campo da baseball "puttana".
DevSolar,

61
-Weverythingè la soluzione migliore, credo, rispetto alla strategia gcc di non dare tale opzione. Uso quella bandiera con clang perché la mia filosofia è che voglio tutti gli avvisi di default (perché qualcuno ha pensato che fosse abbastanza utile da aggiungere al compilatore), e se non mi piace, spengo quell'avvertimento in modo specifico. Il punto è che non si conoscono gli avvisi che non si attivano, ma si conoscono gli avvisi che non si desidera che si attivino e che possono essere facilmente disattivati.
David Stone,

17
@JonathanWakely Sì, ma sono irrisori. Il modo più semplice per vedere quali avvisi potrebbero essere rilevanti per il tuo codice è vedere quali avvisi sono attivati ​​dal tuo codice; a quel punto puoi vedere un esempio pertinente e reale del codice potenzialmente pericoloso prima di decidere se disabilitare o meno l'avviso. Questo può essere fatto facilmente con l' -Weverythingopzione di Clang , ma è impossibile farlo con GCC.
Kyle Strand,

71

Concordo con le risposte precedenti sul fatto che probabilmente non è utile abilitare letteralmente tutti gli avvisi, tuttavia GCC offre un modo ragionevolmente conveniente per raggiungere questo obiettivo. Il comando

gcc -Q --help=warning

fornisce un elenco di tutte le opzioni di avviso supportate con informazioni sul fatto che siano attive. Questo può comunque essere usato per scoprire quali opzioni sono (non) abilitate da eg -Walle-Wextra

gcc -Wall -Wextra -Q --help=warning

Per abilitare tutti gli avvisi è possibile utilizzare un po 'di regex per estrarre i parametri della riga di comando

gcc -Q --help=warning | sed -e 's/^\s*\(\-\S*\)\s*\[\w*\]/\1 /gp;d' | tr -d '\n'

Per il mio attuale CCG ciò dà:

-Wabi -Wabi-tag -Waddress -Waggregate-return -Waggressive-loop-ottimizzazioni -Waliasing -Walign-commons -Wampersand -Warray-bounds -Warray-temporaries -Wassign-interccept -Wattributes -Wbad-function-cast -Wbool-compare -Wbuiltin-macro-ridefinito -Wc ++ - compat -Wc ++ 0x-compat -Wc ++ 14-compat -Wc-binding-type -Wc90-c99-compat -Wc99-c11-compat -Wcast-align -Wcast-qual -Wchar-subscripts -Wcharacter-truncation -Wchkp -Wclobbered -Wcomment -Wcompare-reals -Wconditionally supported -Wconversion -Wconversion-extra -Wconversion-null -Wcoverage-mismatch -Wcpp -Wctor-dtor-privacy -Wdec-time -dopo-statement -Wdelete-incomplete -Wdelete-non-virtual-dtor -Wdeprecated -Wdeprecated-dichiarazioni -Wdesignated-init -Wdisabled-optimisation -Wdiscarded-array-qualifiers -Wdiscarded-qualifiers -Wdiv-by-zero -Wdouble promotion promotion -Weffc ++ -Wempty-body-Wendif-labels -Wenum-compare -Wextra -Wfloat-equal -Wformat-contiene-nul -Wformat-extra-args -Wformat-nonliteral -Wformat-security -Wformat-signness -Wformat-y2k -Wformat-zero-length -Wfree -nonheap-object -Wfunction-eliminification -Wignored-qualifiers -Wimplicit -Wimplicit-function-statement -Wimplicit-int -Wimplicit-interface -Wimplicit-procedure -Wincompatible-pointer-types -Winherited-variadic-ctor -Winit-self -Winline -Wint-conversione -Wint-to-pointer-cast -Wintrinsic-shadow -Wintrinsics-std -Winvalid-memory-model -Winvalid-offsetof -Winvalid-pch -Wjump-misses-init -Wline-truncation -Wliteral-suffix -Wlogical -non parentesi -Wlogical-op -Wlong-long -Wmain -Wmaybe-uninitialized -Wmemset-transposed-args -Wmissing-braces -Wmissing-dichiarazioni -Wmissing-field-initializers -Wmissing-include-dirs -Wmissing-type-type -Wmissing-prototipi-Wmultichar -Wnarrowing -Wnested-externs -Wnoexcept -Wnon-template-friend -Wnon-virtual-dtor -Wnonnull -Wodr -Wold-style-cast -Wold-style-statement -Wold-style-definition -Wopenmp-simd -Woverflow -Woverlength-stringhe -Woverloaded-virtual -Woverride-init -Wpacked -Wpacked-bitfield-compat -Wpadded -Wparentheses -Wpedantic -Wpmf-conversions -Wpointer-arith -Wpointer-sign -Wpointer-to-int-cast -Wpragmas -Wproperty -assign-default -Protocollo -Wreal-q-costante -Wrealloc-lhs -Wrealloc-lhs-all -Wredundant-decls -Wreorder -Wreturn-local-addr -Wreturn-type -Wselector -Wsequence-point -Wshadow -Wshadow-ivar -Wift-count-negative -Wift-count-overflow -Wsign-compare -Wsign-promo -Wsized-deallocation -Wsizeof-array-argomento -Wsizeof-pointer-memaccess -Wstack-protector -Wstrict-null-sentinel -Wstrict-prototypes -Wstrict selettore-partita-Wsuggest-attributo = const -Wsuggest-attributo = formato -Wsuggest-attributo = noreturn -Wsuggest-attributo = pure -Wsuggest-final-metodi -Wsuggest-final-types -Wsuggest-override -Wsurprising -Wswitch -Wswitch-bool -Wswitch -default -Wswitch-enum -Wsync-nand -Wsynth -Wsystem-headers -Wtabs -Wtarget-life -Wtraditional -Wtraditional-conversion -Wtrampolines -Wtrigraphs -Wtype-limits -Wundeclared-selector -Wundef -Wunderflow -Wunk noto -Wunsafe-loop-optimizations -Wunsuffixed-float-constants -Wunused -Wunused-but-set-parametro -Wunused-but-set-variabile -Wunused-dummy-topic -Wunused-function -Wunused-label -Wunused-local-typedefs -Wunused-macro -Wunused-parametro -Wunused-risultato -Wunused-value -Wunused-variabile -Wuse-without-only -Wuseless-cast -Wvarargs -Wvariadic-macros -Wvector-operation-performance -Wvirtual-move-assegnato-Wvla -Wvolatile-register-var -Wwrite-stringhe -Wzero-as-null-pointer-costante -Wzerotrip -frequire-return-statement

Questo può ora essere usato per chiamare il GCC, cioè

gcc $(gcc -Q --help=warning | sed -e 's/^\s*\(\-\S*\)\s*\[\w*\]/\1 /gp;d' | tr -d '\n')

Si noti tuttavia che ciò comporta avvisi a causa di alcune opzioni di avviso disponibili solo per determinate lingue (ad es C++.). Questi potrebbero essere evitati usando un po 'più di regex per includere solo le opzioni consentite per la lingua corrente o aggiungendo un appropriato -Wno-whateveralla fine della chiamata.


10
Temo che non sia pratico. Gcc mi ha mostrato avvertimenti da std lib.
Valentin Heinitz,

13
@ValentinHeinitz Come ho detto, non penso che sia utile abilitare letteralmente tutti gli avvisi, ma questo è stato ciò che OP ha richiesto. Tuttavia, penso rimuovendo esplicitamente alcuni avvisi problematici già menzionati in altre risposte (ad esempio aggiungendo il rispettivo -Wno-qualunque cosa alla fine della chiamata), questo può essere di utilità pratica.
Haatschii,

6
@ValentinHeinitz Puoi impedire a gcc di emettere avvisi per le intestazioni di sistema / std / di terze parti usando -isysteminvece che -Iper le relative directory.
Kyle Strand,

4
Questa dovrebbe essere la risposta accettata in quanto in realtà e risponde direttamente alla domanda.
TFuto,

16

È semplicemente impossibile programmare con tutti gli avvisi abilitati (a meno che tu non li ignori, ma poi, perché preoccuparsi?). Ad esempio, supponiamo di utilizzare seguente set di bandiere: -Wstrict-prototypes -Wtraditional.

Anche con due avvisi abilitati, il seguente programma si lamenterebbe.

/tmp $ cat main.c 
int main(int argc, char **argv) {
    return 0;
}
/tmp $ gcc -Wstrict-prototypes -Wtraditional main.c 
main.c: In function main’:
main.c:1:5: warning: traditional C rejects ISO C style function definitions [-Wtraditional]
 int main(int argc, char **argv) {
     ^

Potresti pensare "bene, userò prototipi vecchio stile allora". No, questo non funzionerà.

/tmp $ cat main.c 
int main(argc, argv)
    int argc;
    char **argv;
{
    return 0;
}
/tmp $ gcc -Wstrict-prototypes -Wtraditional main.c 
main.c:1:5: warning: function declaration isnt a prototype [-Wstrict-prototypes]
 int main(argc, argv)
     ^

E no, anche non specificare alcun prototipo è sbagliato, poiché anche il compilatore si lamenterà.

/tmp $ cat main.c 
int main() {
    return 0;
}
/tmp $ gcc -Wstrict-prototypes -Wtraditional main.c 
main.c:1:5: warning: function declaration isnt a prototype [-Wstrict-prototypes]
 int main() {
     ^

Se si definiscono funzioni all'interno del programma, non è possibile utilizzare tutti i flag, poiché il compilatore si lamenterà di qualsiasi definizione di funzione immaginabile.

Per C ++ questo è possibile (il -Wtraditionalflag non esiste) e possono essere compilati programmi molto semplici. Per abilitare tutti gli avvisi, utilizzare il seguente elenco di avvisi (probabilmente alcuni avvisi sono duplicati, perché non mi sono preoccupato di filtrare gli avvisi abilitati da -Wall).

-Wabi -Wctor-dtor-privacy -Wnon-virtual-dtor -Wreorder -Weffc++ -Wstrict-null-sentinel -Wno-non-template-friend -Wold-style-cast -Woverloaded-virtual -Wno-pmf-conversions -Wsign-promo -Wextra -Wall -Waddress -Waggregate-return -Warray-bounds -Wno-attributes -Wno-builtin-macro-redefined -Wc++0x-compat -Wcast-align -Wcast-qual -Wchar-subscripts -Wclobbered -Wcomment -Wconversion -Wcoverage-mismatch -Wno-deprecated -Wno-deprecated-declarations -Wdisabled-optimization -Wno-div-by-zero -Wempty-body -Wenum-compare -Wno-endif-labels -Wfatal-errors -Wfloat-equal -Wformat -Wformat=2 -Wno-format-contains-nul -Wno-format-extra-args -Wformat-nonliteral -Wformat-security -Wformat-y2k -Wignored-qualifiers -Winit-self -Winline -Wno-int-to-pointer-cast -Wno-invalid-offsetof -Winvalid-pch -Wunsafe-loop-optimizations -Wlogical-op -Wlong-long -Wmain -Wmissing-braces -Wmissing-field-initializers -Wmissing-format-attribute -Wmissing-include-dirs -Wmissing-noreturn -Wno-mudflap -Wno-multichar -Wnonnull -Wno-overflow -Woverlength-strings -Wpacked -Wpacked-bitfield-compat -Wpadded -Wparentheses -Wpointer-arith -Wredundant-decls -Wreturn-type -Wsequence-point -Wshadow -Wsign-compare -Wsign-conversion -Wstack-protector -Wstrict-aliasing=1 -Wstrict-overflow=5 -Wswitch -Wswitch-default -Wswitch-enum -Wsync-nand -Wsystem-headers -Wtrigraphs -Wtype-limits -Wundef -Wuninitialized -Wunknown-pragmas -Wno-pragmas -Wunreachable-code -Wunused -Wunused-function -Wunused-label -Wunused-parameter -Wunused-value -Wunused-variable -Wvariadic-macros -Wvla -Wvolatile-register-var -Wwrite-strings

13
Non mi sono mai preso la briga di verificarlo fino ad ora, ma in realtà non è impossibile ... provaint main(int, char **); int main(argc, argv) int argc; char **argv; { (void)argc; (void)argv; return 0; }
user541686

2
Anche con questo banale programma posso ancora ottenere "avvertimento: l'utilizzo dello stack è di 16 byte [-Wstack-use =]" ;-)
Marc Glisse,

7

Qualcuno ha creato un set di strumenti per determinare il set completo di avvisi per una determinata versione di GCC o Clang.

Per GCC, la copia dall'elenco completo degli avvisi forniti da questo strumento per la versione del compilatore sembra essere l' unico modo per garantire che tutti gli avvisi siano attivati, poiché (diversamente da Clang) GCC non fornisce -Weverything.

Lo strumento sembra analizzare il c.optfile effettivo nel codice sorgente GCC, quindi i suoi risultati dovrebbero essere definitivi.

Il repository contiene anche file di testo con gli elenchi di avvisi generati per la maggior parte delle versioni di GCC e Clang (attualmente Clang da 3.2 a 3.7 e GCC da 3.4 a 5.3).

https://github.com/barro/compiler-warnings


Questa è la risposta Utilizzare l'elenco "livello superiore" e aggiungere tutti gli argomenti che si trovano al livello superiore (non rientrato / nidificato). github.com/Barro/compiler-warnings/blob/master/gcc/…
Jetski S-type

6

Gcc 4.3+ ora ha -Q --help = avvertimenti, puoi persino specificare --help = avvertimenti, C per stampare solo gli avvertimenti relativi a C.

Ho appena scritto un modulo m4 per trarne vantaggio (supporta anche Clang's -Weverything), vedi wget_manywarnings.m4

Come usarlo è piuttosto semplice, in pratica il modulo attiva ogni flag di avviso. E rimuovi gli avvisi quando necessario - alcuni sono davvero molto dettagliati. Esempio: configure.ac

Se non usi gli autotools, troverai il codice per attivare tutti gli avvisi disabilitati nel modulo m4, che in pratica è la chiamata gcc inviata attraverso awk:

flags="-Wall -Wextra -Wformat=2 "$(gcc -Wall -Wextra -Wformat=2 -Q --help=warning,C|awk '{ if (($2 == "[disabled]" || $2 == "") && $1!~/=/ && $1~/^-W/&& $1!="-Wall") print $1 }'


3

Da questa pagina :

Si noti che alcuni flag di avviso non sono impliciti da -Wall. Alcuni avvertono di costruzioni che gli utenti generalmente non considerano discutibili, ma che a volte potresti voler controllare; altri avvertono di costruzioni che sono necessarie o difficili da evitare in alcuni casi e non esiste un modo semplice per modificare il codice per sopprimere l'avviso. Alcuni sono abilitati da, -Wextrama molti devono essere abilitati singolarmente.

Immagino che la domanda sia quali ? Forse potresti grep quella pagina per tutte le righe che iniziano con -W e ottenere un elenco completo di flag di avviso. Quindi confrontare quelli con gli elenchi in -Walle -Wextra. C'è anche -Wpedantic, anche se ovviamente vuoi essere ancora più pedante =)


"E non ho ancora idea se questa lista sia completa" ... sì, posso certamente accedere a quella pagina, ma la domanda è: è completa?
user541686

1
Non lo so ... Potrebbe essere necessario scorrere il codice sorgente di GCC. Stai cercando di rendere la tua vita di programmatore estremamente difficile, o c'è una buona ragione per cui vuoi vedere tutti i possibili avvertimenti? =)
risaia

2
Mi piacerebbe vedere la diagnosi di GCC del mio codice - lo trovo davvero utile. Ma ovviamente, se avessi già saputo di tutti gli avvertimenti e quali fossero utili (e quali no), allora non ci sarebbe stato nulla da chiedere. Non c'è modo reale per me di dirlo se non li provo (e ad esempio ho trovato utile l'ombreggiatura, quindi non è come se fossero inutili solo perché sono spenti).
user541686

3

E non ho ancora idea se questo elenco sia completo.

Probabilmente lo è, ma l'unico elenco completo al 100% è la fonte effettiva per il compilatore. Tuttavia, GCC è grande ! E non so se tutti i parametri della riga di comando sono raccolti in un unico posto o distribuiti su più file di origine. Si noti inoltre che alcuni avvertimenti sono per il pre-processore, alcuni per il compilatore effettivo e altri per il linker (che è un programma completamente separato, e si trovano nel pacchetto binutils), quindi molto probabilmente vengono distribuiti.


3
Ho collegato alla pagina Riepilogo opzioni nella mia risposta, che raggruppa tutte le opzioni in una pagina. I criteri di revisione del codice GCC non consentono nuove opzioni senza documentazione, pertanto i documenti dovrebbero essere completi.
Jonathan Wakely,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.