Comment activer (littéralement) TOUS les avertissements de GCC?

194

Je voudrais activer - littéralement - TOUS les avertissements que GCC a. (On pourrait penser que ce serait facile ...)

  • On pourrait penser -Wallque ça pourrait faire l'affaire, mais non! Encore besoin -Wextra.

  • On pourrait penser -Wextraque ça pourrait faire l'affaire, mais non! Tous les avertissements répertoriés ici (par exemple, -Wshadow) ne sont pas activés par cela. Et je n'ai toujours aucune idée si cette liste est complète.

Comment puis-je dire à GCC d'activer (pas de si, et de, ou mais!) Tous les avertissements qu'il a?

user541686
la source
27
@Arafangion: Je ne comprends pas ce qui est "peu clair" à propos de la question - oui, je voudrais activer tous les avertissements applicables à mon code, aussi pédantique soit-il. Pour la raison, c'est très simple: j'ai trouvé certains des avertissements qui ne sont pas activés par -Wall ou -Wextra pour être utiles, et donc je veux essayer le reste pour voir si je peux améliorer mon code. C'est aussi simple que ça.
user541686
12
@JoachimPileborg: "De quoi voulez-vous que le compilateur vous avertisse?" Erreurs potentielles et / ou mauvais style? Je veux dire, si je connaissais tous les avertissements exacts, je les aurais simplement activés manuellement, pas besoin de poser la question. Si la réponse est en effet "vous devez regarder le code source pour tous les trouver", veuillez le poster comme réponse!
user541686
56
offre clang 3.1 -Weverything.
Alexandre Hamez
5
@Arafangion Eh bien, la question est étiquetée C ++ donc ... :)
Un programmeur du
5
@JoachimPileborg Et maintenant, il existe (enfin) un moyen automatisé d'extraire les avertissements de la source: github.com/barro/compiler-warnings
Kyle Strand

Réponses:

129

Tu ne peux pas.

Le manuel de GCC 4.4.0 n'est complet que pour cette version, mais il répertorie tous les avertissements possibles pour 4.4.0. Cependant, ils ne sont pas tous sur la page vers laquelle vous liez, par exemple, certaines options spécifiques au langage sont sur les pages pour les options C ++ ou les options Obj-C. Pour les trouver tous, il vaut mieux regarder le résumé des options

Activer tout inclurait -Wdouble-promotionce qui n'est pertinent que sur les processeurs avec une unité à virgule flottante simple précision 32 bits qui implémente floatdans le matériel, mais émule doubledans le logiciel. Faire des calculs comme doubleutiliserait l'émulation logicielle et serait plus lent. Cela est pertinent pour certains processeurs intégrés, mais complètement non pertinent pour les processeurs de bureau modernes avec prise en charge matérielle pour les virgules flottantes 64 bits.

Un autre avertissement qui n'est généralement pas utile est celui -Wtraditionalqui met en garde contre un code parfaitement bien formé qui a une signification différente (ou qui ne fonctionne pas) dans les "string " "concatenation"définitions de fonctions C traditionnelles, par exemple , ou ISO C! Vous souciez-vous vraiment de la compatibilité avec les compilateurs de 30 ans? Voulez-vous vraiment un avertissement pour écrire int inc(int i) { return i+1; }?

Je pense que -Weffc++c'est trop bruyant pour être utile, il est basé sur la première édition obsolète d' Efficace C ++ et met en garde contre les constructions qui sont parfaitement valides C ++ (et pour lesquelles les directives ont changé dans les éditions ultérieures du livre.) Je ne veux pas être a averti que je n'ai pas initialisé de std::stringmembre dans mon constructeur; il a un constructeur par défaut qui fait exactement ce que je veux, pourquoi devrais-je écrire m_str()pour l'appeler? Les -Weffc++avertissements qui seraient utiles sont trop difficiles à détecter avec précision par le compilateur (donnant de faux négatifs), et ceux qui ne sont pas utiles, tels que l'initialisation explicite de tous les membres, produisent simplement trop de bruit, donnant des faux positifs.

Luc Danton a fourni un excellent exemple d'avertissements inutiles -Waggregate-returnqui n'ont presque certainement aucun sens pour le code C ++.

c'est-à-dire que vous ne voulez pas vraiment tous les avertissements, vous pensez juste que vous le voulez.

Parcourez le manuel, lisez-les, décidez ce que vous voudrez peut-être activer, essayez-les. Lire le manuel de votre compilateur est une bonne chose TM de toute façon, en prenant une coupe courte et permettant des avertissements que vous ne comprenez pas est pas une très bonne idée, surtout si elle est d'éviter d' avoir à RTFM.

Quiconque allume tout est probablement en train de le faire parce qu'il n'a aucune idée parce que ou un patron aux cheveux pointus n'a dit "aucun avertissement".

Certains avertissements sont importants, d'autres non. Vous devez être discriminant ou vous gâcher votre programme. Prenons, par exemple, -Wdouble-promotion. Si vous travaillez sur un système embarqué, vous voudrez peut-être cela; si vous travaillez sur un système de bureau, vous ne le faites probablement pas. Et tu veux -Wtraditional? J'en doute.

Modifier: Voir aussi -Wall-all pour activer tous les avertissements qui est fermé comme WONTFIX.

Edit 2: en réponse à la plainte de DevSolar sur les makefiles devant utiliser différents avertissements selon la version du compilateur, si cela -Wall -Wextrane convient pas, il n'est pas difficile d'utiliser les CFLAGS spécifiques au compilateur et à la version:

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))
Jonathan Wakely
la source
38
"Parcourez le manuel, lisez-les, décidez ce que vous voudrez peut-être activer, essayez-les." Le problème ici réside dans les étapes que vous avez omises: "Consultez de nouveau le manuel pour chaque version du compilateur et adaptez votre liste d'avertissements car ils changent. Faites en sorte que vos Makefiles vérifient la version exacte du compilateur et utilisez une liste différente d'avertissements pour chacun d'eux. " Nous avons des niveaux d'optimisations maintenus par les mainteneurs; pourquoi ne pourraient-ils pas se soucier de fournir le même service pour les avertissements?
DevSolar
17
@JonathanWakely: J'ai mes projets et GCC n'en fait pas partie. Je signale une faiblesse de leur produit. Soit ils le réparent, soit ils acceptent le blâme de ne pas le faire, mais ce n'est pas à moi de le réparer pour eux, OSS soit damné.
DevSolar
14
@JonathanWakely: "Si vous voulez quelque chose, demandez-le, ne vous en faites pas." - Je ne suis pas obligé de participer au projet GCC afin de le critiquer, surtout pas si # 31573 a déjà été marqué comme WONTFIX. Cela met ce sujet de la "question à ce sujet" dans le stade "chienne à ce sujet".
DevSolar
61
-Weverythingest la meilleure solution, je pense, que la stratégie gcc de ne pas donner une telle option. J'utilise ce drapeau avec clang parce que ma philosophie est que je veux que tous les avertissements soient activés par défaut (parce que quelqu'un a pensé qu'il était assez utile pour les ajouter au compilateur), et si je ne l'aime pas, je désactive cet avertissement spécifiquement. Le fait est que vous ne connaissez pas les avertissements qui ne se déclenchent pas, mais vous connaissez les avertissements que vous ne voulez pas que cela se déclenche, et ils sont facilement désactivés.
David Stone
17
@JonathanWakely Oui, mais ils sont dérisoires. La façon la plus simple de voir quels avertissements peuvent être pertinents pour votre code est de voir quels avertissements sont déclenchés par votre code; à ce stade, vous pouvez voir un exemple réel et pertinent du code potentiellement dangereux avant de décider de désactiver ou non l'avertissement. Cela peut être facilement fait avec l' -Weverythingoption de Clang , mais est impossible à faire avec GCC.
Kyle Strand
71

Je suis d'accord avec les réponses précédentes selon lesquelles il n'est probablement pas avantageux d'activer littéralement tous les avertissements, mais GCC fournit un moyen raisonnablement pratique d'y parvenir. La commande

gcc -Q --help=warning

fournit une liste de toutes les options d'avertissement prises en charge avec des informations indiquant si elles sont actives. Cela peut d'ailleurs être utilisé pour savoir quelles options sont (non) activées par exemple -Wallet-Wextra

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

Pour activer tous les avertissements, vous pouvez utiliser des expressions rationnelles pour extraire les paramètres de ligne de commande

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

Pour mon CCG actuel, cela donne:

-Wabi -Wabi-tag -Waddress -Waggregate-return -Waggressive-loop-optimisations -Waliasing -Walign-commons -Wampersand -Warray-bounds -Warray-temporaries -Wassign-intercept -Wattributes -Wbad-function-cast -Wbool-compare -Wbuiltin-macro-redefined -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 -Wdate-time -Wdestation -after-statement -Wdelete-incomplet -Wdelete-non-virtual-dtor -Wdeprecated -Wdeprecated-declarations -Wdesignated-init -Wdisabled-optimization -Wdiscarded-array-qualifiers -Wdiscarded-qualifiers -Wdiv-by-zero -Wdouble-promotion -Weffc ++ -Wempty-body-Wendif-labels -Wenum-compare -Wextra -Wfloat-equal -Wformat-contains-nul -Wformat-extra-args -Wformat-nonliteral -Wformat-security -Wformat-signé-Wformat-y2k -Wformat-zero-length -Wfree -nonheap-object -Wfunction-suppression -Wignored-qualifiers -Wimplicit -Wimplicit-function-declaration -Wimplicit-int -Wimplicit-interface -Wimplicit-procedure -Wincompatible-pointer-types -Winherited-variadic-ctor -Winit-self -Winline -Wint-conversion -Wint-to-pointer-cast -Wintrinsic-shadow -Wintrinsics-std -Winvalid-memory-model -Winvalid-offsetof -Winvalid-pch -Wjump-misses-init -Wline-truncation -Wliteral-suffix -Wlogical -not-parentheses -Wlogical-op -Wlong-long -Wmain -Wmaybe-uninitialized -Wmemset-transposed-args -Wmissing-braces -Wmissing-declarations -Wmissing-field-initializers -Wmissing-include-dirs -Wmissing-parameter-type -Prototypes manquants-Wmultichar -Wnarrowing -Wnested-externs -Wnoexcept -Wnon-template-friend -Wnon-virtual-dtor -Wnonnull -Wodr -Wold-style-cast -Wold-style-declaration -Wold-style-definition -Wopenmp-simd -Woverflow -Woverlength-strings -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 -Wprotocol -Wreal-q-constant -Wrealloc-lhs -Wrealloc-lhs-all -Wredundant-decls -Wreorder -Wreturn-local-addr -Wreturn-type -Wselector -Wsequence-point -Wshadow -Wshadow-ivar -Wshift-count-negative -Wshift-count-overflow -Wsign-compare -Wsign-promo -Wsized-deallocation -Wsizeof-array-argument -Wsizeof-pointer-memaccess -Wstack-protector -Wstrict-null-sentinel -Wstrict-prototypes -Wstrict-selector-match-Wsuggest-attribute = const -Wsuggest-attribute = format -Wsuggest-attribute = noreturn -Wsuggest-attribute = pure -Wsuggest-final-methods -Wsuggest-final-types -Wsuggest-override -Wsurprising -Wswitch -Wswitch-bool -Wswitch -default -Wswitch-enum -Wsync-nand -Wsynth -Wsystem-headers -Wtabs -Wtarget-lifetime -Wtraditional -Wtraditional-conversion -Wtrampolines -Wtrigraphs -Wtype-limits -Wundeclared-selector -Wundef -Wunderflow -Wuninitialized -Wunknown -Wunsafe-loop-optimizations -Wunsuffixed-float-constants -Wunused -Wunused-but-set-parameter -Wunused-but-set-variable -Wunused-dummy-argument -Wunused-function -Wunused-label -Wunused-local-typedefs -Wunused-macros -Wunused-parameter -Wunused-result -Wunused-variable -Wunused-variable -Wuse-without-only -Wuseless-cast -Wvarargs -Wvariadic-macros -Wvector-operation-performance -Wvirtual-move-assign-assign-Wvla -Wvolatile-register-var -Wwrite-strings -Wzero-as-null-pointer-constant -Wzerotrip -frequire-return-statement

Cela peut maintenant être utilisé pour appeler le GCC, c'est-à-dire

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

Notez cependant que cela entraîne des avertissements car certaines options d'avertissement ne sont disponibles que pour certaines langues (par exemple C++). Ceux-ci pourraient être évités en utilisant une expression plus régulière pour n'inclure que les options autorisées pour la langue actuelle ou en ajoutant une option appropriée -Wno-whateverà la fin de l'appel.

Haatschii
la source
10
J'ai peur que ce ne soit pas pratique. Gcc m'a montré des avertissements de std lib.
Valentin Heinitz
13
@ValentinHeinitz Comme je l'ai dit, je ne pense pas qu'il soit bénéfique d'activer littéralement tous les avertissements, mais c'est ce que OP a demandé. Cependant, je pense qu'en supprimant explicitement certains avertissements problématiques déjà mentionnés dans d'autres réponses (par exemple en ajoutant respectivement -Wno-any à la fin de l'appel), cela peut être d'une utilité pratique.
Haatschii
6
@ValentinHeinitz Vous pouvez empêcher gcc d'émettre des avertissements pour les en-têtes système / std / tiers en utilisant -isystemplutôt que -Ipour les répertoires appropriés.
Kyle Strand
4
Cela devrait être la réponse acceptée car cela répond réellement et directement à la question.
TFuto
16

Il est tout simplement impossible de programmer avec tous les avertissements activés (sauf si vous allez les ignorer, mais alors, pourquoi s'embêter?). Par exemple, supposons que vous utilisez suivant ensemble de drapeaux: -Wstrict-prototypes -Wtraditional.

Même avec deux avertissements activés, le programme suivant se plaindrait.

/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) {
     ^

Vous pensez peut-être "alors je vais utiliser des prototypes à l'ancienne". Non, cela ne fonctionnera pas.

/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)
     ^

Et non, ne pas spécifier de prototype est également faux, car le compilateur se plaindra également.

/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() {
     ^

Si vous définissez des fonctions dans votre programme, vous ne pouvez pas utiliser tous les indicateurs, car le compilateur se plaindra de toute définition de fonction imaginable.

Pour C ++, c'est possible (l' -Wtraditionalindicateur n'existe pas), et des programmes très simples peuvent être compilés. Pour activer tous les avertissements, utilisez la liste suivante des avertissements (probablement certains avertissements sont dupliqués, car je n'ai pas pris la peine de filtrer les avertissements activés par -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
Konrad Borowski
la source
13
Je n'ai jamais pris la peine de vérifier cela jusqu'à présent, mais en fait, ce n'est pas impossible ... essayezint main(int, char **); int main(argc, argv) int argc; char **argv; { (void)argc; (void)argv; return 0; }
user541686
2
Même avec ce programme trivial, je peux toujours obtenir "avertissement: l'utilisation de la pile est de 16 octets [-Wstack-usage =]" ;-)
Marc Glisse
7

Quelqu'un a créé un ensemble d'outils pour déterminer l' ensemble complet des avertissements pour une version GCC ou Clang donnée.

Pour GCC, la copie de la liste complète des avertissements fournis par cet outil pour la version de votre compilateur semble être le seul moyen de garantir que tous les avertissements sont activés, car (contrairement à Clang) GCC ne fournit pas -Weverything.

L'outil semble analyser le c.optfichier réel dans le code source de GCC, donc ses résultats devraient être définitifs.

Le référentiel contient également des fichiers texte avec les listes d'avertissement générées pour la plupart des versions de GCC et Clang (actuellement Clang 3.2 à 3.7 et GCC 3.4 à 5.3).

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

Kyle Strand
la source
Telle est la réponse. Utilisez la liste "de niveau supérieur" et ajoutez tous les arguments qui sont au niveau supérieur (non indentés / imbriqués). github.com/Barro/compiler-warnings/blob/master/gcc/…
Jetski S-type
6

Gcc 4.3+ a maintenant -Q --help = warnings, vous pouvez même spécifier --help = warnings, C pour simplement imprimer les avertissements liés à C.

Je viens d'écrire un module m4 pour en profiter (prend également en charge -Weverything), voir wget_manywarnings.m4

Comment l'utiliser est assez simple, fondamentalement, le module active chaque indicateur d'avertissement. Et vous supprimez les avertissements si nécessaire - certains sont vraiment très verbeux. Exemple: configure.ac

Si vous n'utilisez pas les outils automatiques, vous trouverez le code pour activer tous les avertissements désactivés dans le module m4, qui est essentiellement l'appel gcc acheminé via 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 }'

rockdaboot
la source
3

De cette page :

Notez que certains indicateurs d'avertissement ne sont pas impliqués par -Wall. Certains d'entre eux mettent en garde contre les constructions que les utilisateurs ne considèrent généralement pas comme douteuses, mais que vous souhaiterez parfois vérifier; d'autres mettent en garde contre les constructions qui sont nécessaires ou difficiles à éviter dans certains cas, et il n'y a pas de moyen simple de modifier le code pour supprimer l'avertissement. Certains d'entre eux sont activés par, -Wextramais beaucoup d'entre eux doivent être activés individuellement.

Je suppose que la question est laquelle ? Vous pouvez peut-être grep cette page pour toutes les lignes commençant par -W, et obtenir une liste complète des drapeaux d'avertissement. Comparez ensuite ceux-ci avec les listes sous -Wallet -Wextra. Il y en a aussi -Wpedantic, bien que vous souhaitiez évidemment être encore plus pédant =)

paddy
la source
"Et je n'ai toujours aucune idée si cette liste est complète" ... oui, je peux certainement saluer cette page, mais la question est, est-elle complète?
user541686
1
Je ne sais pas ... Vous devrez peut-être parcourir le code source de GCC. Essayez-vous de vous rendre la vie de programmeur extrêmement difficile, ou y a-t-il une bonne raison pour laquelle vous souhaitez voir tous les avertissements imaginables? =)
paddy
2
J'aimerais voir le diagnostic de mon code par GCC - je le trouve vraiment utile. Mais évidemment, si je connaissais déjà tous les avertissements et lesquels sont utiles (et lesquels ne le sont pas), alors il n'y aurait rien eu à demander. Il n'y a pas vraiment de moyen pour moi de le dire à moins de les essayer (et par exemple, j'ai trouvé l'ombrage utile, donc ce n'est pas comme s'ils étaient inutiles juste parce qu'ils étaient éteints).
user541686
3

Et je n'ai toujours aucune idée si cette liste est complète.

C'est probablement le cas, mais la seule liste complète à 100% est la source réelle du compilateur. Cependant, GCC est grand ! Et je ne sais pas si tous les paramètres de ligne de commande sont collectés en un seul endroit ou répartis sur plusieurs fichiers source. Notez également que certains avertissements sont destinés au préprocesseur, certains au compilateur réel et d'autres au lieur (qui est un programme complètement séparé, et se trouvant dans le paquet binutils), donc ils sont très probablement répartis.

Un mec programmeur
la source
3
J'ai lié à la page Résumé des options dans ma réponse, qui regroupe toutes les options sur une seule page. Les politiques de révision du code GCC ne permettent pas de nouvelles options sans documentation, les documents doivent donc être complets.
Jonathan Wakely