Author: Aaron Ballman Date: 2025-04-02T07:28:45-04:00 New Revision: 574e43dffd7a97d32f996df58b1787ad5158529c
URL: https://github.com/llvm/llvm-project/commit/574e43dffd7a97d32f996df58b1787ad5158529c DIFF: https://github.com/llvm/llvm-project/commit/574e43dffd7a97d32f996df58b1787ad5158529c.diff LOG: [C23] Allow casting from a null pointer constant to nullptr_t (#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 Added: Modified: clang/docs/ReleaseNotes.rst clang/lib/Sema/SemaCast.cpp clang/test/C/C23/n3042.c Removed: ################################################################################ diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 35658d63be55c..eb2591b287c2c 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..2824dfce1572c 100644 --- a/clang/lib/Sema/SemaCast.cpp +++ b/clang/lib/Sema/SemaCast.cpp @@ -3091,10 +3091,10 @@ void CastOperation::CheckCStyleCast() { return; } - // C23 6.5.4p4: - // The type nullptr_t shall not be converted to any type other than void, - // bool, or a pointer type. No type other than nullptr_t shall be converted - // to nullptr_t. + // C23 6.5.5p4: + // ... The type nullptr_t shall not be converted to any type other than + // void, bool or a pointer type.If the target type is nullptr_t, the cast + // expression shall be a null pointer constant or have type nullptr_t. if (SrcType->isNullPtrType()) { // FIXME: 6.3.2.4p2 says that nullptr_t can be converted to itself, but // 6.5.4p4 is a constraint check and nullptr_t is not void, bool, or a @@ -3115,11 +3115,20 @@ 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; + if (!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; + } + // 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