TypeRawPtr::add_offset has an implicit conversion of a literal 0 to a pointer, which would trigger -Wzero-as-null-pointer-constant. The obvious fix is to change the literal 0 to nullptr.
However, the surrounding code touches on UB. The problem code (after replacing literal 0 with nullptr) is
https://github.com/openjdk/jdk/blob/988a531b097ccbd699d233059d73f41cae24dc5b/src/hotspot/share/opto/type.cpp#L3227-L3228
{code:c++}
address bits = _bits+offset;
if (bits == nullptr) ...
{code}
The compiler can infer that the result of pointer arithmetic is never null, as that would involve UB. So the compiler could change or elide the comparison and it's positive consequent.
Exploring with godbolt shows that clang actually does optimize this in a way that differs from a naive reading of the source code.
Consider the following test file:
{code:c++}
#include <stdint.h>
bool is_arith_null(const char* p, intptr_t i) {
return (p + i) == nullptr;
}
{code}
gcc produces this:
{code}
is_arith_null(char const*, int):
add rdi, rsi
sete al
ret
{code}
msvc produces something functionally equivalent.
But clang produces
{code}
is_arith_null(char const*, int):
test rdi, rdi
sete al
ret
{code}
The clang-generated code discards the addition and just returns true if the pointer argument is null.
However, the surrounding code touches on UB. The problem code (after replacing literal 0 with nullptr) is
https://github.com/openjdk/jdk/blob/988a531b097ccbd699d233059d73f41cae24dc5b/src/hotspot/share/opto/type.cpp#L3227-L3228
{code:c++}
address bits = _bits+offset;
if (bits == nullptr) ...
{code}
The compiler can infer that the result of pointer arithmetic is never null, as that would involve UB. So the compiler could change or elide the comparison and it's positive consequent.
Exploring with godbolt shows that clang actually does optimize this in a way that differs from a naive reading of the source code.
Consider the following test file:
{code:c++}
#include <stdint.h>
bool is_arith_null(const char* p, intptr_t i) {
return (p + i) == nullptr;
}
{code}
gcc produces this:
{code}
is_arith_null(char const*, int):
add rdi, rsi
sete al
ret
{code}
msvc produces something functionally equivalent.
But clang produces
{code}
is_arith_null(char const*, int):
test rdi, rdi
sete al
ret
{code}
The clang-generated code discards the addition and just returns true if the pointer argument is null.
- blocks
-
JDK-8332189 Enable -Wzero-as-null-pointer-constant for gcc
-
- Open
-
- relates to
-
JDK-6876037 CTW fails jdk7/hotspot/src/share/vm/opto/type.cpp:2055. assert(bits,"Use TypePtr for NULL")
-
- Closed
-
- links to
-
Commit(master) openjdk/jdk/0a57fe1d
-
Review(master) openjdk/jdk/21324