为什么现代编译器的`-pedantic`选项不再检测分号错误?

41
以下代码片段在一些较旧的编译器上添加-pedantic-Werror时会产生编译错误。
#include <cstdint>
#include <iostream>

int add(int a, int b){
    return a + b;
}; // <-- stray semicolon

int main (){
    return 0;
}


然而,这在较新的编译器版本中并不会发生。请查看GCC(10.x11.x)和Clang(5.x,6.x)的矩阵,展示了它们之间的差异,链接在https://godbolt.org/z/KWeb8WTxz
我有两个问题:
1. 为什么最近的编译器不会触发这个问题? 2. 是否有可能在最新版本的Clang或GCC中启用旧的行为?

5
因为现在在所有声明上下文中都是合法的。尽管编译器允许,在C++14之前(在类作用域中)是不合法的。 - undefined
15
-Wextra-semi可以捕捉到这些问题。 - undefined
8
让我想起了https://xkcd.com/1172/ - undefined
请注意,-Wextra-semiC++方言选项中有所记录,而不是在更一般的请求或禁止警告消息的选项中。它被标记为“仅限C++,Objective C++”。 - undefined
最好删除多余的分号,因为它们会使代码凌乱不堪。码头的询问指出,他们已经被一个严肃的教授激怒了,一个严肃的教授坟墓;他的快速餐桌;他敏锐而专业地引起了兴趣,以在平面上引入时间的概念,通过在空间中打孔(?!)。 - undefined
1个回答

60
从C++11开始,全局级别的额外分号(也称为空声明)是有效的。我相信这在编写宏时偶尔会有用。
因此,GCC 11在使用-std=c++11或更高版本时,删除了对额外分号的-pedantic诊断。请参见:

您可以通过使用早于C++11的C++标准来恢复旧的行为。如果您传递-std=c++03,GCC 11和clang 6都会发出旧的诊断信息。

或者,最近版本的GCC和Clang都支持警告选项-Wextra-semi,该选项专门警告多余的分号。感谢HolyBlackCat提到这一点。


9
@jerin 你可以使用类似于IF_DEBUG的宏来删除调试版本之外的代码。然后,使用IF_DEBUG(int counter = 0);来声明一个仅在调试版本中存在的全局变量。当然,你也可以将分号放在宏参数列表内,但这可能会与clang-format的自动格式化产生冲突,而且大多数开发人员更喜欢在函数式宏之后放置分号。在非调试版本中,这个宏会展开为空,从而得到一个空声明 - undefined
3
@HolyBlackCat 在命名空间范围内你不能这样做。 - undefined
2
@Caleth 在命名空间范围内,你可以使用 static_assert(true) 来消耗 ;。而且在函数范围内也是有效的... - undefined
3
@jerin,我在这里想知道的是为什么你这么在意,偶尔多一个分号会有什么坏处呢? - undefined
9
@PlasmaHH 我在一个运行CI的CentOS系统上遇到了-Wpedantic被激活的问题(该系统用于构建manylinux wheels),而在本地我无法触发它(因为我有更新的编译器)。通过CI来修复这个问题变得很麻烦,所以我想知道底层发生了什么以及可能的解决方案。通过谷歌搜索并没有给我提供太多线索,所以我提出了这个问题。 - undefined
显示剩余2条评论

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