web-dev-qa-db-fra.com

Drapeaux pour permettre des avertissements complets et verbeux de g ++

Souvent en C sous gcc, je commencerai par les drapeaux d'avertissement suivants (assemblés avec difficulté à partir de sources multiples):

-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 construirai (au moins mes versions de débogage) avec cet ensemble d'avertissements et corrigerai tout ce que je pourrai (généralement tout), puis ne retirerai les indicateurs que s'ils ne sont pas pertinents ou non réparables (presque jamais le cas). Parfois, j'ajoute aussi -Werror si je dois m'éloigner pendant la compilation.

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

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

104
Sdaz MacSkibbons

D'oh, toutes mes recherches initiales ont révélé 99% de messages sur la façon de supprimer avertissements (assez effrayants), mais je viens de tomber sur ce commentaire , qui contient cette jolie série de drapeaux (certains moins pertinents):

Croix vérifié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 ne savais pas que c'était une dupe, mais au moins c'était profondément enterré. :-)

35
Sdaz MacSkibbons

J'ai parcouru et trouvé un ensemble minimal d'inclusions qui devrait obtenir le niveau maximal d'avertissement. J'ai ensuite retiré de cette liste l'ensemble des avertissements qui, à mon avis, n'indiquent pas réellement que quelque chose de mauvais se produit ou qui contiennent trop de faux positifs pour pouvoir être utilisés dans une version réelle. J'ai commenté pourquoi chacun de ceux que j'ai exclus ont été exclus. Ceci est mon dernier ensemble 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-unused parce que j'ai souvent des variables que je saurai utiliser plus tard, mais pour lesquelles la fonctionnalité n'a pas encore été écrite. Supprimer les avertissements à ce sujet me permet d’écrire dans le style que je préfère, qui consiste parfois à différer la mise en œuvre de certaines choses. Il est utile de le désactiver de temps en temps pour s'assurer que rien ne passe entre les mailles du filet.

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

  • -Wfloat-equal avertit des comparaisons d'égalité sûres (en particulier, une 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. Je les ai donc mis à -1.0f (étant donné que mon problème utilise uniquement des nombres positifs, -1 est en dehors du domaine). Je vais plus tard et mettre à jour les valeurs -1.0f. Il ne se prête pas facilement à un mode de fonctionnement différent. Je soupçonne que la plupart des gens n’ont pas ce problème et que la comparaison d’un nombre exact en virgule flottante est probablement une erreur, je l’inclus donc dans la liste par défaut.

  • -Wold-style-cast a beaucoup de faux positifs dans le code de bibliothèque que j'utilise. En particulier, la famille de fonctions htonl utilisée dans les réseaux, ainsi que l’implémentation du chiffrement Rijndael (AES) que j’utilise ont des versions à l’ancienne dont elle me met en garde. J'ai l'intention de remplacer les deux, mais je ne suis pas sûr s'il y a quelque chose d'autre dans mon code dont il va se plaindre. La plupart des utilisateurs devraient toutefois l'avoir 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 quantité énorme d'avertissements (plus de 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 en le divisant (ce qui n'est pas sûr, contrairement à l'addition, la soustraction et la multiplication). L'activation de cet avertissement m'a permis de modifier en toute sécurité la plupart de mes variables en types non signés et d'ajouter quelques transformations à d'autres endroits. Il est actuellement un peu difficile à utiliser car l'avertissement n'est pas si malin. Par exemple, si vous faites unsigned short + (integral constant expression), ce résultat est implicitement promu en int. Il vous avertit ensuite d'un problème de signe potentiel si vous affectez cette valeur à unsigned ou unsigned short, même si c'est sûr. C'est certainement l'avertissement le plus facultatif pour presque tous les utilisateurs.

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

  • -Wswitch-default semble inutile (vous ne voulez pas toujours de cas par défaut si vous avez explicitement énuméré toutes les possibilités). Cependant, l'activation de cet avertissement peut forcer l'application de quelque chose qui est probablement une bonne idée. Dans les cas où vous souhaitez explicitement tout ignorer à l'exception des possibilités énumérées (mais d'autres nombres sont possibles), saisissez default: break; pour le rendre explicite. Si vous énumérez explicitement toutes les possibilités, l'activation de cet avertissement vous aidera à vous assurer que vous mettez quelque chose comme assert (false) afin de vous assurer que vous avez réellement couvert toutes les options possibles. Il vous permet d’être explicite sur le domaine de votre problème et de le mettre en œuvre par programme. Cependant, vous devrez faire attention en collant juste (faux) 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 release. En d’autres termes, vous ne pouvez pas vous fier à elle pour valider des numéros provenant d’une connexion réseau ou d’une base de données sur laquelle vous n’exercez aucun contrôle absolu. Les exceptions ou les retours anticipés sont le meilleur moyen de gérer cela (mais vous devez tout de même avoir un cas par défaut!).

  • -Werror est important pour moi. Lors de la compilation de grandes quantités de code dans une construction multithread avec plusieurs cibles, il est facile de laisser passer un avertissement. En transformant les avertissements en erreurs, je les remarque.

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

Avertissements absents:

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

  • -Waggregate-return n'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 en atténuer les effets négatifs.

  • -Wconversion se déclenche sur ce code: short n = 0; n += 2; La conversion implicite en int provoque un avertissement lorsqu'elle est ensuite reconvertie dans son type cible.

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

  • -Winline est absent car je n'utilise pas le mot clé inline à des fins d'optimisation, mais uniquement pour définir des fonctions inline dans les en-têtes. Je ne me soucie pas de savoir si l'optimiseur le met en ligne. Cet avertissement se plaint également s'il ne peut pas insérer en ligne une fonction déclarée dans un corps de classe (tel qu'un destructeur virtuel vide).

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

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

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

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

  • -Wpadded est activé occasionnellement pour optimiser la disposition des classes, mais il n'est pas laissé activé car toutes les classes ne possèdent pas suffisamment d'éléments pour supprimer le remplissage à la fin. En théorie, je pourrais obtenir des variables supplémentaires pour "gratuit", mais cela ne vaut pas la peine de maintenir cet effort supplémentaire (si la taille de ma classe change, il n'est pas facile de supprimer ces variables précédemment gratuites).

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

  • -Wstrict-aliasing=3 est activé par -Wall et 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 il entraîne un plus grand nombre de faux positifs. Mon propre code de test a été compilé proprement sous les 3 niveaux.

  • -Wswitch-enum n'est pas un comportement que je veux. Je ne veux pas gérer chaque déclaration de commutateur explicitement. Il serait utile que le langage dispose d'un mécanisme pour l'activer sur des instructions switch spécifiées (afin de s'assurer que les modifications futures de l'énum sont gérées partout où elles doivent l'être), mais il est excessif de définir un paramètre "tout ou rien".

  • -Wunsafe-loop-optimizations provoque trop d'avertissements parasites. 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 parcouru tous les éléments d'un vecteur pour leur appliquer un ensemble de fonctions (à l'aide de la boucle for basée sur l'intervalle). C'est aussi un avertissement pour le constructeur d'un tableau const de const std :: string (où il n'y a pas de boucle dans le code utilisateur).

  • -Wzero-as-null-pointer-constant et -Wuseless-cast sont des avertissements réservés à GCC-4.7, que j'ajouterai lors de la transition vers GCC 4.7.

Nous avons déposé quelques rapports de bogues/demandes d'amélioration auprès de gcc à la suite de certaines de ces recherches. J'espère pouvoir ajouter éventuellement d'autres avertissements de la liste "ne pas inclure" à la liste "d'inclure". . Cette liste comprend tous les avertissements mentionnés dans ce fil de discussion (plus, je pense, quelques suppléments). Un grand nombre des avertissements non explicitement mentionnés dans cet article font partie d'un autre avertissement que je mentionne. Si quelqu'un remarque des avertissements qui sont totalement exclus de cet article, faites-le-moi savoir.

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

119
David Stone

Certains d'entre eux sont déjà inclus dans -Wall ou -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++

(ignorer -Werror pour C++ car -Weffc++ a quelques inconvénients)

11
Let_Me_Be

Essayer

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

C'est un début rapide et sale qui nécessitera certainement quelques ajustements; D'une part, même si vous appelez le compilateur avec le nom approprié pour votre langage (par exemple, g++ pour C++), vous recevrez des avertissements qui ne s'appliquent pas à ce langage (et le compilateur lève les mains et refuse de continuer vous supprimez l'avertissement).

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

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

À propos, certains avertissements s’excluent mutuellement; en particulier, utiliser -Wtraditional et -Wold-style-definition avec -Werror ne compilera pas.

2

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)
0
snr