[Bug c++/77513] New: -Wzero-as-null-pointer-constant vs 0, nullptr, NULL and __null

petschy at gmail dot com gcc-bugzilla@gcc.gnu.org
Wed Sep 7 11:23:00 GMT 2016


https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77513

            Bug ID: 77513
           Summary: -Wzero-as-null-pointer-constant vs 0, nullptr, NULL
                    and __null
           Product: gcc
           Version: 7.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: petschy at gmail dot com
  Target Milestone: ---

Created attachment 39580
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=39580&action=edit
Preprocessed source, generated with g++-7.0.0 -std=c++14
-Wzero-as-null-pointer-constant 20160907-null.cpp -E > 20160907-null.ii

Yesterday I switched on the warning for a ~250kloc codebase to clean it up.
Used 7.0, it was tedious but it was done. I had to replace NULLs also, not just
0s, but at that time I wasn't suspecting anything, though it seemed a bit
strange.

Then, tried to build on another machine with 5.4.1, and to my surprise, tons of
warnings appeared. Then tried to build on my machine with 5.4.1, the same
results. It turned out that NULLs are frowned upon, quite inconsistently.

5.4.1 has problems with 7 cpp files, 6.2.1 and 7.0 with just a single one. Did
a grep for NULL, and as expected for a large and aging codebase, there were
lots of them, but they are not treated equally. All files are c++, and compiled
with the same flags.

Preprocessed 2 problematic files with all three gcc versions mentioned. Diffing
them revealed that there is no difference in the actual code, only what gets
included due to the differing gcc versions. All NULLs were replaced with
__null's by the preprocessor, which is defined in the gcc version specific
stddef.h include.

Crafted a test case:

#include <stddef.h>
char* a = 0;
char* b = nullptr;
char* c = __null;
char* d = NULL;
int main()
{
}

$ g++-5.4.1 -std=c++14 -Wzero-as-null-pointer-constant 20160907-null.cpp
20160907-null.cpp:2:11: warning: zero as null pointer constant
[-Wzero-as-null-pointer-constant]
 char* a = 0;
           ^
20160907-null.cpp:4:11: warning: zero as null pointer constant
[-Wzero-as-null-pointer-constant]
 char* c = __null;
           ^
6.2.1 and 7.0 print exactly the same warnings.

So NULL is ok, but __null is not? The end of the preprocessed source looks like
this:

# 2 "20160907-null.cpp"
char* a = 0;
char* b = nullptr;
char* c = __null;
char* d = 
# 5 "20160907-null.cpp" 3 4
         __null
# 5 "20160907-null.cpp"
             ;
int main()
{
}

c and d initialized the same except for whitespace and the two "'# 6" lines
around d's __null. I naively thought that these are only to communicate line
info to the compiler, but if I delete the first one:

$ g++-7.0.0 -std=c++14 -Wzero-as-null-pointer-constant 20160907-null.ii
20160907-null.cpp:2:11: warning: zero as null pointer constant
[-Wzero-as-null-pointer-constant]
 char* a = 0;
           ^
20160907-null.cpp:4:11: warning: zero as null pointer constant
[-Wzero-as-null-pointer-constant]
 char* c = __null;
           ^~~~~~
20160907-null.cpp:6:10: warning: zero as null pointer constant
[-Wzero-as-null-pointer-constant]
 int main()
          ^

The interpretation of __null at d changed for some reason. What is going on? It
seems that the interpretation can change unpredictably, and in the problematic
source files __null's are misdiagnosed even when the "# ..." lines are around
them.

For c++11 and later code, why is NULL defined as __null, rather than nullptr?

I put a fast bandaid on my code by redefining NULL to be nullptr after the last
include in the problematic files, but since the number of problematic files
seems to change from gcc version to gcc version, this is rather fragile, let
alone unelegant.

Platform is Debian Jessie AMD64, the gcc versions:

$ g++-5.4.1 -v
Using built-in specs.
COLLECT_GCC=g++-5.4.1
COLLECT_LTO_WRAPPER=/usr/local/libexec/gcc/x86_64-unknown-linux-gnu/5.4.1/lto-wrapper
Target: x86_64-unknown-linux-gnu
Configured with: ../configure --enable-languages=c,c++ --disable-multilib
--program-suffix=-5.4.1 --disable-bootstrap CFLAGS='-O2 -march=native'
CXXFLAGS='-O2 -march=native'
Thread model: posix
gcc version 5.4.1 20160829 (GCC)

$ g++-6.2.1 -v
Using built-in specs.
COLLECT_GCC=g++-6.2.1
COLLECT_LTO_WRAPPER=/usr/local/libexec/gcc/x86_64-pc-linux-gnu/6.2.1/lto-wrapper
Target: x86_64-pc-linux-gnu
Configured with: ../configure --enable-languages=c,c++ --disable-multilib
--program-suffix=-6.2.1 --disable-bootstrap CFLAGS='-O2 -march=native'
CXXFLAGS='-O2 -march=native'
Thread model: posix
gcc version 6.2.1 20160831 (GCC)

$ g++-7.0.0 -v
Using built-in specs.
COLLECT_GCC=g++-7.0.0
COLLECT_LTO_WRAPPER=/usr/local/libexec/gcc/x86_64-pc-linux-gnu/7.0.0/lto-wrapper
Target: x86_64-pc-linux-gnu
Configured with: ../configure --enable-languages=c,c++ --disable-multilib
--program-suffix=-7.0.0 --disable-bootstrap CFLAGS='-O2 -march=native'
CXXFLAGS='-O2 -march=native'
Thread model: posix
gcc version 7.0.0 20160831 (experimental) (GCC)


More information about the Gcc-bugs mailing list