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

Reply via email to