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

问题描述 投票:23回答:3

我们正在接受来自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:
   ^~~~

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

switch (cond)
  {
  case 1:
    bar (0);
    /* FALLTHRU */
  default:
    …
  }

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

c++ gcc switch-statement warnings
3个回答
29
投票

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

  m_state = BODY;
  // fall through
case BODY:

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

fall through是GCC认可的标志之一。这不仅仅是FALLTHRU。有关完整列表,请参阅-Wimplicit-fallthrough option的文档。另见posting on the Red Hat Developer blog

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

请注意,仅当编译器实际看到注释时,才使用带标记注释的警告。如果预处理器单独运行,则需要指示它保留注释,如-C option of GCC)。例如,要避免使用ccache进行虚假警告,您需要在编译时指定-C标志,或者使用最新版本的ccache,使用keep_comments_cpp选项。


5
投票

C ++ 17 [[fallthrough]]

例:

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

编译:

g++ -std=c++17 -Wimplicit-fallthrough main.cpp

如果你删除[[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:
         ^~~~

另请注意,例子中只有在遇到两种情况时才会发出警告:最后一个case语句(case 1 here)即使没有break也不会产生警告。

以下构造不会生成警告:

case 0:
    argc = 1;
    break;
case 1:

case 0:
    argc = 1;
    return 0;
case 1:

// Empty case synonyms are fine.
case 0:
case 1:

// https://stackoverflow.com/a/45137452/895245
case 0:
    argc = 1;
    // fall through
case 1:

// GCC extension for pre C++17.
case 0:
    argc = 1;
    __attribute__ ((fallthrough));
case 1:

// GCC examines all braches.
case 0:
    if (argv[0][0] == 'm') {
        [[fallthrough]];
    } else {
        return 0;
    }
case 1:
    argc = 2;

我们可以从最后一个看到GCC检查所有可能的分支,并警告其中是否有任何一个没有[[fallthrough]];breakreturn

您可能还想在this GEM5 inspired 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

另见:https://en.cppreference.com/w/cpp/language/attributes/fallthrough

在GCC 7.3.0上测试,Ubuntu 16.04


0
投票

如上所述,C ++ 17支持[[fallthrough]]属性。只有g++有一个捕获(至少版本7.3.0)。如果在命令行中使用-Wextra,并且缺少break;语句,即使包含[[fallthrough]],仍然会收到警告。这是因为它测试了该属性的其他版本,而不是C ++ 17。

如果您明确设置了警告,则可以解决问题。所以如果你有:

... -std=c++17 -Wextra ...

它失败。

如果你有:

... -std=c++17 -Wextra -Wimplicit-fallthrough ...

它仅适用于C ++ 17 fallthrough属性。我没试过,但我认为订单可能很重要。话虽这么说,-Wextra实现可能足够聪明,不能改变已经设置的警告。

case 1:
  blah = 5;
  [[fallthrough]];  // works only if "... -Wimplicit-fallthrough ..." is used

旧的属性是__attribute__((fallthrough))。 g ++也可以识别一些评论。

© www.soinside.com 2019 - 2024. All rights reserved.