[clang] [C23] Allow casting from a null pointer constant to nullptr_t (PR #133742)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Mar 31 09:03:38 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Aaron Ballman (AaronBallman)
<details>
<summary>Changes</summary>
C23 allows a cast of a null pointer constant to nullptr_t. e.g., (nullptr_t)0 or (nullptr_t)(void *)0.
Fixes #<!-- -->133644
---
Full diff: https://github.com/llvm/llvm-project/pull/133742.diff
3 Files Affected:
- (modified) clang/docs/ReleaseNotes.rst (+2)
- (modified) clang/lib/Sema/SemaCast.cpp (+18-5)
- (modified) clang/test/C/C23/n3042.c (+3-2)
``````````diff
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
``````````
</details>
https://github.com/llvm/llvm-project/pull/133742
More information about the cfe-commits
mailing list