如何在gcc中正确使用__attribute__((fallthrough))

10

代码示例:

int main(int argc, char **argv)
{
    switch(argc)
    {
    case 0:
        argc = 5;
        __attribute__((fallthrough));

    case 1:
        break;
    }
}

使用gcc 6.3.0,只使用-std=c11,此代码会产生一个警告:

<source>: In function 'main':
7 : <source>:7:3: warning: empty declaration
   __attribute__((fallthrough));
   ^~~~~~~~~~~~~

如何正确使用此功能,而不触发警告?


2
如果你比较 6.4文档7.1文档 ,似乎语句属性这样的东西是在7版中添加的。 - Some programmer dude
不是一个答案,但是6.3手册完全缺少7.1中存在的“语句属性”部分,其中描述了fallthrough。我认为它在6.3中根本不被支持。诊断结果是因为GCC不仅仅忽略未知属性,而且将其视为违反此约束的声明(违反了这个约束)。 - StoryTeller - Unslander Monica
@StoryTeller 那很有道理。 - M.M
3个回答

12
作为之前的回答,__attribute__ ((fallthrough)) 是在GCC 7中引入的。 为了保持向后兼容性并清除Clang和GCC的fall through警告,您可以使用/* fall through */标记注释。 应用于您的代码示例:
int main(int argc, char **argv)
{
    switch(argc)
    {
    case 0:
        argc = 5;
        /* fall through */

    case 1:
        break;
    }

    return 0;
}

标记注释和属性都可以在代码后面的同一行或下方使用。 - David C. Rankin
不会没有警告。在旧版的GCC(<7.x)上,将返回属性“warning: empty declaration”。 - jyvet
抱歉,GCC7被隐含了。 - David C. Rankin
2
虽然 fall though 注释是可怕的编译器设计,但是在将预处理和编译合并后,再针对已经分别进行了预处理的同一文件进行编译,应该产生相同的警告/错误,但如果你有特殊的魔术注释就不可能实现这种情况。 - Petr Skocik

8

之前尝试发表评论,但是没有50个声望。

以下是我的经验:

1) 该功能自gcc 7开始使用,因此在旧编译器上使用属性(attribute)会产生警告。因此,我目前使用:

#if defined(__GNUC__) && __GNUC__ >= 7
 #define FALL_THROUGH __attribute__ ((fallthrough))
#else
 #define FALL_THROUGH ((void)0)
#endif /* __GNUC__ >= 7 */

然后我在代码中使用 FALL_THROUGH;

(有一天我会弄清楚clang需要什么,但今天不行)

2) 我花了很多时间尝试让gcc的标记注释起作用,但是我尝试的所有方法都没有成功!某个评论建议为了使其工作,需要在gcc参数中添加-C(意味着注释将被传递给cc1)。当然,gcc 7文档中没有提到任何关于这个要求的内容...


1
为了与XCode 12兼容(以及GNU GCC >= 7兼容),我使用了您解决方案的变体:#if defined(__GNUC__) && __GNUC__ >= 7 || defined(__clang__) && __clang_major__ >= 12。在XCode 12上,$ gcc -xc -dM -E /dev/null | sort | grep __GNUC__会产生#define __GNUC__ 4 - RjOllos
好的信息 - 将集成到我的“模板”中:D - tomi
1
自Clang 10起实际支持此功能,因此__clang_major__ >= 10更准确。看起来在发布说明中错过了这个信息,但提交记录在这里:https://github.com/llvm/llvm-project/commit/1e0affb6e564b7361b0aadb38805f26deff4ecfc - Deewiant
我尝试使用 __cland_major__>=10 条件语句,但遇到了“declaration does not declare anything”的问题。 - Leonid Usov

1
您也可以尝试下面的代码,因为只有这个在Android上有效:
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
// your code
#pragma GCC diagnostic pop

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接