Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
-------------------------------------------------
Expand Down
25 changes: 17 additions & 8 deletions clang/lib/Sema/SemaCast.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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()) {
Expand Down
5 changes: 3 additions & 2 deletions clang/test/C/C23/n3042.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -93,6 +91,9 @@ void test() {
(int *)null_val; // ok
(int *)nullptr; // ok
(nullptr_t)nullptr; // ok
(nullptr_t)0; // ok
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe worth checking other literals as well, like floating point, char and string literals?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added that test coverage in fb9deab, thanks for the suggestion!

(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
Expand Down
Loading