https://github.com/AaronBallman created https://github.com/llvm/llvm-project/pull/133742
C23 allows a cast of a null pointer constant to nullptr_t. e.g., (nullptr_t)0 or (nullptr_t)(void *)0. Fixes #133644 >From 5ad66ec7a9ea76a080ee34ddf0d68a19dbb9dec6 Mon Sep 17 00:00:00 2001 From: Aaron Ballman <aa...@aaronballman.com> Date: Mon, 31 Mar 2025 12:01:08 -0400 Subject: [PATCH] [C23] Allow casting from a null pointer constant to nullptr_t C23 allows a cast of a null pointer constant to nullptr_t. e.g., (nullptr_t)0 or (nullptr_t)(void *)0. Fixes #133644 --- clang/docs/ReleaseNotes.rst | 2 ++ clang/lib/Sema/SemaCast.cpp | 23 ++++++++++++++++++----- clang/test/C/C23/n3042.c | 5 +++-- 3 files changed, 23 insertions(+), 7 deletions(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 4b8e09d051616..5fdbec3eb4443 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -159,6 +159,8 @@ C23 Feature Support which clarified that a compound literal used within a function prototype is treated as if the compound literal were within the body rather than at file scope. +- Fixed a bug where you could not cast a null pointer constant to type + ``nullptr_t``. Fixes #GH133644. Non-comprehensive list of changes in this release ------------------------------------------------- diff --git a/clang/lib/Sema/SemaCast.cpp b/clang/lib/Sema/SemaCast.cpp index a5dbc16eaea0b..2087815abe9e4 100644 --- a/clang/lib/Sema/SemaCast.cpp +++ b/clang/lib/Sema/SemaCast.cpp @@ -3115,11 +3115,24 @@ void CastOperation::CheckCStyleCast() { Self.CurFPFeatureOverrides()); } } - if (DestType->isNullPtrType() && !SrcType->isNullPtrType()) { - Self.Diag(SrcExpr.get()->getExprLoc(), diag::err_nullptr_cast) - << /*type to nullptr*/ 1 << SrcType; - SrcExpr = ExprError(); - return; + // C23 6.3.2.4p2: a null pointer constant or value of type nullptr_t may be + // converted to nullptr_t. + if (DestType->isNullPtrType()) { + if (!SrcType->isNullPtrType() && + !SrcExpr.get()->isNullPointerConstant(Self.Context, + Expr::NPC_NeverValueDependent)) { + Self.Diag(SrcExpr.get()->getExprLoc(), diag::err_nullptr_cast) + << /*type to nullptr*/ 1 << SrcType; + SrcExpr = ExprError(); + return; + } + if (!SrcType->isNullPtrType()) { + // Need to convert the source from whatever its type is to a null pointer + // type first. + SrcExpr = ImplicitCastExpr::Create( + Self.Context, DestType, CK_NullToPointer, SrcExpr.get(), nullptr, + VK_PRValue, Self.CurFPFeatureOverrides()); + } } if (DestType->isExtVectorType()) { diff --git a/clang/test/C/C23/n3042.c b/clang/test/C/C23/n3042.c index 99661b1fb39eb..fdcb48eb1322a 100644 --- a/clang/test/C/C23/n3042.c +++ b/clang/test/C/C23/n3042.c @@ -82,8 +82,6 @@ void test() { (nullptr_t)12; // expected-error {{cannot cast an object of type 'int' to 'nullptr_t'}} (float)null_val; // expected-error {{cannot cast an object of type 'nullptr_t' to 'float'}} (float)nullptr; // expected-error {{cannot cast an object of type 'nullptr_t' to 'float'}} - (nullptr_t)0; // expected-error {{cannot cast an object of type 'int' to 'nullptr_t'}} - (nullptr_t)(void *)0; // expected-error {{cannot cast an object of type 'void *' to 'nullptr_t'}} (nullptr_t)(int *)12; // expected-error {{cannot cast an object of type 'int *' to 'nullptr_t'}} (void)null_val; // ok @@ -93,6 +91,9 @@ void test() { (int *)null_val; // ok (int *)nullptr; // ok (nullptr_t)nullptr; // ok + (nullptr_t)0; // ok + (nullptr_t)(void *)0; // ok + (nullptr_t)null_val; // ok // Can it be converted to bool with the result false (this relies on Clang // accepting additional kinds of constant expressions where an ICE is _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits