这个问题实际上由两个观察结果组成。
第一:<atomic>
的包含使GCC至少在某些情况下不会发出conversion-null
诊断信号,否则会发出
例如,考虑文件noerror.cpp
:
#include <atomic>
#pragma GCC diagnostic error "-Wconversion-null"
int * foo() {return false;}
这个文件(error.cpp
)除了注释掉include:之外是相同的
//#include <atomic>
#pragma GCC diagnostic error "-Wconversion-null"
int * foo() {return false;}
如果我试图编译error.cpp
,我会得到一个预期的错误:
$ g++-4.8 -c -std=c++11 error.cpp
error.cpp: In function ‘int* foo()’:
error.cpp:3:21: error: converting ‘false’ to pointer type ‘int*’ [-Werror=conversion-null]
int * foo() {return false;}
^
cc1plus: some warnings being treated as errors
如果我省略了#pragma
,改为使用-Werror
编译,我会得到相同的结果。这也是意料之中的:根据GCC文档,默认情况下会启用警告。
令我惊讶的是,我可以毫无错误地编译noerror.cpp
。即使<atomic>
标头通过#pragma GCC diagnostic ignore
抑制了警告和错误,我的代码中的显式杂注也应该重新启用它们,但它没有。
顺便说一句,无论是否包括报头,clang++
都会出现预期错误:
error: cannot initialize return object of type 'int *' with an rvalue of type 'bool'
第二:使用distcc运行可恢复正常行为
我有多个工作站。如果我试图在它们中的任何一个上进行本地构建,我会遇到上述行为。但是,如果distcc试图在任何远程机器上构建它,那么错误就会正确地发出。(这就是我最初发现这个问题的原因;我们的构建很可能会使distcc回退到本地编译)。事实上,即使我在自己的机器上有distcc
SSH,也会恢复正确的行为(即错误):
$ DISTCC_HOSTS='localhost' distcc g++-4.8 -c -std=c++11 noerror.cpp # no error
$ DISTCC_HOSTS='@[my_ip_address]' distcc g++-4.8 -c -std=c++11 noerror.cpp
noerror.cpp: In function ‘int* foo()’:
noerror.cpp:3:21: error: converting ‘false’ to pointer type ‘int*’ [-Werror=conversion-null]
cc1plus: some warnings being treated as errors
我不清楚distcc
是如何恢复正常行为的。
版本信息:我运行的是Ubuntu3.5.0-46-generic
、GCC 4.8.1和distcc 3.1。
摘要
包括<atomic>
似乎打破了GCC对conversion-null
的诊断。不知怎么的,使用distcc修复了它。我已经搜索过了,但找不到任何类似bug的引用。这个试点错误是一个已知的问题,还是我应该提交GCC错误报告
[编辑:代码片段是我将其作为警告而非错误时的代码片段。粘贴了更正后的版本]
我进一步发现,只有在将编译和预处理组合在一个步骤中时才会发生这种情况。这解释了使用distcc
时的行为差异:它预处理本地机器上的所有代码,并远程编译。
尽管@user2485710的评论与此相反,但这并不是飞行员错误或使用了记录不足的功能。这是一个真正的错误,我已经报告过了:
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=60304
[目前尚未解决,但Harald van Dijk指出,GCC抑制警告是因为它(错误地)认为它在系统标头中。可以使用-Wsystem-headers
重新暴露错误/警告。]