海湾合作委员会第7号, - 明显的通过警告,以及清除它们的便携方式?

jww*_*jww 31 c++ gcc warnings switch-statement

我们正在接受GCC 7的警告,因为它在switch语句中是隐含的.以前,我们在Clang下清除它们(这是下面评论的原因):

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:
   ^~~~
Run Code Online (Sandbox Code Playgroud)

GCC手册状态使用__attribute__ ((fallthrough)),但它不便于携带.该手册还指出"...也可以添加一个通过注释来消除警告",但它只提供FALLTHRU(这真的是唯一的选择吗?):

switch (cond)
  {
  case 1:
    bar (0);
    /* FALLTHRU */
  default:
    …
  }
Run Code Online (Sandbox Code Playgroud)

对于Clang和GCC,是否有通过警告来清除坠落的便携方法?如果是的话那么它是什么?

Flo*_*mer 36

海湾合作委员会希望标记评论在自己的行上,如下所示:

  m_state = BODY;
  // fall through
case BODY:
Run Code Online (Sandbox Code Playgroud)

标记也必须在case标签前面; 没有干预的闭合支撑}.

fall through是GCC认可的标志之一.这不仅仅是FALLTHRU.有关完整列表,请参阅该-Wimplicit-fallthrough选项的文档.另请参阅Red Hat Developer博客上的这篇帖子.

(这也应该与Clang兼容,虽然我无法通过当前主干(r308163)发出切换 - 通过警告来验证这一点.)

请注意,仅当编译器实际看到注释时,才使用带标记注释的警告.如果预处理器单独运行,则需要指示它保留注释,与-Wimplicit-fallthroughGCC选项一样.例如,要避免使用ccache发出虚假警告,您需要-Wall在编译时指定标志,或者使用最新版本的ccache使用该-Wextra选项.


Cir*_*四事件 8

C ++ 17 [[fallthrough]]

例:

int main(int argc, char **argv) {
    switch (argc) {
        case 0:
            argc = 1;
            [[fallthrough]];
        case 1:
            argc = 2;
    };
}
Run Code Online (Sandbox Code Playgroud)

编译:

g++ -std=c++17 -Wimplicit-fallthrough main.cpp
Run Code Online (Sandbox Code Playgroud)

如果删除[[fallthrough]];,则GCC警告:

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:
         ^~~~
Run Code Online (Sandbox Code Playgroud)

还要从示例中注意到,警告仅在您遇到两种情况时才会发生:最后一个case语句(case 1此处)即使没有,也不会生成警告break

以下构造也不会生成警告:

#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.
    // /sf/ask/737680401/#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:
    // /sf/answers/3159621671/
    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;
    }
}
Run Code Online (Sandbox Code Playgroud)

从最后一个可以看出,GCC会检查所有可能的分支,并警告它们中的任何一个都不具有[[fallthrough]];or break或or return

您可能还想使用此GEM5启发性代码段来检查宏的功能可用性:

#if defined __has_cpp_attribute
    #if __has_cpp_attribute(fallthrough)
        #define MY_FALLTHROUGH [[fallthrough]]
    #else
        #define MY_FALLTHROUGH
    #endif
#else
    #define MY_FALLTHROUGH
#endif
Run Code Online (Sandbox Code Playgroud)

另请参阅:https : //en.cppreference.com/w/cpp/language/attributes/fallthrough

已在GCC 7.4.0,Ubuntu 18.04上测试。

也可以看看

这个问题的C版本:GCC 7,-Wimplicit-fallthrough警告和清除警告的可移植方式?