Skip to content

Commit 574e43d

Browse files
authored
[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
1 parent 7c4009f commit 574e43d

File tree

3 files changed

+22
-10
lines changed

3 files changed

+22
-10
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,8 @@ C23 Feature Support
159159
which clarified that a compound literal used within a function prototype is
160160
treated as if the compound literal were within the body rather than at file
161161
scope.
162+
- Fixed a bug where you could not cast a null pointer constant to type
163+
``nullptr_t``. Fixes #GH133644.
162164

163165
Non-comprehensive list of changes in this release
164166
-------------------------------------------------

clang/lib/Sema/SemaCast.cpp

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3091,10 +3091,10 @@ void CastOperation::CheckCStyleCast() {
30913091
return;
30923092
}
30933093

3094-
// C23 6.5.4p4:
3095-
// The type nullptr_t shall not be converted to any type other than void,
3096-
// bool, or a pointer type. No type other than nullptr_t shall be converted
3097-
// to nullptr_t.
3094+
// C23 6.5.5p4:
3095+
// ... The type nullptr_t shall not be converted to any type other than
3096+
// void, bool or a pointer type.If the target type is nullptr_t, the cast
3097+
// expression shall be a null pointer constant or have type nullptr_t.
30983098
if (SrcType->isNullPtrType()) {
30993099
// FIXME: 6.3.2.4p2 says that nullptr_t can be converted to itself, but
31003100
// 6.5.4p4 is a constraint check and nullptr_t is not void, bool, or a
@@ -3115,11 +3115,20 @@ void CastOperation::CheckCStyleCast() {
31153115
Self.CurFPFeatureOverrides());
31163116
}
31173117
}
3118+
31183119
if (DestType->isNullPtrType() && !SrcType->isNullPtrType()) {
3119-
Self.Diag(SrcExpr.get()->getExprLoc(), diag::err_nullptr_cast)
3120-
<< /*type to nullptr*/ 1 << SrcType;
3121-
SrcExpr = ExprError();
3122-
return;
3120+
if (!SrcExpr.get()->isNullPointerConstant(Self.Context,
3121+
Expr::NPC_NeverValueDependent)) {
3122+
Self.Diag(SrcExpr.get()->getExprLoc(), diag::err_nullptr_cast)
3123+
<< /*type to nullptr*/ 1 << SrcType;
3124+
SrcExpr = ExprError();
3125+
return;
3126+
}
3127+
// Need to convert the source from whatever its type is to a null pointer
3128+
// type first.
3129+
SrcExpr = ImplicitCastExpr::Create(Self.Context, DestType, CK_NullToPointer,
3130+
SrcExpr.get(), nullptr, VK_PRValue,
3131+
Self.CurFPFeatureOverrides());
31233132
}
31243133

31253134
if (DestType->isExtVectorType()) {

clang/test/C/C23/n3042.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,6 @@ void test() {
8282
(nullptr_t)12; // expected-error {{cannot cast an object of type 'int' to 'nullptr_t'}}
8383
(float)null_val; // expected-error {{cannot cast an object of type 'nullptr_t' to 'float'}}
8484
(float)nullptr; // expected-error {{cannot cast an object of type 'nullptr_t' to 'float'}}
85-
(nullptr_t)0; // expected-error {{cannot cast an object of type 'int' to 'nullptr_t'}}
86-
(nullptr_t)(void *)0; // expected-error {{cannot cast an object of type 'void *' to 'nullptr_t'}}
8785
(nullptr_t)(int *)12; // expected-error {{cannot cast an object of type 'int *' to 'nullptr_t'}}
8886

8987
(void)null_val; // ok
@@ -93,6 +91,9 @@ void test() {
9391
(int *)null_val; // ok
9492
(int *)nullptr; // ok
9593
(nullptr_t)nullptr; // ok
94+
(nullptr_t)0; // ok
95+
(nullptr_t)(void *)0; // ok
96+
(nullptr_t)null_val; // ok
9697

9798
// Can it be converted to bool with the result false (this relies on Clang
9899
// accepting additional kinds of constant expressions where an ICE is

0 commit comments

Comments
 (0)