[clang] [C23] Allow casting from a null pointer constant to nullptr_t (PR #133742)
Aaron Ballman via cfe-commits
cfe-commits at lists.llvm.org
Mon Mar 31 09:03:16 PDT 2025
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 <aaron at 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
More information about the cfe-commits
mailing list