This question actually consists of two observations.
First: The inclusion of <atomic>
makes GCC not emit the conversion-null
diagnostic in at least some cases where it otherwise does.
For example, consider the file noerror.cpp
:
#include <atomic>
#pragma GCC diagnostic error "-Wconversion-null"
int * foo() {return false;}
This file (error.cpp
) is identical except for commenting out the include:
//#include <atomic>
#pragma GCC diagnostic error "-Wconversion-null"
int * foo() {return false;}
If I attempt to compile error.cpp
, I get an error as expected:
$ 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
I get the same results if I omit the #pragma
and compile with -Werror
instead. This is also expected: according to the GCC docs, the warning is enabled by default.
To my surprise, I can compile noerror.cpp
with no errors. Even if the <atomic>
header suppressed warnings and errors through #pragma GCC diagnostic ignore
, the explicit pragma in my code should re-enable them, and yet it doesn't.
Incidentally, clang++
errors as expected regardless of whether the header is included:
error: cannot initialize return object of type 'int *' with an rvalue of type 'bool'
Second: Running with distcc restores proper behavior
I have multiple workstations. If I attempt to build locally on any of them, I encounter the above behavior. If, however, distcc attempts to built it on any remote machine, the error is emitted properly. (This is how I discovered this issue in the first place; our build would with high probability make distcc fallback to local compilation). In fact, even if I have distcc
SSH to my own machine, the proper behavior (i.e. an error) is restored:
$ 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
It is not clear to me how distcc
manages to restore the proper behavior.
Version information: I'm running Ubuntu 3.5.0-46-generic
, GCC 4.8.1, and distcc 3.1.
Including <atomic>
seems to break GCC's conversion-null
diagnostic. And somehow, using distcc fixes it. I've searched but been unable to find any reference to a similar bug. Is this pilot error, a known issue, or should I file a GCC bug report?
[Edit: The code snippets were from when I made it a warning instead of an error. Pasted the corrected version]
I've further found that this only occurs when combining compilation and preprocessing in a single step. This accounts for the difference in behavior when using distcc
: it preprocesses all the code on the local machine, and compiles it remotely.
Despite @user2485710's comments to the contrary, this is not a case of pilot error or using a poorly documented feature. This is a bona fide bug, and I've reported it as such:
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=60304
[As of now it's unresolved, but Harald van Dijk noted that GCC suppresses the warning because it (wrongly) thinks it's in a system header. The error/warning can be re-exposed by using -Wsystem-headers
.]