Skip to content

Commit 8704ca0

Browse files
authored
[clang][ExprConst] Consider integer pointers of value 0 nullptr (#150164)
When casting a 0 to a pointer type, the IsNullPtr flag was always set to false, leading to weird results like a pointer with value 0 that isn't a null pointer. This caused ```c++ struct B { const int *p;}; template<B> void f() {} template void f<B{nullptr}>(); template void f<B{fold(reinterpret_cast<int*>(0))}>(); ``` to be valid code, since nullptr and (int*)0 aren't equal. This seems weird and GCC doesn't behave like this.
1 parent 75838b8 commit 8704ca0

File tree

4 files changed

+27
-12
lines changed

4 files changed

+27
-12
lines changed

clang/lib/AST/ExprConstant.cpp

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9860,11 +9860,15 @@ bool PointerExprEvaluator::VisitCastExpr(const CastExpr *E) {
98609860
if (Value.isInt()) {
98619861
unsigned Size = Info.Ctx.getTypeSize(E->getType());
98629862
uint64_t N = Value.getInt().extOrTrunc(Size).getZExtValue();
9863-
Result.Base = (Expr*)nullptr;
9864-
Result.InvalidBase = false;
9865-
Result.Offset = CharUnits::fromQuantity(N);
9866-
Result.Designator.setInvalid();
9867-
Result.IsNullPtr = false;
9863+
if (N == Info.Ctx.getTargetNullPointerValue(E->getType())) {
9864+
Result.setNull(Info.Ctx, E->getType());
9865+
} else {
9866+
Result.Base = (Expr *)nullptr;
9867+
Result.InvalidBase = false;
9868+
Result.Offset = CharUnits::fromQuantity(N);
9869+
Result.Designator.setInvalid();
9870+
Result.IsNullPtr = false;
9871+
}
98689872
return true;
98699873
} else {
98709874
// In rare instances, the value isn't an lvalue.

clang/test/AST/ByteCode/functions.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -622,7 +622,7 @@ namespace FromIntegral {
622622
int a[(int)DoubleFn((void*)-1)()]; // both-error {{not allowed at file scope}} \
623623
// both-warning {{variable length arrays}}
624624
int b[(int)DoubleFn((void*)(-1 + 1))()]; // both-error {{not allowed at file scope}} \
625-
// expected-note {{evaluates to a null function pointer}} \
625+
// both-note {{evaluates to a null function pointer}} \
626626
// both-warning {{variable length arrays}}
627627
#endif
628628
}

clang/test/CodeGenCXX/mangle-class-nttp.cpp

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,14 @@ template void f<B{nullptr}>();
2727
// CHECK: define weak_odr void @_Z1fIXtl1BLPKi32EEEEvv(
2828
// MSABI: define {{.*}} @"??$f@$2UB@@PEBH0CA@H0A@@@@YAXXZ"
2929
template void f<B{fold((int*)32)}>();
30-
#ifndef _WIN32
31-
// FIXME: On MS ABI, we mangle this the same as nullptr, despite considering a
32-
// null pointer and zero bitcast to a pointer to be distinct pointer values.
33-
// CHECK: define weak_odr void @_Z1fIXtl1BrcPKiLi0EEEEvv(
34-
template void f<B{fold(reinterpret_cast<int*>(0))}>();
35-
#endif
30+
31+
// CHECK: define weak_odr void @_Z1fIXtl1BLPKi0ELi2EEEEvv(
32+
// MSABI: define {{.*}} @"??$f@$2UB@@PEBH0A@H01@@@YAXXZ"(
33+
template void f<B{fold(reinterpret_cast<int*>(0)), 2}>();
34+
35+
// CHECK: define weak_odr void @_Z1fIXtl1BLPKi12EEEEvv(
36+
// MSABI: define {{.*}} @"??$f@$2UB@@PEBH0M@H0A@@@@YAXXZ"(
37+
template void f<B{fold(reinterpret_cast<int*>(12))}>();
3638

3739
// Pointers to subobjects.
3840
struct Nested { union { int k; int arr[2]; }; } nested[2];
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// RUN: %clang_cc1 -triple amdgcn -cl-std=clc++ -verify %s
2+
3+
// expected-no-diagnostics
4+
5+
#define fold(x) (__builtin_constant_p(x) ? (x) : (x))
6+
static_assert(nullptr != fold(reinterpret_cast<private int*>(0)));
7+
8+
static_assert(nullptr == (private int *)0);
9+

0 commit comments

Comments
 (0)