Pour le contexte, je suis un développeur Clang travaillant chez Google. Chez Google, nous avons étendu les diagnostics de Clang à (essentiellement) tous nos développeurs C ++, et nous traitons également les avertissements de Clang comme des erreurs. En tant que développeur Clang et l'un des principaux utilisateurs des diagnostics de Clang, je vais essayer de faire la lumière sur ces indicateurs et sur la manière dont ils peuvent être utilisés. Notez que tout ce que je décris est génériquement applicable à Clang, et non spécifique à C, C ++ ou Objective-C.
TL; DR Version: Veuillez utiliser -Wall
et -Werror
au minimum tout nouveau code que vous développez. Nous (les développeurs du compilateur) ajoutons ici des avertissements pour de bonnes raisons: ils trouvent des bogues. Si vous trouvez un avertissement qui attrape des bugs pour vous, activez-le également. Essayez d' -Wextra
avoir un groupe de bons candidats ici. Si l’un d’eux est trop bruyant pour que vous l’utilisiez de manière rentable, signalez un bogue . Si vous écrivez du code contenant un bogue "évident" mais que le compilateur ne vous en a pas averti, créez un bogue.
Maintenant pour la version longue. Tout d'abord quelques informations sur les groupes d'indicateurs d'avertissement. Il y a beaucoup de "groupements" d'avertissements dans Clang (et dans une moindre mesure dans GCC). Certains qui sont pertinents pour cette discussion:
- Activé par défaut: ces avertissements sont toujours activés, sauf si vous les désactivez explicitement.
-Wall
: Ce sont des avertissements que les développeurs ont une grande confiance dans leur valeur et un faible taux de faux positifs.
-Wextra
: Ce sont des avertissements qui sont considérés comme précieux et valables (c’est-à-dire qu’ils ne sont pas buggés), mais ils peuvent présenter des taux de faux positifs élevés ou des objections philosophiques communes.
-Weverything
: Ceci est un groupe insensé qui active littéralement tous les
avertissements dans Clang. Ne l'utilisez pas dans votre code. Il est destiné uniquement aux développeurs Clang ou à l'exploration des avertissements existants .
Il existe deux critères principaux mentionnés ci-dessus qui guident les avertissements dans Clang, et clarifions leur signification. Le premier est la valeur potentielle
d'une occurrence particulière de l'avertissement. C'est l'avantage attendu par l'utilisateur (développeur) lorsque l'avertissement se déclenche et qui
identifie correctement un problème avec le code.
Le deuxième critère est l’idée de déclarations faussement positives . Ce sont des situations où l'avertissement se déclenche sur le code, mais le problème potentiel évoqué ne se produit en fait pas à cause du contexte ou d'une autre contrainte du programme. Le code sur lequel on vous a prévenu se comporte correctement. Celles-ci sont particulièrement dommageables lorsque l'avertissement n'a jamais été conçu pour déclencher ce code. Au lieu de cela, c'est une déficience dans la mise en œuvre de l'alerte qui la déclenche là.
Pour les avertissements Clang, la valeur doit être exprimée en termes d' exactitude , et non en termes de style, de goût ou de conventions de codage. Cela limite l'ensemble des avertissements disponibles, en excluant les avertissements souvent demandés tels que les avertissements lorsque {}
aucun s n'est utilisé autour du corps d'une if
instruction. Clang est également très intolérant envers les faux positifs . Contrairement à la plupart des autres compilateurs, il utilisera une incroyable variété de sources d’information pour élaguer les faux positifs, notamment l’orthographe exacte de la construction, la présence ou non de macros «()» supplémentaires, ou même de préprocesseurs!
Prenons maintenant des exemples concrets d’avertissements de Clang et examinons leur classement. Tout d'abord, un avertissement par défaut:
% nl x.cc
1 class C { const int x; };
% clang -fsyntax-only x.cc
x.cc:1:7: warning: class 'C' does not declare any constructor to initialize its non-modifiable members
class C { const int x; };
^
x.cc:1:21: note: const member 'x' will never be initialized
class C { const int x; };
^
1 warning generated.
Ici, aucun drapeau n'était requis pour obtenir cet avertissement. La raison en est que ce code n’est jamais vraiment correct, ce qui donne une valeur élevée à l’avertissement , et cet avertissement ne déclenche que le code que Clang peut prouver tombe dans ce compartiment, ce qui lui donne un taux de zéro faux positif .
% nl x2.cc
1 int f(int x_) {
2 int x = x;
3 return x;
4 }
% clang -fsyntax-only -Wall x2.cc
x2.cc:2:11: warning: variable 'x' is uninitialized when used within its own initialization [-Wuninitialized]
int x = x;
~ ^
1 warning generated.
Clang requiert le -Wall
drapeau pour cet avertissement. La raison en est qu’il existe une quantité non négligeable de code qui a utilisé (pour le meilleur ou pour le pire) le modèle de code sur lequel nous avertissons de produire intentionnellement une valeur non initialisée. Philosophiquement, je ne vois pas l'intérêt de cela, mais beaucoup d'autres sont en désaccord et la réalité de cette divergence d'opinion est ce qui motive l'avertissement sous le
-Wall
drapeau. Il a toujours une valeur très élevée et un taux de faux positifs très bas
, mais sur certains codes, il est non partant.
% nl x3.cc
1 void g(int x);
2 void f(int arr[], unsigned int size) {
3 for (int i = 0; i < size; ++i)
4 g(arr[i]);
5 }
% clang -fsyntax-only -Wextra x3.cc
x3.cc:3:21: warning: comparison of integers of different signs: 'int' and 'unsigned int' [-Wsign-compare]
for (int i = 0; i < size; ++i)
~ ^ ~~~~
1 warning generated.
Cet avertissement nécessite le -Wextra
drapeau. La raison en est qu’il existe de très
grandes bases de code où les comparaisons de signatures mal appariées sont extrêmement courantes. Bien que cet avertissement trouve des bogues, la probabilité que le code soit un bogue lorsque l'utilisateur l'écrit est en moyenne assez faible. Le résultat est un taux extrêmement élevé de faux positifs . Cependant, lorsqu'un programme contient un bogue en raison d'étranges règles de promotion, il est souvent extrêmement subtil de rendre cet avertissement
lorsqu'il signale qu'un bogue a une valeur relativement élevée . En conséquence, Clang le fournit et l’expose sous un drapeau.
Généralement, les avertissements ne survivent pas longtemps en dehors du -Wextra
drapeau. Clang essaie très fort de ne pas mettre en œuvre des avertissements qui ne sont pas régulièrement utilisés et testés. Les avertissements supplémentaires activés par -Weverything
sont généralement des avertissements en développement actif ou avec des bogues actifs. Soit ils seront fixés et placés sous des drapeaux appropriés, soit ils devraient être supprimés.
Maintenant que nous comprenons comment ces choses fonctionnent avec Clang, essayons de revenir à la question initiale: quels avertissements devriez-vous activer pour votre développement? La réponse est, malheureusement, que cela dépend. Réfléchissez aux questions suivantes pour déterminer les avertissements les mieux adaptés à votre situation.
- Avez-vous le contrôle de tout votre code, ou est-ce que certains d'entre eux sont externes?
- Quels sont vos objectifs? Attraper des bugs ou écrire un meilleur code?
- Quelle est votre tolérance faussement positive? Êtes-vous disposé à écrire du code supplémentaire pour faire taire les avertissements régulièrement?
Tout d'abord, si vous ne contrôlez pas le code, n'essayez pas d'activer des avertissements supplémentaires. Préparez-vous à en éteindre. Il y a beaucoup de mauvais codes dans le monde, et vous ne pourrez peut-être pas tout réparer. C'est bon. Travaillez pour trouver un moyen de concentrer vos efforts sur le code que vous contrôlez.
Ensuite, déterminez ce que vous voulez sortir de vos avertissements. Ceci est différent pour différentes personnes. Clang essaiera d’avertir sans aucune option pour les bogues évidents ou les modèles de code pour lesquels nous avons un précédent historique qui indique que le taux de bogues est extrêmement élevé. En activant cette fonctionnalité, -Wall
vous obtiendrez un ensemble d'avertissements beaucoup plus agressif visant à détecter les erreurs les plus courantes observées par les développeurs Clang dans le code C ++. Mais avec ces deux facteurs, le
taux de faux positifs devrait rester assez faible.
Enfin, si vous êtes parfaitement disposé à faire taire les * faux-positifs * à chaque tour, foncez -Wextra
. Si vous remarquez des avertissements qui attirent de nombreux bogues réels, mais qui ont des faux positifs stupides ou inutiles, vous pouvez créer des bogues. Nous travaillons constamment pour trouver des moyens d'introduire de plus en plus de la logique de recherche de bogues -Wextra
dans -Wall
laquelle nous pouvons éviter les faux positifs.
Beaucoup trouveront qu'aucune de ces options n'est juste pour eux. Chez Google, certains avertissements ont été -Wall
désactivés, car de nombreux codes existants ne respectaient pas cet avertissement. Nous avons également activé explicitement certains avertissements, même s'ils ne sont pas activés par -Wall
, car ils ont une valeur particulièrement élevée pour nous. Votre kilométrage variera, mais variera probablement de la même manière. Il peut souvent être préférable d’activer quelques avertissements clés plutôt que tous
-Wextra
.
J'encourage tout le monde à activer le -Wall
code non hérité. Pour les nouveaux codes, les avertissements ici sont presque toujours précieux et améliorent réellement l'expérience de développement de code. Inversement, j'encourage tout le monde à
ne pas autoriser les drapeaux au-delà -Wextra
. Si vous trouvez un avertissement de Clang qui -Wextra
ne comprend pas , mais qui prouve tout précieux pour vous, déposer simplement un bug et nous pouvons probablement le mettre sous -Wextra
. Que vous activiez explicitement un sous-ensemble des avertissements dans -Wextra
dépendra beaucoup de votre code, de votre style de codage et de la pertinence de la gestion de cette liste plutôt que de tout réparer -Wextra
.
Parmi la liste d'avertissements de l'OP (qui incluait les deux -Wall
et -Wextra
), seuls les avertissements suivants ne sont pas couverts par ces deux groupes (ou activés par défaut). Le premier groupe explique pourquoi le recours excessif à des indicateurs d'avertissement explicites peut être mauvais: aucun de ceux-ci n'est même implémenté dans Clang! Ils sont acceptés sur la ligne de commande uniquement pour la compatibilité GCC.
-Wbad-function-cast
-Wdeclaration-after-statement
-Wmissing-format-attribute
-Wmissing-noreturn
-Wnested-externs
-Wnewline-eof
-Wold-style-definition
-Wredundant-decls
-Wsequence-point
-Wstrict-prototypes
-Wswitch-default
Les prochains avertissements inutiles dans la liste d'origine sont ceux qui sont redondants avec ceux de cette liste:
-Wformat-nonliteral
-- Sous-ensemble de -Wformat=2
-Wshorten-64-to-32
-- Sous-ensemble de -Wconversion
-Wsign-conversion
-- Sous-ensemble de -Wconversion
Il existe également une sélection d'avertissements plus catégoriquement différents. Celles-ci traitent de variantes linguistiques du dialecte plutôt que de codes bogués ou non bogués. À l'exception de -Wwrite-strings
, tous ces avertissements concernent les extensions de langage fournies par Clang. Que Clang avertisse de leur utilisation dépend de la prévalence de l'extension. Clang vise la compatibilité GCC et, dans de nombreux cas, simplifie ainsi la tâche avec des extensions de langage implicites largement utilisées. -Wwrite-strings
, comme indiqué dans l'OP, est un indicateur de compatibilité de GCC qui modifie réellement la sémantique du programme. Je regrette profondément ce drapeau, mais nous devons le soutenir en raison de l'héritage qu'il a aujourd'hui.
-Wfour-char-constants
-Wpointer-arith
-Wwrite-strings
Les options restantes permettant des avertissements potentiellement intéressants sont les suivantes:
-Wcast-align
-Wconversion
-Wfloat-equal
-Wformat=2
-Wimplicit-atomic-properties
-Wmissing-declarations
-Wmissing-prototypes
-Woverlength-strings
-Wshadow
-Wstrict-selector-match
-Wundeclared-selector
-Wunreachable-code
La raison pour laquelle ils ne sont pas -Wall
ou -Wextra
ne sont pas toujours clairs. Pour beaucoup d' entre eux, ils sont en fait basés sur les avertissements du CCG ( -Wconversion
,
-Wshadow
, etc.) et en tant que telle Clang tente d'imiter le comportement de GCC. Nous en décomposons progressivement certaines en des mises en garde plus fines et utiles. Ceux-ci ont alors une probabilité plus élevée de faire partie de l’un des groupes d’alerte les plus avancés. Cela dit, choisir un seul avertissement -Wconversion
est si vaste qu'il restera probablement sa propre catégorie de "premier niveau" dans un avenir prévisible. Certains autres avertissements dont dispose GCC mais qui ont une faible valeur et des taux de faux positifs élevés peuvent être relégués au rang de no man's land.
Parmi les autres raisons pour lesquelles ils ne font pas partie des plus grands compartiments, citons les bogues simples, les très importants problèmes de faux positifs et les avertissements en cours de développement. Je vais examiner le classement des bogues pour ceux que je peux identifier. Ils devraient tous éventuellement migrer vers un grand drapeau de seau approprié ou être retirés de Clang.
J'espère que cela clarifie la situation d'avertissement avec Clang et fournit quelques informations à ceux qui essaient de choisir un ensemble d'avertissements pour leur utilisation ou l'utilisation de leur entreprise.