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

Je voudrais activer -- littéralement -- tous les des avertissements que GCC a. (Vous pensez que ça serait facile...)

  • Vous pensez -Wall pourrait faire l'affaire, mais non! Encore besoin -Wextra.

  • Vous pensez -Wextra pourrait faire l'affaire, mais non! Tous les Avertissements listés ici (par exemple, -Wshadow) ne sont pas activés par ceci. Et je n'ai toujours aucune idée si cette liste est exhaustive.

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

142
demandé sur Mehrdad 2012-07-30 06:39:08

7 réponses

Vous ne pouvez 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. Ils ne sont pas tous sur la page que vous liez, par exemple certaines options spécifiques à la langue sont sur les pages pour les options C++ ou Obj-C options. Pour les trouver tous, il vaut mieux regarder le résumé des Options

Activer Tout inclurait -Wdouble-promotion qui n'est pertinent que sur les processeurs avec un bit 32 unité à virgule flottante simple précision qui implémente float dans le matériel, mais émule double dans le logiciel. Faire des calculs comme double utiliserait l'émulation logicielle et serait plus lent. C'est pertinent pour certains processeurs embarqués, mais complètement hors de propos pour les processeurs de bureau modernes avec support matériel pour 64 bits à virgule flottante.

Un autre avertissement qui n'est généralement pas utile est -Wtraditional, qui met en garde contre un code parfaitement bien formé qui a une signification différente (ou ne fonctionne pas) en C traditionnel, par exemple "string " "concatenation", ou définitions de fonctions 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++ est trop bruyant pour être utile, il est basé sur la première édition obsolète de Effective 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 averti que je n'ai pas initialisé un membre std::string dans mon constructeur; il a un constructeur par défaut qui fait exactement ce que je veux, pourquoi devrais-je écrire m_str() pour appeler? Les Avertissements -Weffc++ qui seraient utiles sont trop difficiles à détecter par le compilateur (donnant des faux négatifs), et ceux qui ne sont pas utiles, tels que l'initialisation explicite de tous les membres, produisent trop de bruit, donnant des faux positifs.

Luc Danton a fourni un excellent exemple d'Avertissements inutiles de {[12] } qui n'a presque certainement jamais de sens pour C++ code.

C'est-à-dire que vous ne voulez pas vraiment tous les Avertissements, vous pensez juste que vous le faites.

Parcourez le manuel, lisez à leur sujet, décidez lequel vous voudrez peut-être activer, essayez-les. Lire le manuel de votre compilateur est une bonne choseTM de toute façon, prendre un raccourci et activer des avertissements que vous ne comprenez pas n'est pas une très bonne idée, surtout si c'est pour éviter D'avoir à RTFM.

Toute personne qui vient d'allumer everything le fait probablement parce qu'ils sont désemparés parce que ou un patron aux cheveux pointus a dit " pas d'Avertissements."

Certains avertissements sont importants, et d'autres ne le sont pas. vous devez faire preuve de discrimination ou vous gâchez votre programme. Considérons, par exemple, -Wdouble-promotion. Si vous travaillez sur un système embarqué, vous pourriez voulez que cela, si vous travaillez sur un système de bureau vous n'avez probablement pas. Et voulez-vous -Wtraditional? J'en doute.

Edit: Voir aussi -Mur, afin de permettre à tous les avertissements, qui est fermé comme WONTFIX.

Edit 2: en réponse à la plainte de DevSolar concernant les makefiles qui doivent utiliser différents avertissements en fonction de la version du compilateur, Si -Wall -Wextra ne convient pas, il n'est pas difficile d'utiliser des 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))
97
répondu Jonathan Wakely 2015-09-22 12:15:53

Je suis d'accord avec les réponses précédentes qu'il n'est probablement pas bénéfique 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 (pas) activées par exemple -Wall et -Wextra

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

Pour activer tous les Avertissements, vous pouvez utiliser une expression rationnelle pour extraire la commande paramètres de ligne

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

Pour mon GCC actuel, cela donne:

-Wabi-Wabi-tag-Waddress-Waggregate-return-Waggressive-loop-optimizations-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-indices-wcharacter-truncation-Wchkp -Wclobbered-Wcomment-Wcompare-reals-wconditionally-supported-Wconversion-wconversion-extra-wconversion-null-Wcoverage-mismatch-Wcpp-wctor-dtor-privacy-Wdate-time-Wdeclaration-after-statement-Wdelete-incomplet-Wdelete-non-virtual-dtor-Wdeprecated-wdeprecated-declarations-Wdesignated-init-Wdisabled-optimization-Wdiscarded-tableau-qualificateurs-Wdiscarded-Qualifiers-WDIV-par-zéro-Wdouble-promotion-Weffc++ -Wempty-corps-Wendif-labels-Wenum-comparer-Wextra-wfloat-égale -Wformat-contains-nul-Wformat-extra-args-Wformat-nonliteral-wformat-security-Wformat-signedness-Wformat-y2k-Wformat-zero-length-Wfree-nonheap-object-Wfunction-elimination-Wignored-qualifiers-Wimplicic-wimplicic-function-declaration-Wimplicic-int-wimplicic-interface-wimplicic-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-wmissing-prototypes-Wmultichar-Wnarrrowing-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 -Wsizeof-deallocation-wsizeof-array-argument-wsizeof-pointer-memaccess-wstack-protector-wstrict-null-sentinel-wstrict-prototypes-wstrict-selector-match-wsuggest-attribut=const-wsuggest-attribut=format-wsuggest-attribut=noreturn-wsuggest-attribut=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-limites-Wundeclared-sélecteur -Wundef -Wunderflow -Wuninitialized -Wunknown-pragmas -Wunsafe-boucle-optimisations -Wunsuffixed-float-les constantes -Wunused -Wunused-mais-set-paramètre -Wunused-mais-set-variable -Wunused-mannequin-argument -Wunused-fonction -Wunused-label-Wunused-local-typedefs -Wunused-macros-Wunused-paramètre -Wunused-résultat -Wunused-valeur -Wunused-variable -Wuse-sans-seulement -Wuseless-cast -Wvarargs -Wvariadic-macros-Wvector-de fonctionnement-de la performance -Wvirtual-move-attribuer -Wvla -Wvolatile-inscrivez-vous-var -Wwrite-strings -Wzero-que-de pointeur null-constant-Wzerotrip -frequire-retour-déclaration de

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 en raison de certaines options d'avertissement disponibles uniquement pour certaines langues (par exemple C++). Ceux-ci pourraient être évités en utilisant plus de regex pour inclure uniquement les options autorisées pour la langue actuelle.

44
répondu Haatschii 2016-01-24 02:09:26

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 utilisiez l'ensemble de drapeaux suivant: -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 pouvez penser "Eh bien, je vais utiliser des prototypes de style ancien alors". Non, cela ne fonctionne 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 isn’t a prototype [-Wstrict-prototypes]
 int main(argc, argv)
     ^

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

/tmp $ cat main.c 
int main() {
    return 0;
}
/tmp $ gcc -Wstrict-prototypes -Wtraditional main.c 
main.c:1:5: warning: function declaration isn’t 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'indicateur -Wtraditional n'existe pas), et des programmes très simples peuvent être compilés. Pour activer tous les Avertissements, utilisez la liste d'Avertissements suivante(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
12
répondu Konrad Borowski 2013-12-21 16:30:36

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

Pour GCC, copier à partir de la liste complète des avertissements fournis par cet outil pour votre version du compilateur semble être le moyen seulement de s'assurer que Tous les Avertissements sont activés, puisque (contrairement à Clang) GCC ne fournit pas -Weverything.

L'outil semble analyser le fichier c.opt réel dans le code source GCC, donc ses résultats devraient être définitif.

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

4
répondu Kyle Strand 2016-02-28 19:04:51

Gcc 4.3+ nows-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 (supporte également clang's-Weverything), voir wget_manywarnings.m4

Comment l'utiliser est assez simple, fondamentalement le module sur lequel vous activez chaque drapeau warn. Et vous supprimez les avertissements au besoin-certains sont vraiment très verbeux. Exemple: configurer.ac

Si vous n'utilisez pas autotools, vous trouvez 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 }'

4
répondu Tim Ruehsen rockdaboot 2016-11-11 21:32:56

À Partir de cette page:

Notez que certains indicateurs d'avertissement ne sont pas implicites par -Wall. Certains d'entre eux avertir des constructions que les utilisateurs ne considèrent généralement pas discutable, mais que vous voudrez peut-être vérifier de temps en temps; d'autres mettent en garde contre les constructions nécessaires ou difficiles à éviter certains cas, et il n'y a pas de moyen simple de modifier le code pour supprimer avertissement. Certains d'entre eux sont activés par -Wextra, mais beaucoup d'entre eux doit être activé individuellement.

Je suppose que la question Est lesquels ? Peut-être que vous pourriez grep{[15] } cette page pour toutes les lignes commençant par-W, et obtenir une liste complète des drapeaux d'avertissement. Ensuite, comparez ceux avec les listes sous -Wall et -Wextra. Il y a aussi -Wpedantic, bien que vous vouliez évidemment être encore plus pédant=)

3
répondu paddy 2012-07-30 03:00:25

Et je n'ai toujours aucune idée si cette liste est exhaustive.

C'est probablement le cas, mais la seule liste complète à 100% est la source réelle du compilateur. Cependant, GCC estbig ! 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 pour le pré-processeur, certains pour le compilateur réel et d'autres pour l'éditeur de liens (qui est un programme complètement séparé, et trouvé dans le paquet binutils) donc ils sont très probablement étalés.

3
répondu Some programmer dude 2012-07-30 06:03:08