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?

  • 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


Benutzer-Avatar
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 }.

fall through gehört zu den von GCC anerkannten Markern. Es ist nicht nur FALLTHRU. Eine vollständige Liste finden Sie in der Dokumentation der -Wimplicit-fallthrough Möglichkeit. Siehe auch dies Posting im Red Hat Developer Blog.

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

Benutzer-Avatar
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.

Möglicherweise möchten Sie auch die Verfügbarkeit von Funktionen mit Makros wie in überprüfen dieses von GEM5 inspirierte Snippet:

#if defined __has_cpp_attribute
    #if __has_cpp_attribute(fallthrough)
        #define MY_FALLTHROUGH [[fallthrough]]
    #else
        #define MY_FALLTHROUGH
    #endif
#else
    #define MY_FALLTHROUGH
#endif

Siehe auch: https://en.cppreference.com/w/cpp/language/attributes/fallthrough

Getestet auf GCC 7.4.0, Ubuntu 18.04.

Siehe auch

C-Version dieser Frage: So führen Sie einen expliziten Fall-Through in C durch

Ein weiteres Beispiel: Der Linux-Kernel stellt eine fallthrough Pseudo-Keyword-Makro. Was verwendet werden kann als:

switch (cond) {
case 1:
    foo();
    fallthrough;
case 2:
    bar();
    break;
default:
    baz();
}

Im Kern v5.10 es ist so implementiert:

#if __has_attribute(__fallthrough__)
# define fallthrough                    __attribute__((__fallthrough__))
#else
# define fallthrough                    do {} while (0)  /* fallthrough */
#endif

Benutzer-Avatar
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.

Benutzer-Avatar
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

1012080cookie-checkGCC 7, -Wimplicit-Fallthrough-Warnungen und tragbare Möglichkeit, sie zu löschen?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy