GCC 7, -Wimplicit-Fallthrough-Warnungen und tragbare Möglichkeit, sie zu löschen?
Lesezeit: 6 Minuten
Wir erhalten Warnungen von GCC 7 für implizites Durchfallen in einer switch-Anweisung. Zuvor haben wir sie unter Clang gelöscht (das ist der Grund für den unten stehenden Kommentar):
g++ -DNDEBUG -g2 -O3 -std=c++17 -Wall -Wextra -fPIC -c authenc.cpp
asn.cpp: In member function ‘void EncodedObjectFilter::Put(const byte*, size_t)’:
asn.cpp:359:18: warning: this statement may fall through [-Wimplicit-fallthrough=]
m_state = BODY; // fall through
^
asn.cpp:361:3: note: here
case BODY:
^~~~
Das GCC-Handbuch Staaten zu verwenden __attribute__ ((fallthrough)), aber es ist nicht tragbar. Das Handbuch sagt auch “… es ist auch möglich, einen Fallthrough-Kommentar hinzuzufügen, um die Warnung stumm zu schalten.”aber es bietet nur FALLTHRU (Ist das wirklich die einzige Möglichkeit?):
switch (cond)
{
case 1:
bar (0);
/* FALLTHRU */
default:
…
}
Gibt es eine tragbare Möglichkeit, die Fall-Through-Warnung für Clang und GCC zu löschen? Wenn ja, was ist es dann?
Danke Richard. Leider NEIN, wir sind derzeit keine Attribute. Wir unterstützen immer noch zurück zu C++03. -std=c++17 testet nur eine Konfiguration unter Fedora 26, weil es GCC 7 bereitstellt. Aber ich würde ein Makro verwenden, um es für die Portabilität zu abstrahieren.
Danke @BaummitAugen – Ja, das könnte wahrscheinlich funktionieren. Weißt du zufällig ob __has_feature(x) funktioniert dafür? Reicht es zum Testen __has_feature(fallthrough)? Oder müssen wir dies mit Compiler-Versionstests tun? Oder vielleicht etwas anderes?
– jww
16. Juli 2017 um 15:20 Uhr
@BaummitAugen – Mein Fehler, wir verwenden Boost nicht. Ich muss ein gleichwertiges Makro von Grund auf neu erstellen. Darum ging es bei den Zusatzfragen.
– jww
16. Juli 2017 um 15:28 Uhr
Florian Weimer
GCC erwartet den Marker-Kommentar in einer eigenen Zeile, etwa so:
m_state = BODY;
// fall through
case BODY:
Der Marker muss auch direkt vor dem kommen case Etikette; es darf keine schließende geschweifte Klammer dazwischen sein }.
C++17 fügt a [[fallthrough]] Attribut, mit dem solche Warnungen unterdrückt werden können. Beachten Sie das abschließende Semikolon:
m_state = BODY;
[[fallthrough]];
case BODY:
Clang unterstützt -Wimplicit-fallthrough Warnungen, aktiviert sie jedoch nicht als Teil von -Wall oder -Wextra. Clang erkennt keine Kommentarmarken, daher muss dafür die attributbasierte Unterdrückung verwendet werden (was derzeit die Nicht-Standard __attribute__((fallthrough)) Konstrukt für das C-Frontend).
Beachten Sie, dass das Unterdrücken der Warnung mit Markierungskommentaren nur funktioniert, wenn der Compiler den Kommentar tatsächlich sieht. Wenn der Präprozessor separat läuft, muss er angewiesen werden, Kommentare beizubehalten, wie bei der -C Option von GCC. Zum Beispiel, um falsche Warnungen mit zu vermeiden Cachemüssen Sie die angeben -C Flag beim Kompilieren, oder verwenden Sie bei neueren Versionen von ccache das keep_comments_cpp Möglichkeit.
Danke Florian. Ich habe GCC 7 auf Fedora 26 ausprobiert (gcc (GCC) 7.1.1 20170622 (Red Hat 7.1.1-3)). Ziehen um // fall through nach unten, wie in Ihrem Beispiel gezeigt, noch die Warnung erzeugt. Hier ist die eigentliche Quelldatei, falls sie benötigt wird: asn.cpp. Wenn es darauf ankommt, benutze ich -std=c++17.
– jww
17. Juli 2017 um 7:47 Uhr
Wo genau hast du den Kommentar platziert? Vor oder nach dem }? Sie müssen es unmittelbar vor dem auf der Linie platzieren case Stichwort.
– Florian Weimer
17. Juli 2017 um 8:08 Uhr
Nochmals vielen Dank Florian. Es scheint, dass andere einige Probleme mit der Implementierung von GCC haben. Sehen -Wimplicit-Fallthrough defekt? in der GCC-Hilfeliste.
– jww
21. Juli 2017 um 11:45 Uhr
Zu Ihrer Information: Die Option -save-temps unterbricht die Kommentarerkennungsheuristik. Die Warnung wird in diesem Fall nicht unterdrückt
– Patrick Schlüter
1. Februar 2018 um 13:52 Uhr
Obwohl Fallthrough-Kommentare portabel sein können, sind Kommentare im Code so konzipiert, dass sie den Präprozessor nicht durchlaufen, und mit einem Tool wie ccache, das die Präprozessorausgabe verwendet, werden solche Kommentare entfernt, bevor die vorverarbeitete Ausgabe zur Kompilierung an gcc gesendet wird . Wenn Sie also Ccache verwenden, werden Sie diese Warnungen weiterhin sehen.
– Blauer Dämon
1. Juni 2018 um 20:32 Uhr
Ciro Santilli Путлер Капут 六四事
C++17 [[fallthrough]]
Beispiel:
int main(int argc, char **argv) {
switch (argc) {
case 0:
argc = 1;
[[fallthrough]];
case 1:
argc = 2;
};
}
Kompilieren mit:
g++ -std=c++17 -Wimplicit-fallthrough main.cpp
Wenn Sie die entfernen [[fallthrough]];GCC warnt:
main.cpp: In function ‘int main()’:
main.cpp:5:15: warning: this statement may fall through [-Wimplicit-fallthrough=]
argc = 1;
~~^~~
main.cpp:6:9: note: here
case 1:
^~~~
Beachten Sie aus dem Beispiel auch, dass die Warnung nur erfolgt, wenn Sie auf zwei Fälle stoßen: die letzte case-Anweisung (case 1 hier) generiert keine Warnungen, obwohl es keine gibt break.
Die folgenden Konstrukte erzeugen die Warnung ebenfalls nicht:
#include <cstdlib>
[[noreturn]] void my_noreturn_func() {
exit(1);
}
int main(int argc, char **argv) {
// Erm, an actual break
switch (argc) {
case 0:
argc = 1;
break;
case 1:
argc = 2;
}
// Return also works.
switch (argc) {
case 0:
argc = 1;
return 0;
case 1:
argc = 2;
}
// noreturn functions are also work.
// https://stackoverflow.com/questions/10538291/what-is-the-point-of-noreturn/47444782#47444782
switch (argc) {
case 0:
argc = 1;
my_noreturn_func();
case 1:
argc = 2;
}
// Empty case synonyms are fine.
switch (argc) {
case 0:
case 1:
argc = 2;
}
// Magic comment mentioned at:
// https://stackoverflow.com/a/45137452/895245
switch (argc) {
case 0:
argc = 1;
// fall through
case 1:
argc = 2;
}
switch (argc) {
// GCC extension for pre C++17.
case 0:
argc = 1;
__attribute__ ((fallthrough));
case 1:
argc = 2;
}
switch (argc) {
// GCC examines all braches.
case 0:
if (argv[0][0] == 'm') {
[[fallthrough]];
} else {
return 0;
}
case 1:
argc = 2;
}
}
Aus dem letzten können wir ersehen, dass GCC alle möglichen Zweige untersucht und warnt, wenn keiner davon vorhanden ist [[fallthrough]]; oder break oder return.
#if __has_attribute(__fallthrough__)
# define fallthrough __attribute__((__fallthrough__))
#else
# define fallthrough do {} while (0) /* fallthrough */
#endif
MCCCS
Saubere C-Lösung:
int r(int a) {
switch(a) {
case 0:
a += 3;
case 1:
a += 2;
default:
a += a;
}
return a;
}
wird:
int h(int a) {
switch(a) {
case 0:
a += 3;
goto one;
case 1:
one:
a += 2;
goto others;
default:
others:
a += a;
}
return a;
}
BEARBEITEN: Die Beschriftungen wurden nach Fallaussagen verschoben, wie von Stéphane Gourichon in Kommentaren vorgeschlagen, um den Fallthrough leichter zu erkennen.
stefankt
Niemand hat erwähnt, dass die Warnung vollständig deaktiviert wurde, und dies ist möglicherweise nicht die Antwort, nach der das OP gesucht hat, aber ich denke, sie sollte der Vollständigkeit halber aufgenommen werden, da sie auch für beide Compiler funktioniert:
-Wno-implicit-fallthrough
Wenn Sie aus irgendeinem Grund nicht in der Lage sind, den Quellcode zu ändern, bleibt die Kompilierausgabe sauber, was einen klaren Blick auf andere Probleme ermöglicht (aber natürlich muss man sich darüber im Klaren sein, was man verliert).
Wenn es eine Sache gibt, die ärgerlicher ist als kein Versehen, dann ist es ein übertriebenes Versehen, das durch einen schlechten Regelsatz ermöglicht wird. Compiler-Warnungen sind ein solches Beispiel.
– stefankt
7. April um 12:25 Uhr
Wenn es eine Sache gibt, die ärgerlicher ist als kein Versehen, dann ist es ein übertriebenes Versehen, das durch einen schlechten Regelsatz ermöglicht wird. Compiler-Warnungen sind ein solches Beispiel.
– stefankt
7. April um 12:25 Uhr
10120800cookie-checkGCC 7, -Wimplicit-Fallthrough-Warnungen und tragbare Möglichkeit, sie zu löschen?yes
Wie Sie C++17 verwenden, siehe Attribut
[[fallthrough]];
(Anmerkung – benötigt die;
) Quelle: en.cppreference.com/w/cpp/language/attributes– Richard Critten
16. Juli 2017 um 14:41 Uhr
Danke Richard. Leider NEIN, wir sind derzeit keine Attribute. Wir unterstützen immer noch zurück zu C++03.
-std=c++17
testet nur eine Konfiguration unter Fedora 26, weil es GCC 7 bereitstellt. Aber ich würde ein Makro verwenden, um es für die Portabilität zu abstrahieren.– jww
16. Juli 2017 um 14:50 Uhr
Vielleicht
BOOST_FALLTHROUGH
macht was du brauchst. boost.org/doc/libs/master/libs/config/doc/html/boost_config/…– Baum mit Augen
♦
16. Juli 2017 um 15:06 Uhr
Danke @BaummitAugen – Ja, das könnte wahrscheinlich funktionieren. Weißt du zufällig ob
__has_feature(x)
funktioniert dafür? Reicht es zum Testen__has_feature(fallthrough)
? Oder müssen wir dies mit Compiler-Versionstests tun? Oder vielleicht etwas anderes?– jww
16. Juli 2017 um 15:20 Uhr
@BaummitAugen – Mein Fehler, wir verwenden Boost nicht. Ich muss ein gleichwertiges Makro von Grund auf neu erstellen. Darum ging es bei den Zusatzfragen.
– jww
16. Juli 2017 um 15:28 Uhr