Drapeaux pour activer des avertissements G ++ détaillés et détaillés

122

Souvent en C sous gcc, je commencerai par l'ensemble suivant d'indicateurs d'avertissement (douloureusement assemblés à partir de plusieurs sources):

-Wall -Wextra -Wformat-nonliteral -Wcast-align -Wpointer-arith -Wbad-function-cast \
-Wmissing-prototypes -Wstrict-prototypes -Wmissing-declarations -Winline -Wundef \
-Wnested-externs -Wcast-qual -Wshadow -Wwrite-strings -Wno-unused-parameter \
-Wfloat-equal -pedantic -ansi

Je vais créer (au moins mes versions de débogage) avec cet ensemble d'avertissements et réparer tout ce que je peux (généralement tout), puis supprimer uniquement les indicateurs s'ils ne sont pas pertinents ou non réparables (presque jamais le cas). Parfois, j'ajouterai aussi -Werrorsi je dois m'éloigner pendant la compilation.

Je ne fais que reprendre le C ++ (oui, j'ai 15 ans de retard sur le temps), et j'aimerais commencer du bon pied.

Ma question est la suivante: quelqu'un a-t-il un ensemble similaire précompilé d'indicateurs d'avertissement complets pour C ++ sous g++? (Je sais que beaucoup d'entre eux seront les mêmes.)

Sdaz MacSkibbons
la source
69
Quels sont les besoins de gcc (car il est décidé de façon flagrante mensonge au sujet -Wall) est un -Wbloody_everythingdrapeau :-)
paxdiablo
Vous pouvez marquer votre question comme dupe, mais vous pouvez également mettre votre dernière modification en tant que réponse puisque vous avez effectivement répondu à votre question. Et je serais heureux de voter alors :)
ereOn
4
OP et @paxdiablo: GCC a toujours rejeté ce genre de chose, mais il est disponible dans Clang via -Weverything. J'ai lu que même les développeurs de Clang ++ sont un peu préoccupés par les utilisateurs qui l'activent; apparemment, il était destiné à un usage de développement interne uniquement. Cela n'a cependant aucun sens, car l'activation -Weverythingest probablement le meilleur moyen possible de découvrir des avertissements potentiellement utiles que vous ne connaissiez pas auparavant.
Kyle Strand
1
OP et @paxdiablo Il existe maintenant un moyen de trouver la liste complète des avertissements pour une version GCC donnée: github.com/barro/compiler-warnings
Kyle Strand
1
Double possible de Comment activer (littéralement) TOUS les avertissements de GCC?
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

Réponses:

138

J'ai parcouru et trouvé l'ensemble minimal d'inclusions qui devrait obtenir le niveau maximal d'avertissement. J'ai ensuite supprimé de cette liste l'ensemble des avertissements qui, à mon avis, n'indiquent pas réellement que quelque chose de mauvais se passe, ou qui ont trop de faux positifs pour être utilisés dans une vraie construction. J'ai expliqué pourquoi chacun de ceux que j'avais exclus étaient exclus. Voici ma dernière série d'avertissements suggérés:

-pedantic -Wall -Wextra -Wcast-align -Wcast-qual -Wctor-dtor-privacy -Wdisabled-optimization -Wformat=2 -Winit-self -Wlogical-op -Wmissing-declarations -Wmissing-include-dirs -Wnoexcept -Wold-style-cast -Woverloaded-virtual -Wredundant-decls -Wshadow -Wsign-conversion -Wsign-promo -Wstrict-null-sentinel -Wstrict-overflow=5 -Wswitch-default -Wundef -Werror -Wno-unused

Avertissements douteux présents:

  • J'inclus -Wno-unusedparce que j'ai souvent des variables que je sais que j'utiliserai plus tard, mais que je n'ai pas encore écrit pour la fonctionnalité. Supprimer les avertissements à ce sujet me permet d'écrire dans mon style préféré de différer occasionnellement la mise en œuvre des choses. Il est utile de désactiver cette option de temps en temps pour vous assurer que rien ne passe entre les mailles du filet.

  • -Wdisabled-optimizationsemble être un paramètre de préférence utilisateur fort. Je viens d'ajouter celui-ci à ma version (uniquement pour les versions optimisées pour des raisons évidentes) et cela n'a rien changé, donc cela ne semble pas être un avertissement particulièrement bavard, du moins pour la façon dont je code. Je l'inclus (même si le code qui déclenche cet avertissement n'est pas nécessairement faux) parce que je crois qu'il faut travailler avec mes outils plutôt que contre eux. Si gcc me dit qu'il ne peut pas optimiser le code pour la façon dont je l'ai écrit, alors je devrais envisager de le réécrire. Je soupçonne que le code qui déclenche cet avertissement pourrait bénéficier d'être plus modulaire, peu importe, donc bien que le code ne soit pas techniquement faux (probablement), il l'est probablement d'un point de vue stylistique.

  • -Wfloat-equalavertit des comparaisons d'égalité sûres (en particulier, comparaison avec une valeur non calculée de -1). Un exemple dans mon code où j'utilise ceci est que j'ai un vecteur de float. Je passe par ce vecteur, et il y a des éléments que je ne peux pas encore évaluer ce qu'ils devraient être, donc je les mets à -1.0f (puisque mon problème n'utilise que des nombres positifs, -1 est hors du domaine). Plus tard, je passe par et met à jour les valeurs -1.0f. Il ne se prête pas facilement à un autre mode de fonctionnement. Je soupçonne que la plupart des gens n'ont pas ce problème, et la comparaison d'un nombre exact en virgule flottante est probablement une erreur, donc je l'inclus dans la liste par défaut.

  • -Wold-style-casta beaucoup de faux positifs dans le code de bibliothèque que j'utilise. En particulier, la famille de fonctions htonl utilisée dans la mise en réseau, ainsi qu'une implémentation de chiffrement Rijndael (AES) que j'utilise, ont des moulages à l'ancienne dont elle me met en garde. J'ai l'intention de remplacer les deux, mais je ne suis pas sûr qu'il y ait autre chose dans mon code dont il se plaindra. Cependant, la plupart des utilisateurs devraient probablement l'activer par défaut.

  • -Wsign-conversionétait difficile (et n'a presque pas fait la liste). L'activer dans mon code a généré une énorme quantité d'avertissements (100+). Presque tous étaient innocents. Cependant, j'ai pris soin d'utiliser des entiers signés partout où je n'étais pas sûr, bien que pour mon domaine de problème particulier, j'obtienne généralement une légère augmentation de l'efficacité en utilisant des valeurs non signées en raison de la grande quantité de division d'entiers que je fais. J'ai sacrifié cette efficacité parce que je craignais de promouvoir accidentellement un entier signé en un entier non signé, puis de le diviser (ce qui n'est pas sûr, contrairement à l'addition, à la soustraction et à la multiplication). L'activation de cet avertissement m'a permis de changer en toute sécurité la plupart de mes variables en types non signés et d'ajouter quelques transtypages à d'autres endroits. Il est actuellement un peu difficile à utiliser car l'avertissement n'est pas si intelligent. Par exemple, si vous faitesunsigned short + (integral constant expression), ce résultat est implicitement promu en int. Il avertit ensuite d'un problème potentiel de signe si vous attribuez cette valeur à unsignedou unsigned short, même si elle est sûre. C'est certainement l'avertissement le plus facultatif pour presque tous les utilisateurs.

  • -Wsign-promo: voir -Wsign-conversion.

  • -Wswitch-defaultsemble inutile (vous ne voulez pas toujours un cas par défaut si vous avez explicitement énuméré toutes les possibilités). Cependant, activer cet avertissement peut appliquer quelque chose qui est probablement une bonne idée. Pour les cas où vous souhaitez explicitement tout ignorer sauf les possibilités énumérées (mais d'autres nombres sont possibles), insérezdefault: break;pour le rendre explicite. Si vous énumérez explicitement toutes les possibilités, l'activation de cet avertissement vous assurera de mettre quelque chose comme assert (false) pour vous assurer que vous avez réellement couvert toutes les options possibles. Cela vous permet d'être explicite dans le domaine de votre problème et de l'appliquer par programme. Cependant, vous devrez faire attention en collant simplement assert (false) partout. C'est mieux que de ne rien faire avec le cas par défaut, mais comme d'habitude avec assert, cela ne fonctionnera pas dans les versions de version. En d'autres termes, vous ne pouvez pas vous y fier pour valider les numéros que vous obtenez, par exemple, d'une connexion réseau ou d'une base de données sur laquelle vous n'avez pas un contrôle absolu. Les exceptions ou le retour anticipé sont le meilleur moyen de gérer cela (mais vous devez toujours avoir un cas par défaut!).

  • -Werrorest important pour moi. Lors de la compilation de grandes quantités de code dans une version multithread avec plusieurs cibles, il est facile pour un avertissement de passer. Transformer les avertissements en erreurs garantit que je les remarque.

Ensuite, il y a un ensemble d'avertissements qui ne sont pas inclus dans la liste ci-dessus car je ne les ai pas trouvés utiles. Voici les avertissements et mes commentaires sur les raisons pour lesquelles je ne les inclut pas dans la liste par défaut:

Avertissements absents:

  • -Wabin'est pas nécessaire car je ne combine pas les binaires de différents compilateurs. J'ai quand même essayé de compiler avec, et cela ne s'est pas déclenché, donc cela ne semble pas inutilement verbeux.

  • -Waggregate-returnn'est pas quelque chose que je considère comme une erreur. Par exemple, il se déclenche lors de l'utilisation d'une boucle for basée sur une plage sur un vecteur de classes. L'optimisation de la valeur de retour doit prendre en compte les effets négatifs de cela.

  • -Wconversiontriggers sur ce code: short n = 0; n += 2;la conversion implicite en int provoque un avertissement lorsqu'il est ensuite reconverti dans son type cible.

  • -Weffc++inclut un avertissement si tous les membres de données ne sont pas initialisés dans la liste d'initialisation. Je ne fais pas cela intentionnellement dans de nombreux cas, donc l'ensemble d'avertissements est trop encombré pour être utile. Cependant, il est utile de l'activer de temps en temps et de rechercher d'autres avertissements (tels que les destructeurs non virtuels de classes de base). Ce serait plus utile comme une collection d'avertissements (comme -Wall) au lieu d'un seul avertissement en soi.

  • -Winlineest absent parce que je n'utilise pas le mot-clé en ligne à des fins d'optimisation, juste pour définir des fonctions en ligne dans les en-têtes. Je me fiche de savoir si l'optimiseur l'intègre réellement. Cet avertissement se plaint également s'il ne peut pas insérer une fonction déclarée dans un corps de classe (comme un destructeur virtuel vide).

  • -Winvalid-pch est manquant car je n'utilise pas d'en-têtes précompilés.

  • -Wmissing-format-attributen'est pas utilisé car je n'utilise pas d'extensions gnu. Idem pour -Wsuggest-attributeet plusieurs autres

  • Potentiellement remarquable pour son absence est -Wno-long-long, dont je n'ai pas besoin. Je compile avec -std=c++0x( -std=c++11dans GCC 4.7), qui inclut long longdes types entiers. Ceux qui sont bloqués sur C ++ 98 / C ++ 03 peuvent envisager d'ajouter cette exclusion de la liste d'avertissement.

  • -Wnormalized=nfc est déjà l'option par défaut et semble être la meilleure.

  • -Wpaddedest activé occasionnellement pour optimiser la disposition des classes, mais il n'est pas laissé activé car toutes les classes n'ont pas suffisamment d'éléments pour supprimer le remplissage à la fin. En théorie, je pourrais obtenir des variables supplémentaires gratuitement, mais cela ne vaut pas l'effort supplémentaire de maintenir cela (si la taille de ma classe change, il n'est pas facile de supprimer ces variables auparavant libres).

  • -Wstack-protector n'est pas utilisé car je n'utilise pas -fstack-protector

  • -Wstrict-aliasing=3est activé par -Wallet est le plus précis, mais il semble que les niveaux 1 et 2 donnent plus d'avertissements. En théorie, un niveau inférieur est un avertissement «plus fort», mais cela se fait au prix de plus de faux positifs. Mon propre code de test compilé proprement sous les 3 niveaux.

  • -Wswitch-enumn'est pas un comportement que je veux. Je ne veux pas gérer chaque instruction de commutation explicitement. Ce serait utile si le langage avait un mécanisme pour l'activer sur des instructions de commutation spécifiées (pour s'assurer que les futures modifications de l'énumération sont gérées partout où elles doivent l'être), mais c'est excessif pour un paramètre "tout ou rien".

  • -Wunsafe-loop-optimizationsprovoque trop de faux avertissements. Il peut être utile d'appliquer celui-ci périodiquement et de vérifier manuellement les résultats. À titre d'exemple, il a généré cet avertissement dans mon code lorsque j'ai bouclé sur tous les éléments d'un vecteur pour leur appliquer un ensemble de fonctions (en utilisant la boucle for basée sur la plage). C'est également un avertissement pour le constructeur d'un tableau const de const std :: string (où ce n'est pas une boucle dans le code utilisateur).

  • -Wzero-as-null-pointer-constantet -Wuseless-castsont des avertissements uniquement GCC-4.7, que j'ajouterai lorsque je passerai à GCC 4.7.

J'ai déposé quelques rapports de bogue / demandes d'amélioration sur gcc à la suite de certaines de ces recherches, donc j'espère que je pourrai éventuellement ajouter d'autres avertissements de la liste "ne pas inclure" à la liste "inclure" . Cette liste comprend tous les avertissements mentionnés dans ce fil (plus je pense que quelques autres). De nombreux avertissements non mentionnés explicitement dans cet article sont inclus dans le cadre d'un autre avertissement que je mentionne. Si quelqu'un remarque des avertissements qui sont entièrement exclus de ce message, faites-le moi savoir.

edit: Il semble que j'en avais manqué plusieurs (que j'ai maintenant ajoutées). Il y a en fait une deuxième page sur http://gcc.gnu.org qui est assez bien cachée. Options générales d'avertissement et options C ++ (faites défiler vers le bas pour les avertissements)

David Stone
la source
J'ai récemment soumis une demande d'amélioration basée sur mes recherches pour cette réponse: gcc.gnu.org/bugzilla/show_bug.cgi?id=53313 . Cela simplifierait considérablement la situation d'alerte en créant des niveaux d'alerte. Dans ma proposition, mon ensemble d'avertissements suggéré est d'environ -W4, avec une proposition supplémentaire de créer -Winf, ce qui signifierait -Weverything-and-I-really-mean-it-this-time
David Stone
Demande d'amélioration qui entraînerait l'ajout d'une partie de -Wpadded à la liste recommandée: gcc.gnu.org/bugzilla/show_bug.cgi?id=53514
David Stone
Demande d'amélioration qui entraînerait l'ajout de parties de -Weffc ++ à la liste recommandée: gcc.gnu.org/bugzilla/show_bug.cgi?id=16166
David Stone
1
@Predelnik: C'est plus compliqué que ça. -Wswitch-enumavertit si vous ne gérez pas explicitement chaque valeur d'énumération dans un commutateur et defaultne compte pas comme explicite. D'autre part, -Wswitch-defaultvous avertit si votre commutateur n'a pas de defaultcas, même si vous avez explicitement couvert toutes les valeurs possibles.
David Stone
2
BTW - utilisez à la -isystemplace de -Ivotre "ancien code de bibliothèque" pour éviter tous ces faux positifs
galois
39

D'oh, toutes mes recherches originales ont généré 99% de messages sur la façon de supprimer les avertissements (assez effrayants), mais je viens de parcourir ce commentaire , qui contient ce bel ensemble d'indicateurs (certains moins pertinents):

Vérification croisée avec:

http://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html

-g -O -Wall -Weffc++ -pedantic  \
-pedantic-errors -Wextra -Waggregate-return -Wcast-align \
-Wcast-qual -Wconversion \
-Wdisabled-optimization \
-Werror -Wfloat-equal -Wformat=2 \
-Wformat-nonliteral -Wformat-security  \
-Wformat-y2k \
-Wimplicit  -Wimport  -Winit-self  -Winline \
-Winvalid-pch   \
-Wlong-long \
-Wmissing-field-initializers -Wmissing-format-attribute   \
-Wmissing-include-dirs -Wmissing-noreturn \
-Wpacked  -Wpadded -Wpointer-arith \
-Wredundant-decls \
-Wshadow -Wstack-protector \
-Wstrict-aliasing=2 -Wswitch-default \
-Wswitch-enum \
-Wunreachable-code -Wunused \
-Wunused-parameter \
-Wvariadic-macros \
-Wwrite-strings

Donc, je pense que c'est un bon point de départ. Je n'avais pas réalisé que c'était une dupe, mais au moins c'était profondément enterré. :-)

Sdaz MacSkibbons
la source
1
Peut-être, mais cela semble changer entre les versions, et probablement au gré des taches solaires et du RMS, donc être trop explicite ne fera probablement pas de mal. C'est un bon point de départ, de toute façon.
Sdaz MacSkibbons
3
D'un grep rapide de c-opts.c / opts.c de 4.5.2 pour 'case OPT_W', il vous manque: débordement strict, undef, sentinelle nulle stricte, normalisé, multichar, déclaration de fonction implicite, obsolète, étiquettes endif, comment s , macro intégrée redéfinie, plus grande que, plus grande que eq, abi. C'est fou qu'il n'y ait pas d'option de ligne de commande pour les lister.
Tony Delroy
3
Je pense que c'est plus fou de -Wallne pas faire ce à quoi on pourrait s'attendre. Mais merci, certains d'entre eux semblent très utiles!
Sdaz MacSkibbons
1
La désactivation des avertissements a sa place. Après tout, ce sont des "avertissements". Une autre situation est lorsque vous activez un indicateur qui active plusieurs avertissements, mais que vous voulez être sélectif à ce sujet.
Tamás Szelei
1
Comment pouvez-vous utiliser -Waggregate-return? Cela me donne un avertissement pour chaque utilisation debegin/end()
Flamefire
13

Certains d'entre eux sont déjà inclus dans -Wallou -Wextra.

Une bonne configuration de base pour C est:

-std=c99 -pedantic -Wall -Wextra -Wwrite-strings -Werror

et pour C ++

-ansi -pedantic -Wall -Wextra -Weffc++

(sauter -Werrorpour C ++ depuis -Weffc++a quelques ennuis)

Šimon Tóth
la source
10
-Werror peut être désactivé pour des types d'avertissements spécifiques, par exemple: -Werror -Weffc ++ -Wno-error = effc ++
Robert Hensing
2
ansi : En mode C, cela équivaut à -std=c89. En mode C ++, c'est équivalent à -std=c++98. ie si vous en spécifiez un autre std, ne l'utilisez pasansi
Sean Breckenridge
2

Essayer

export CFLAGS="`gcc --help=warnings | grep '\-W' | awk '{print $1 \" \"}' |
sort | uniq` -pedantic -fdiagnostics-show-option -Werror"

C'est un démarrage rapide et sale qui aura certainement besoin de quelques ajustements; pour une chose, même si vous appelez le compilateur par le nom approprié pour votre langage (par exemple g++pour C ++), vous obtiendrez des avertissements qui ne s'appliquent pas à ce langage (et le compilateur lèvera ses mains et refusera de continuer jusqu'à ce que vous supprimer l'avertissement).

Une autre chose est que j'ai ajouté -Werror, car si vous ne corrigez pas les avertissements, pourquoi vous souciez-vous de les activer? Vous pouvez également retirer les avertissements de la liste. (Par exemple, je n'utilise presque jamais -Waggregate-returnavec C ++.)

Certains avertissements ne feront rien sans d'autres options liées aux performances ( -Wstack-protector). -fdiagnostics-show-optionet le manuel GCC sont vos amis.

À propos, certains avertissements sont mutuellement exclusifs; en particulier en utilisant -Wtraditionalet -Wold-style-definitionavec -Werror, ne compilera pas.

Nathan Paul Simons
la source
0

Dans mon CmakeLists.txt de Clion

cmake_minimum_required(VERSION 3.13)
project(cpp17)

set(CMAKE_CXX_STANDARD 17)

set(GCC_COVERAGE_COMPILE_FLAGS "-std=c++17 -Wall -Weffc++ -Wno-error=effc++ -pedantic \
 -Weverything -Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-newline-eof  \
-pedantic-errors -Wextra -Waggregate-return -Wcast-align \
-Wcast-qual -Wconversion \
-Wdisabled-optimization \
-Werror -Wfloat-equal -Wformat=2 \
-Wformat-nonliteral -Wformat-security  \
-Wformat-y2k \
-Wimplicit  -Wimport  -Winit-self  -Winline -Winvalid-pch   \
-Wlong-long \
-Wmissing-field-initializers -Wmissing-format-attribute   \
-Wmissing-include-dirs -Wmissing-noreturn \
-Wpacked  -Wpadded -Wpointer-arith \
-Wredundant-decls \
-Wshadow -Wstack-protector \
-Wstrict-aliasing=2 -Wswitch-default \
-Wswitch-enum \
-Wunreachable-code -Wunused \
-Wunused-parameter \
-Wvariadic-macros \
-Wwrite-strings")


set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${GCC_COVERAGE_COMPILE_FLAGS}" )

add_executable(cpp17 main.cpp)
snr
la source