aboutsummaryrefslogtreecommitdiff
path: root/clang/lib
diff options
context:
space:
mode:
authorTimm Baeder <tbaeder@redhat.com>2025-08-06 16:49:00 +0200
committerGitHub <noreply@github.com>2025-08-06 16:49:00 +0200
commit8704ca0fb8fb3c659a4e98e9362cd56d453dcb4b (patch)
treec2e49d091c10143c25697e1e36d5950c600f30da /clang/lib
parent75838b818bdbc14fc41f901b4e60821647009cf3 (diff)
downloadllvm-8704ca0fb8fb3c659a4e98e9362cd56d453dcb4b.zip
llvm-8704ca0fb8fb3c659a4e98e9362cd56d453dcb4b.tar.gz
llvm-8704ca0fb8fb3c659a4e98e9362cd56d453dcb4b.tar.bz2
[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.
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/AST/ExprConstant.cpp14
1 files changed, 9 insertions, 5 deletions
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 34af9cc..3679327 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.