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@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@H01@@@YAXXZ"( +template void f<B{fold(reinterpret_cast<int*>(0)), 2}>(); + +// CHECK: define weak_odr void @_Z1fIXtl1BLPKi12EEEEvv( +// MSABI: define {{.*}} @"??$f@$2UB@@PEBH0M@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); + _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
