[clang] 8704ca0 - [clang][ExprConst] Consider integer pointers of value 0 nullptr (#150164)

via cfe-commits cfe-commits at lists.llvm.org
Wed Aug 6 07:49:03 PDT 2025


Author: Timm Baeder
Date: 2025-08-06T16:49:00+02:00
New Revision: 8704ca0fb8fb3c659a4e98e9362cd56d453dcb4b

URL: https://github.com/llvm/llvm-project/commit/8704ca0fb8fb3c659a4e98e9362cd56d453dcb4b
DIFF: https://github.com/llvm/llvm-project/commit/8704ca0fb8fb3c659a4e98e9362cd56d453dcb4b.diff

LOG: [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.

Added: 
    clang/test/SemaOpenCLCXX/amdgpu-nullptr.clcpp

Modified: 
    clang/lib/AST/ExprConstant.cpp
    clang/test/AST/ByteCode/functions.cpp
    clang/test/CodeGenCXX/mangle-class-nttp.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 34af9ccd2e96e..3679327da7b0c 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -9860,11 +9860,15 @@ bool PointerExprEvaluator::VisitCastExpr(const CastExpr *E) {
     if (Value.isInt()) {
       unsigned Size = Info.Ctx.getTypeSize(E->getType());
       uint64_t N = Value.getInt().extOrTrunc(Size).getZExtValue();
-      Result.Base = (Expr*)nullptr;
-      Result.InvalidBase = false;
-      Result.Offset = CharUnits::fromQuantity(N);
-      Result.Designator.setInvalid();
-      Result.IsNullPtr = false;
+      if (N == Info.Ctx.getTargetNullPointerValue(E->getType())) {
+        Result.setNull(Info.Ctx, E->getType());
+      } else {
+        Result.Base = (Expr *)nullptr;
+        Result.InvalidBase = false;
+        Result.Offset = CharUnits::fromQuantity(N);
+        Result.Designator.setInvalid();
+        Result.IsNullPtr = false;
+      }
       return true;
     } else {
       // In rare instances, the value isn't an lvalue.

diff  --git a/clang/test/AST/ByteCode/functions.cpp b/clang/test/AST/ByteCode/functions.cpp
index 363b6a58ac54d..36e7bb32b2d86 100644
--- a/clang/test/AST/ByteCode/functions.cpp
+++ b/clang/test/AST/ByteCode/functions.cpp
@@ -622,7 +622,7 @@ namespace FromIntegral {
   int a[(int)DoubleFn((void*)-1)()]; // both-error {{not allowed at file scope}} \
                                     // both-warning {{variable length arrays}}
   int b[(int)DoubleFn((void*)(-1 + 1))()]; // both-error {{not allowed at file scope}} \
-                                           // expected-note {{evaluates to a null function pointer}} \
+                                           // both-note {{evaluates to a null function pointer}} \
                                            // both-warning {{variable length arrays}}
 #endif
 }

diff  --git a/clang/test/CodeGenCXX/mangle-class-nttp.cpp b/clang/test/CodeGenCXX/mangle-class-nttp.cpp
index 12c81f2ba0514..536592c6a9308 100644
--- a/clang/test/CodeGenCXX/mangle-class-nttp.cpp
+++ b/clang/test/CodeGenCXX/mangle-class-nttp.cpp
@@ -27,12 +27,14 @@ template void f<B{nullptr}>();
 // CHECK: define weak_odr void @_Z1fIXtl1BLPKi32EEEEvv(
 // MSABI: define {{.*}} @"??$f@$2UB@@PEBH0CA at H0A@@@@YAXXZ"
 template void f<B{fold((int*)32)}>();
-#ifndef _WIN32
-// FIXME: On MS ABI, we mangle this the same as nullptr, despite considering a
-// null pointer and zero bitcast to a pointer to be distinct pointer values.
-// CHECK: define weak_odr void @_Z1fIXtl1BrcPKiLi0EEEEvv(
-template void f<B{fold(reinterpret_cast<int*>(0))}>();
-#endif
+
+// CHECK: define weak_odr void @_Z1fIXtl1BLPKi0ELi2EEEEvv(
+// MSABI: define {{.*}} @"??$f@$2UB@@PEBH0A at H01@@@YAXXZ"(
+template void f<B{fold(reinterpret_cast<int*>(0)), 2}>();
+
+// CHECK: define weak_odr void @_Z1fIXtl1BLPKi12EEEEvv(
+// MSABI: define {{.*}} @"??$f@$2UB@@PEBH0M at H0A@@@@YAXXZ"(
+template void f<B{fold(reinterpret_cast<int*>(12))}>();
 
 // Pointers to subobjects.
 struct Nested { union { int k; int arr[2]; }; } nested[2];

diff  --git a/clang/test/SemaOpenCLCXX/amdgpu-nullptr.clcpp b/clang/test/SemaOpenCLCXX/amdgpu-nullptr.clcpp
new file mode 100644
index 0000000000000..5bc147c2deba7
--- /dev/null
+++ b/clang/test/SemaOpenCLCXX/amdgpu-nullptr.clcpp
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 -triple amdgcn -cl-std=clc++ -verify %s
+
+// expected-no-diagnostics
+
+#define fold(x) (__builtin_constant_p(x) ? (x) : (x))
+static_assert(nullptr != fold(reinterpret_cast<private int*>(0)));
+
+static_assert(nullptr == (private int *)0);
+


        


More information about the cfe-commits mailing list