我们正在接受来自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,是否有通过警告来清除坠落的便携方法?如果是的话那么它是什么?
海湾合作委员会希望标记评论在自己的行上,如下所示:
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
选项。
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]];
或break
或return
。
您可能还想在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。
如上所述,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 ++也可以识别一些评论。