-
Notifications
You must be signed in to change notification settings - Fork 12k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Clang] Remove __is_nullptr #99038
[Clang] Remove __is_nullptr #99038
Conversation
@llvm/pr-subscribers-clang Author: Nikolas Klauser (philnik777) Changes
Full diff: https://github.com/llvm/llvm-project/pull/99038.diff 5 Files Affected:
diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst
index 81784c75081ba..cfd7d29fb9eac 100644
--- a/clang/docs/LanguageExtensions.rst
+++ b/clang/docs/LanguageExtensions.rst
@@ -1614,10 +1614,6 @@ The following type trait primitives are supported by Clang. Those traits marked
* ``__is_nothrow_assignable`` (C++, MSVC 2013)
* ``__is_nothrow_constructible`` (C++, MSVC 2013)
* ``__is_nothrow_destructible`` (C++, MSVC 2013)
-* ``__is_nullptr`` (C++, GNU, Microsoft, Embarcadero):
- Returns true for ``std::nullptr_t`` and false for everything else. The
- corresponding standard library feature is ``std::is_null_pointer``, but
- ``__is_null_pointer`` is already in use by some implementations.
* ``__is_object`` (C++, Embarcadero)
* ``__is_pod`` (C++, GNU, Microsoft, Embarcadero):
Note, the corresponding standard trait was deprecated in C++20.
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp
index ce827c689beb7..2c201d346328b 100644
--- a/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/clang/lib/Parse/ParseDeclCXX.cpp
@@ -447,9 +447,9 @@ Decl *Parser::ParseLinkage(ParsingDeclSpec &DS, DeclaratorContext Context) {
///
/// HLSL: Parse export function declaration.
///
-/// export-function-declaration:
+/// export-function-declaration:
/// 'export' function-declaration
-///
+///
/// export-declaration-group:
/// 'export' '{' function-declaration-seq[opt] '}'
///
@@ -1799,7 +1799,6 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
tok::kw___is_nothrow_constructible,
tok::kw___is_nothrow_convertible,
tok::kw___is_nothrow_destructible,
- tok::kw___is_nullptr,
tok::kw___is_object,
tok::kw___is_pod,
tok::kw___is_pointer,
diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp
index 3d7c58e5b3c3c..b3df9cfbc8b9a 100644
--- a/clang/lib/Parse/ParseExpr.cpp
+++ b/clang/lib/Parse/ParseExpr.cpp
@@ -800,7 +800,6 @@ bool Parser::isRevertibleTypeTrait(const IdentifierInfo *II,
REVERTIBLE_TYPE_TRAIT(__is_nothrow_assignable);
REVERTIBLE_TYPE_TRAIT(__is_nothrow_constructible);
REVERTIBLE_TYPE_TRAIT(__is_nothrow_destructible);
- REVERTIBLE_TYPE_TRAIT(__is_nullptr);
REVERTIBLE_TYPE_TRAIT(__is_object);
REVERTIBLE_TYPE_TRAIT(__is_pod);
REVERTIBLE_TYPE_TRAIT(__is_pointer);
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index bef7da239e6e5..a41b938531cab 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -4979,7 +4979,6 @@ static bool CheckUnaryTypeTraitTypeCompleteness(Sema &S, TypeTrait UTT,
case UTT_IsArray:
case UTT_IsBoundedArray:
case UTT_IsPointer:
- case UTT_IsNullPointer:
case UTT_IsReferenceable:
case UTT_IsLvalueReference:
case UTT_IsRvalueReference:
@@ -5235,8 +5234,6 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT,
return T->isIncompleteArrayType();
case UTT_IsPointer:
return T->isAnyPointerType();
- case UTT_IsNullPointer:
- return T->isNullPtrType();
case UTT_IsLvalueReference:
return T->isLValueReferenceType();
case UTT_IsRvalueReference:
diff --git a/clang/test/SemaCXX/type-traits.cpp b/clang/test/SemaCXX/type-traits.cpp
index 7adbf4aad7afe..b38e8989cb559 100644
--- a/clang/test/SemaCXX/type-traits.cpp
+++ b/clang/test/SemaCXX/type-traits.cpp
@@ -1041,42 +1041,6 @@ void is_pointer()
static_assert(!__is_pointer(void (StructWithMembers::*) ()));
}
-void is_null_pointer() {
- StructWithMembers x;
-
- static_assert(__is_nullptr(decltype(nullptr)));
- static_assert(!__is_nullptr(void *));
- static_assert(!__is_nullptr(cvoid *));
- static_assert(!__is_nullptr(cvoid *));
- static_assert(!__is_nullptr(char *));
- static_assert(!__is_nullptr(int *));
- static_assert(!__is_nullptr(int **));
- static_assert(!__is_nullptr(ClassType *));
- static_assert(!__is_nullptr(Derives *));
- static_assert(!__is_nullptr(Enum *));
- static_assert(!__is_nullptr(IntArNB *));
- static_assert(!__is_nullptr(Union *));
- static_assert(!__is_nullptr(UnionAr *));
- static_assert(!__is_nullptr(StructWithMembers *));
- static_assert(!__is_nullptr(void (*)()));
-
- static_assert(!__is_nullptr(void));
- static_assert(!__is_nullptr(cvoid));
- static_assert(!__is_nullptr(cvoid));
- static_assert(!__is_nullptr(char));
- static_assert(!__is_nullptr(int));
- static_assert(!__is_nullptr(int));
- static_assert(!__is_nullptr(ClassType));
- static_assert(!__is_nullptr(Derives));
- static_assert(!__is_nullptr(Enum));
- static_assert(!__is_nullptr(IntArNB));
- static_assert(!__is_nullptr(Union));
- static_assert(!__is_nullptr(UnionAr));
- static_assert(!__is_nullptr(StructWithMembers));
- static_assert(!__is_nullptr(int StructWithMembers::*));
- static_assert(!__is_nullptr(void(StructWithMembers::*)()));
-}
-
void is_member_object_pointer()
{
StructWithMembers x;
|
You can test this locally with the following command:git-clang-format --diff 91450f1b57b34034376662dae5452af8c992c103 bd3b3b354fd3c94ef4f9eb9acd7f5bfd1beddbb1 --extensions cpp -- clang/lib/Parse/ParseDeclCXX.cpp clang/lib/Parse/ParseExpr.cpp clang/lib/Sema/SemaExprCXX.cpp clang/test/SemaCXX/type-traits.cpp View the diff from clang-format here.diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp
index 2c201d3463..d0bdbc6599 100644
--- a/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/clang/lib/Parse/ParseDeclCXX.cpp
@@ -1766,64 +1766,31 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
Tok.isOneOf(
#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) tok::kw___##Trait,
#include "clang/Basic/TransformTypeTraits.def"
- tok::kw___is_abstract,
- tok::kw___is_aggregate,
- tok::kw___is_arithmetic,
- tok::kw___is_array,
- tok::kw___is_assignable,
- tok::kw___is_base_of,
- tok::kw___is_bounded_array,
- tok::kw___is_class,
- tok::kw___is_complete_type,
- tok::kw___is_compound,
- tok::kw___is_const,
- tok::kw___is_constructible,
- tok::kw___is_convertible,
- tok::kw___is_convertible_to,
- tok::kw___is_destructible,
- tok::kw___is_empty,
- tok::kw___is_enum,
- tok::kw___is_floating_point,
- tok::kw___is_final,
- tok::kw___is_function,
- tok::kw___is_fundamental,
- tok::kw___is_integral,
- tok::kw___is_interface_class,
- tok::kw___is_literal,
- tok::kw___is_lvalue_expr,
- tok::kw___is_lvalue_reference,
- tok::kw___is_member_function_pointer,
- tok::kw___is_member_object_pointer,
- tok::kw___is_member_pointer,
- tok::kw___is_nothrow_assignable,
- tok::kw___is_nothrow_constructible,
- tok::kw___is_nothrow_convertible,
- tok::kw___is_nothrow_destructible,
- tok::kw___is_object,
- tok::kw___is_pod,
- tok::kw___is_pointer,
- tok::kw___is_polymorphic,
- tok::kw___is_reference,
- tok::kw___is_referenceable,
- tok::kw___is_rvalue_expr,
- tok::kw___is_rvalue_reference,
- tok::kw___is_same,
- tok::kw___is_scalar,
- tok::kw___is_scoped_enum,
- tok::kw___is_sealed,
- tok::kw___is_signed,
- tok::kw___is_standard_layout,
- tok::kw___is_trivial,
+ tok::kw___is_abstract, tok::kw___is_aggregate,
+ tok::kw___is_arithmetic, tok::kw___is_array, tok::kw___is_assignable,
+ tok::kw___is_base_of, tok::kw___is_bounded_array, tok::kw___is_class,
+ tok::kw___is_complete_type, tok::kw___is_compound, tok::kw___is_const,
+ tok::kw___is_constructible, tok::kw___is_convertible,
+ tok::kw___is_convertible_to, tok::kw___is_destructible,
+ tok::kw___is_empty, tok::kw___is_enum, tok::kw___is_floating_point,
+ tok::kw___is_final, tok::kw___is_function, tok::kw___is_fundamental,
+ tok::kw___is_integral, tok::kw___is_interface_class,
+ tok::kw___is_literal, tok::kw___is_lvalue_expr,
+ tok::kw___is_lvalue_reference, tok::kw___is_member_function_pointer,
+ tok::kw___is_member_object_pointer, tok::kw___is_member_pointer,
+ tok::kw___is_nothrow_assignable, tok::kw___is_nothrow_constructible,
+ tok::kw___is_nothrow_convertible, tok::kw___is_nothrow_destructible,
+ tok::kw___is_object, tok::kw___is_pod, tok::kw___is_pointer,
+ tok::kw___is_polymorphic, tok::kw___is_reference,
+ tok::kw___is_referenceable, tok::kw___is_rvalue_expr,
+ tok::kw___is_rvalue_reference, tok::kw___is_same, tok::kw___is_scalar,
+ tok::kw___is_scoped_enum, tok::kw___is_sealed, tok::kw___is_signed,
+ tok::kw___is_standard_layout, tok::kw___is_trivial,
tok::kw___is_trivially_equality_comparable,
tok::kw___is_trivially_assignable,
- tok::kw___is_trivially_constructible,
- tok::kw___is_trivially_copyable,
- tok::kw___is_unbounded_array,
- tok::kw___is_union,
- tok::kw___is_unsigned,
- tok::kw___is_void,
- tok::kw___is_volatile
- ))
+ tok::kw___is_trivially_constructible, tok::kw___is_trivially_copyable,
+ tok::kw___is_unbounded_array, tok::kw___is_union,
+ tok::kw___is_unsigned, tok::kw___is_void, tok::kw___is_volatile))
// GNU libstdc++ 4.2 and libc++ use certain intrinsic names as the
// name of struct templates, but some are keywords in GCC >= 4.3
// and Clang. Therefore, when we see the token sequence "struct
|
It's probably reasonable to do that, however to be on the safe side, let's merge that after the Clang 19 branch. Thanks! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mostly support the removal but I'd feel more comfortable documenting the extension as deprecated in Clang 19, adding a release note warning users about it going away and what the replacement code would look like, and then remove __is_nullptr()
in Clang 20. (edited to remove the need for a time machine as a prerequisite.)
That said, has anyone checked with Embarcadero and Microsoft as to whether they still need it supported for their STL implementations for historical reasons? That might delay the timeline or change opinions on the direction.
AFAICT MSVC never had such a trait. I don't know why it's documented that way, but the documentation is almost certainly wrong. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM (modulo whitespace nits), but please make sure the 19.x branch gets a release note officially deprecating the trait and saying it will be removed in Clang 20.
bd3b3b3
to
c1090a5
Compare
`is_null_pointer` can be implemented very efficiently as `__is_same(__remove_cv(T), decltype(nullptr))`. Since GCC supports both of these builtins as well, libc++ has no interest in using `__is_nullptr` instead. Furthermore, I could find only a single use in the wild (https://sourcegraph.com/search?q=context:global+__is_nullptr%28+-file:clang&patternType=keyword&sm=0). Because of these reasons I don't think it's worth keeping this builtin around.
`is_null_pointer` can be implemented very efficiently as `__is_same(__remove_cv(T), decltype(nullptr))`. Since GCC supports both of these builtins as well, libc++ has no interest in using `__is_nullptr` instead. Furthermore, I could find only a single use in the wild (https://sourcegraph.com/search?q=context:global+__is_nullptr%28+-file:clang&patternType=keyword&sm=0). Because of these reasons I don't think it's worth keeping this builtin around.
Support for `__is_nullptr` was removed in #99038, but I forgot to remove it from the list of type traits, resulting in Clang crashing when one tries to use it.
Support for `__is_nullptr` was removed in llvm#99038, but I forgot to remove it from the list of type traits, resulting in Clang crashing when one tries to use it.
Support for `__is_nullptr` was removed in llvm#99038, but I forgot to remove it from the list of type traits, resulting in Clang crashing when one tries to use it.
is_null_pointer
can be implemented very efficiently as__is_same(__remove_cv(T), decltype(nullptr))
. Since GCC supports both of these builtins as well, libc++ has no interest in using__is_nullptr
instead. Furthermore, I could find only a single use in the wild (https://sourcegraph.com/search?q=context:global+__is_nullptr%28+-file:clang&patternType=keyword&sm=0). Because of these reasons I don't think it's worth keeping this builtin around.