Ich bin ein Clang-Entwickler, der bei Google arbeitet. Bei Google haben wir die Diagnose von Clang (im Wesentlichen) allen unseren C ++ - Entwicklern zur Verfügung gestellt, und wir behandeln die Warnungen von Clang auch als Fehler. Als Clang-Entwickler und einer der größeren Benutzer von Clangs Diagnose werde ich versuchen, diese Flags zu beleuchten und zu erläutern, wie sie verwendet werden können. Beachten Sie, dass alles, was ich beschreibe, generisch für Clang gilt und nicht spezifisch für C, C ++ oder Objective-C.
TL; DR - Version: Bitte verwenden -Wall
und -Werror
bei einem Minimum an jedem neuen Code Sie entwickeln. Wir (die Compiler-Entwickler) fügen hier aus guten Gründen Warnungen hinzu: Sie finden Fehler. Wenn Sie eine Warnung finden, die Fehler für Sie entdeckt, aktivieren Sie diese ebenfalls. Versuchen Sie es hier -Wextra
mit ein paar guten Kandidaten. Wenn einer von ihnen zu laut ist, als dass Sie ihn gewinnbringend einsetzen könnten, melden Sie einen Fehler . Wenn Sie Code schreiben, der einen "offensichtlichen" Fehler enthält, der vom Compiler jedoch nicht gemeldet wurde, melden Sie einen Fehler.
Nun zur langen Version. Zunächst einige Hintergrundinformationen zu Warnflaggruppierungen. In Clang (und in begrenztem Umfang auch im GCC) gibt es viele "Warnungsgruppen". Einige, die für diese Diskussion relevant sind:
- Standardmäßig aktiviert: Diese Warnungen sind immer aktiviert, sofern Sie sie nicht ausdrücklich deaktivieren.
-Wall
: Dies sind die Warnungen , dass die Entwickler haben hohe sowohl das Vertrauen in ihrem Wert und eine niedrige Rate falsch-positiver.
-Wextra
: Dies sind Warnungen, von denen angenommen wird, dass sie wertvoll und vernünftig sind (dh sie sind nicht fehlerhaft), aber sie können hohe falsch-positive Raten oder allgemeine philosophische Einwände haben.
-Weverything
: Dies ist eine verrückte Gruppe, die buchstäblich jede
Warnung in Clang aktiviert. Verwenden Sie dies nicht für Ihren Code. Es ist ausschließlich für Clang-Entwickler gedacht oder um herauszufinden, welche Warnungen vorhanden sind .
Es gibt zwei Hauptkriterien, die oben erwähnt wurden und die Aufschluss darüber geben, welche Warnungen in Clang angezeigt werden. Der erste ist der potenzielle
Wert eines bestimmten Auftretens der Warnung. Dies ist der erwartete Vorteil für den Benutzer (Entwickler), wenn die Warnung ausgelöst wird und
ein Problem mit dem Code korrekt identifiziert wird.
Das zweite Kriterium ist die Idee von falsch positiven Berichten. Dies sind Situationen, in denen die Warnung im Code ausgelöst wird, das angegebene potenzielle Problem jedoch aufgrund des Kontexts oder einer anderen Einschränkung des Programms nicht auftritt. Der Code, über den gewarnt wurde, verhält sich tatsächlich korrekt. Dies ist besonders schlimm, wenn die Warnung niemals auf dieses Codemuster abfeuern sollte. Stattdessen führt ein Mangel an der Implementierung der Warnung dazu, dass sie dort ausgelöst wird.
Für Clang-Warnungen muss der Wert in Bezug auf die Korrektheit angegeben werden , nicht in Bezug auf Stil, Geschmack oder Kodierungskonventionen. Dies schränkt die Anzahl der verfügbaren Warnungen ein und schließt häufig angeforderte Warnungen aus, z. B. Warnungen, wenn {}
s nicht im gesamten Text einer if
Anweisung verwendet werden. Clang ist auch sehr unverträglich gegenüber falsch positiven Ergebnissen . Im Gegensatz zu den meisten anderen Compilern wird eine unglaubliche Vielzahl von Informationsquellen verwendet, um falsch positive Ergebnisse zu bereinigen, einschließlich der genauen Schreibweise des Konstrukts, des Vorhandenseins oder Fehlens von zusätzlichen () -, Cast- oder sogar Präprozessor-Makros!
Nehmen wir nun einige Warnungen aus der Praxis von Clang und sehen uns an, wie sie kategorisiert sind. Zunächst eine Standard-Ein-Warnung:
% 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.
Hier war keine Flagge erforderlich, um diese Warnung zu erhalten. Der Grund dafür ist, dass dieser Code niemals wirklich korrekt ist und der Warnung einen hohen Wert gibt. Die Warnung wird nur für Code ausgelöst, von dem Clang nachweisen kann, dass er in diesen Bereich fällt, und gibt ihm eine Null- Falsch-Positiv- Rate.
% 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 benötigt die -Wall
Flagge für diese Warnung. Der Grund dafür ist, dass es eine nicht triviale Menge an Code gibt, die (für gut oder schlecht) das Codemuster verwendet hat, vor dem wir warnen, um absichtlich einen nicht initialisierten Wert zu erzeugen. Philosophisch sehe ich darin keinen Grund, aber viele andere stimmen dem nicht zu, und die Realität dieses Meinungsunterschieds ist der Auslöser für die Warnung unter der
-Wall
Flagge. Es hat immer noch einen sehr hohen Wert und eine sehr niedrige
Falsch-Positiv- Rate, aber auf einigen Codebasen ist es kein Starter.
% 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.
Diese Warnung erfordert die -Wextra
Flagge. Der Grund ist, dass es sehr
große Codebasen gibt, in denen falsch zugeordnete Vorzeichen bei Vergleichen extrem häufig sind. Während diese Warnung einige Fehler findet, ist die Wahrscheinlichkeit, dass der Code ein Fehler ist, wenn der Benutzer ihn schreibt, im Durchschnitt ziemlich gering. Das Ergebnis ist eine extrem hohe Falsch-Positiv- Rate. Wenn jedoch aufgrund der seltsamen Regeln für die Werbung ein Fehler in einem Programm auftritt, ist es häufig äußerst subtil, diese Warnung zu erstellen,
wenn ein Fehler mit einem relativ hohen Wert gekennzeichnet wird . Infolgedessen stellt Clang es zur Verfügung und macht es unter einer Flagge sichtbar.
In der Regel leben Warnungen nicht lange außerhalb der -Wextra
Flagge. Clang bemüht sich sehr, keine Warnungen zu implementieren, die nicht regelmäßig verwendet und getestet werden. Die zusätzlichen Warnungen, die von aktiviert werden, -Weverything
sind normalerweise Warnungen, die sich in der aktiven Entwicklung oder bei aktiven Fehlern befinden. Entweder werden sie repariert und unter entsprechende Flaggen gesetzt, oder sie sollten entfernt werden.
Nachdem wir nun verstanden haben, wie diese Dinge mit Clang funktionieren, wollen wir versuchen, auf die ursprüngliche Frage zurückzukommen: Welche Warnungen sollten Sie für Ihre Entwicklung aktivieren? Die Antwort ist leider, dass es darauf ankommt. Berücksichtigen Sie die folgenden Fragen, um herauszufinden, welche Warnungen für Ihre Situation am besten geeignet sind.
- Haben Sie die Kontrolle über Ihren gesamten Code oder ist ein Teil davon extern?
- Was sind deine Ziele? Fehler abfangen oder besseren Code schreiben?
- Was ist Ihre falsch-positive Toleranz? Sind Sie bereit, zusätzlichen Code zu schreiben, um Warnungen regelmäßig auszuschalten?
Versuchen Sie in erster Linie nicht, zusätzliche Warnungen einzuschalten, wenn Sie den Code nicht kontrollieren. Seien Sie bereit, einige auszuschalten. Es gibt eine Menge schlechten Codes auf der Welt, und Sie können möglicherweise nicht alles reparieren. Das ist ok. Arbeiten Sie daran, wie Sie sich auf den Code konzentrieren können, den Sie steuern.
Finden Sie als Nächstes heraus, was Sie von Ihren Warnungen erwarten. Dies ist für verschiedene Menschen unterschiedlich. Clang wird versuchen, zu warnen, ohne Optionen für ungeheure Fehler oder Codemuster zu haben, für die wir einen langjährigen Präzedenzfall haben, der darauf hinweist, dass die Fehlerrate extrem hoch ist. Wenn -Wall
Sie diese Option aktivieren, erhalten Sie eine viel aggressivere Reihe von Warnungen, die darauf abzielen, die häufigsten Fehler abzufangen, die Clang-Entwickler im C ++ - Code beobachtet haben. Bei beiden sollte die
Falsch-Positiv- Rate jedoch recht niedrig bleiben.
Schließlich, wenn Sie vollkommen bereit sind, * falsch-positive * s an jeder Ecke zum Schweigen zu bringen, dann machen Sie mit -Wextra
. Melden Sie Fehler an, wenn Sie Warnungen bemerken, die viele echte Fehler enthalten, die aber dumme oder sinnlose Fehlalarme enthalten. Wir arbeiten ständig daran, Wege zu finden, um mehr und mehr von der vorhandenen Fehlerfindungslogik -Wextra
in -Wall
uns zu bringen, um Fehlalarme zu vermeiden.
Viele werden feststellen, dass keine dieser Optionen für sie genau richtig ist. Bei Google haben wir einige Warnungen -Wall
deaktiviert, da ein Großteil des vorhandenen Codes gegen die Warnung verstoßen hat. Wir haben auch einige Warnungen explizit aktiviert, obwohl sie von nicht aktiviert wurden -Wall
, da sie für uns einen besonders hohen Wert haben. Ihr Kilometerstand wird variieren, aber wahrscheinlich in ähnlicher Weise variieren. Es kann oft viel besser sein, ein paar wichtige Warnungen zu aktivieren, als alle
-Wextra
.
Ich würde jeden ermutigen , sich -Wall
für jeden Nicht-Legacy-Code einzuschalten. Für neuen Code sind die Warnungen hier fast immer wertvoll und verbessern die Erfahrung beim Entwickeln von Code. Umgekehrt würde ich jeden ermutigen, keine Flaggen darüber hinaus zu
aktivieren -Wextra
. Wenn Sie eine Clang Warnung finden , das -Wextra
nicht enthalten ist , aber das erweist sich als überhaupt wertvoll für Sie, einfach Fehler melden , und wir können es wahrscheinlich unter setzen -Wextra
. Ob Sie eine Teilmenge der Warnungen in explizit aktivieren, -Wextra
hängt stark von Ihrem Code, Ihrem Codierungsstil und davon ab, ob es einfacher ist, diese Liste zu pflegen, als alles zu reparieren, was nicht von abgedeckt wird -Wextra
.
Von der Liste der Warnungen des OP (die sowohl -Wall
als auch enthielten -Wextra
) werden nur die folgenden Warnungen von diesen beiden Gruppen nicht abgedeckt (oder standardmäßig aktiviert). Die erste Gruppe hebt hervor, warum es schlecht sein kann, sich zu sehr auf explizite Warnflags zu verlassen: Keine davon ist sogar in Clang implementiert ! Sie werden in der Befehlszeile nur aus Gründen der GCC-Kompatibilität akzeptiert.
-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
Die nächsten unnötigen Warnungen in der ursprünglichen Liste sind solche, die mit anderen in dieser Liste überflüssig sind:
-Wformat-nonliteral
- Teilmenge von -Wformat=2
-Wshorten-64-to-32
- Teilmenge von -Wconversion
-Wsign-conversion
- Teilmenge von -Wconversion
Es gibt auch eine Auswahl von Warnungen, die sich kategorisch unterscheiden. Diese befassen sich eher mit Sprachdialektvarianten als mit fehlerhaftem oder nicht fehlerhaftem Code. Mit Ausnahme von -Wwrite-strings
sind dies alle Warnungen für von Clang bereitgestellte Spracherweiterungen. Ob Clang vor ihrer Verwendung warnt, hängt von der Verbreitung der Erweiterung ab. Clang strebt die Kompatibilität mit GCC an und erleichtert dies in vielen Fällen durch implizite Spracherweiterungen, die häufig verwendet werden. -Wwrite-strings
Wie auf dem OP kommentiert, handelt es sich um ein Kompatibilitätsflag von GCC, das die Programmsemantik tatsächlich ändert. Ich bedaure diese Flagge zutiefst, aber wir müssen sie aufgrund ihres Erbes unterstützen.
-Wfour-char-constants
-Wpointer-arith
-Wwrite-strings
Die verbleibenden Optionen, die potenziell interessante Warnungen ermöglichen, sind folgende:
-Wcast-align
-Wconversion
-Wfloat-equal
-Wformat=2
-Wimplicit-atomic-properties
-Wmissing-declarations
-Wmissing-prototypes
-Woverlength-strings
-Wshadow
-Wstrict-selector-match
-Wundeclared-selector
-Wunreachable-code
Der Grund , dass diese nicht in -Wall
oder -Wextra
ist nicht immer klar. Für viele von ihnen, werden sie auf GCC Warnungen tatsächlich basiert ( -Wconversion
,
-Wshadow
usw.) und als solcher Clang versucht GCC Verhalten zu imitieren. Wir zerlegen einige davon langsam in feinkörnigere und nützlichere Warnungen. Diese haben dann eine höhere Wahrscheinlichkeit, es in eine der Warnungsgruppen der obersten Ebene zu schaffen. Dies -Wconversion
ist jedoch so weit gefasst, dass es auf absehbare Zeit wahrscheinlich seine eigene "oberste" Kategorie bleiben wird. Einige andere Warnungen, die der GCC hat, die aber einen geringen Wert und hohe falsch-positive Quoten haben, könnten in ein ähnliches Niemandsland verbannt werden.
Andere Gründe, warum diese nicht in einem der größeren Buckets enthalten sind, sind einfache Fehler, sehr signifikante falsch-positive Probleme und Warnungen während der Entwicklung. Ich werde nach Fehlern suchen, die ich identifizieren kann. Sie sollten alle irgendwann in eine richtige große Eimerfahne migrieren oder aus Clang entfernt werden.
Ich hoffe, dies verdeutlicht die Warnsituation mit Clang und gibt einen Einblick für diejenigen, die versuchen, eine Reihe von Warnungen für ihre Verwendung oder die Verwendung durch ihr Unternehmen auszuwählen.