cjdb created this revision.
cjdb added a reviewer: aaron.ballman.
Herald added a project: All.
cjdb requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

... as builtins.

This is information that the compiler already has, and should be exposed
so that the library doesn't need to reimplement the exact same
functionality.

This was originally a part of D116280 <https://reviews.llvm.org/D116280>.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D135177

Files:
  clang/include/clang/Basic/TokenKinds.def
  clang/lib/Parse/ParseDeclCXX.cpp
  clang/lib/Parse/ParseExpr.cpp
  clang/lib/Sema/SemaExprCXX.cpp
  clang/test/SemaCXX/type-traits.cpp

Index: clang/test/SemaCXX/type-traits.cpp
===================================================================
--- clang/test/SemaCXX/type-traits.cpp
+++ clang/test/SemaCXX/type-traits.cpp
@@ -345,11 +345,19 @@
 }
 
 typedef Enum EnumType;
+typedef EnumClass EnumClassType;
 
 void is_enum()
 {
   { int arr[T(__is_enum(Enum))]; }
   { int arr[T(__is_enum(EnumType))]; }
+  { int arr[T(__is_enum(SignedEnum))]; }
+  { int arr[T(__is_enum(UnsignedEnum))]; }
+
+  { int arr[T(__is_enum(EnumClass))]; }
+  { int arr[T(__is_enum(EnumClassType))]; }
+  { int arr[T(__is_enum(SignedEnumClass))]; }
+  { int arr[T(__is_enum(UnsignedEnumClass))]; }
 
   { int arr[F(__is_enum(int))]; }
   { int arr[F(__is_enum(Union))]; }
@@ -363,6 +371,29 @@
   { int arr[F(__is_enum(HasAnonymousUnion))]; }
 }
 
+void is_scoped_enum() {
+  { int arr[F(__is_scoped_enum(Enum))]; }
+  { int arr[F(__is_scoped_enum(EnumType))]; }
+  { int arr[F(__is_scoped_enum(SignedEnum))]; }
+  { int arr[F(__is_scoped_enum(UnsignedEnum))]; }
+
+  { int arr[T(__is_scoped_enum(EnumClass))]; }
+  { int arr[T(__is_scoped_enum(EnumClassType))]; }
+  { int arr[T(__is_scoped_enum(SignedEnumClass))]; }
+  { int arr[T(__is_scoped_enum(UnsignedEnumClass))]; }
+
+  { int arr[F(__is_scoped_enum(int))]; }
+  { int arr[F(__is_scoped_enum(Union))]; }
+  { int arr[F(__is_scoped_enum(Int))]; }
+  { int arr[F(__is_scoped_enum(IntAr))]; }
+  { int arr[F(__is_scoped_enum(UnionAr))]; }
+  { int arr[F(__is_scoped_enum(Derives))]; }
+  { int arr[F(__is_scoped_enum(ClassType))]; }
+  { int arr[F(__is_scoped_enum(cvoid))]; }
+  { int arr[F(__is_scoped_enum(IntArNB))]; }
+  { int arr[F(__is_scoped_enum(HasAnonymousUnion))]; }
+}
+
 struct FinalClass final {
 };
 
@@ -766,6 +797,42 @@
   (void)__is_unbounded_array(decltype(t32)); // expected-error{{variable length arrays are not supported for '__is_unbounded_array'}}
 }
 
+void is_referenceable() {
+  { int a[T(__is_referenceable(int))]; }
+  { int a[T(__is_referenceable(const int))]; }
+  { int a[T(__is_referenceable(volatile int))]; }
+  { int a[T(__is_referenceable(const volatile int))]; }
+  { int a[T(__is_referenceable(int *))]; }
+  { int a[T(__is_referenceable(int &))]; }
+  { int a[T(__is_referenceable(int &&))]; }
+  { int a[T(__is_referenceable(int (*)()))]; }
+  { int a[T(__is_referenceable(int (&)()))]; }
+  { int a[T(__is_referenceable(int(&&)()))]; }
+  { int a[T(__is_referenceable(IntAr))]; }
+  { int a[T(__is_referenceable(IntArNB))]; }
+  { int a[T(__is_referenceable(decltype(nullptr)))]; }
+  { int a[T(__is_referenceable(Empty))]; }
+  { int a[T(__is_referenceable(Union))]; }
+  { int a[T(__is_referenceable(Derives))]; }
+  { int a[T(__is_referenceable(Enum))]; }
+  { int a[T(__is_referenceable(EnumClass))]; }
+  { int a[T(__is_referenceable(int Empty::*))]; }
+  { int a[T(__is_referenceable(int(Empty::*)()))]; }
+  { int a[T(__is_referenceable(int(Empty::*)() const))]; }
+  { int a[T(__is_referenceable(int(Empty::*)() volatile))]; }
+  { int a[T(__is_referenceable(int(Empty::*)() const volatile))]; }
+  { int a[T(__is_referenceable(int(Empty::*)() &))]; }
+  { int a[T(__is_referenceable(int(Empty::*)() const &))]; }
+  { int a[T(__is_referenceable(int(Empty::*)() volatile &))]; }
+  { int a[T(__is_referenceable(int(Empty::*)() const volatile &))]; }
+  { int a[T(__is_referenceable(int(Empty::*)() &&))]; }
+  { int a[T(__is_referenceable(int(Empty::*)() const &&))]; }
+  { int a[T(__is_referenceable(int(Empty::*)() volatile &&))]; }
+  { int a[T(__is_referenceable(int(Empty::*)() const volatile &&))]; }
+
+  { int a[F(__is_referenceable(void))]; }
+}
+
 template <typename T> void tmpl_func(T&) {}
 
 template <typename T> struct type_wrapper {
@@ -998,6 +1065,42 @@
   int t34[F(__is_pointer(void (StructWithMembers::*) ()))];
 }
 
+void is_null_pointer() {
+  StructWithMembers x;
+
+  int t00[T(__is_nullptr(decltype(nullptr)))];
+  int t01[F(__is_nullptr(void *))];
+  int t02[F(__is_nullptr(cvoid *))];
+  int t03[F(__is_nullptr(cvoid *))];
+  int t04[F(__is_nullptr(char *))];
+  int t05[F(__is_nullptr(int *))];
+  int t06[F(__is_nullptr(int **))];
+  int t07[F(__is_nullptr(ClassType *))];
+  int t08[F(__is_nullptr(Derives *))];
+  int t09[F(__is_nullptr(Enum *))];
+  int t10[F(__is_nullptr(IntArNB *))];
+  int t11[F(__is_nullptr(Union *))];
+  int t12[F(__is_nullptr(UnionAr *))];
+  int t13[F(__is_nullptr(StructWithMembers *))];
+  int t14[F(__is_nullptr(void (*)()))];
+
+  int t20[F(__is_nullptr(void))];
+  int t21[F(__is_nullptr(cvoid))];
+  int t22[F(__is_nullptr(cvoid))];
+  int t23[F(__is_nullptr(char))];
+  int t24[F(__is_nullptr(int))];
+  int t25[F(__is_nullptr(int))];
+  int t26[F(__is_nullptr(ClassType))];
+  int t27[F(__is_nullptr(Derives))];
+  int t28[F(__is_nullptr(Enum))];
+  int t29[F(__is_nullptr(IntArNB))];
+  int t30[F(__is_nullptr(Union))];
+  int t31[F(__is_nullptr(UnionAr))];
+  int t32[F(__is_nullptr(StructWithMembers))];
+  int t33[F(__is_nullptr(int StructWithMembers::*))];
+  int t34[F(__is_nullptr(void(StructWithMembers::*)()))];
+}
+
 void is_member_object_pointer()
 {
   StructWithMembers x;
@@ -3359,6 +3462,8 @@
     static_assert(__is_same(remove_cvref_t<M>, M), "");
     static_assert(__is_same(remove_pointer_t<M>, M), "");
     static_assert(__is_same(remove_reference_t<M>, M), "");
+
+    static_assert(!__is_referenceable(M), "");
   }
 };
 
Index: clang/lib/Sema/SemaExprCXX.cpp
===================================================================
--- clang/lib/Sema/SemaExprCXX.cpp
+++ clang/lib/Sema/SemaExprCXX.cpp
@@ -4760,11 +4760,14 @@
   case UTT_IsArray:
   case UTT_IsBoundedArray:
   case UTT_IsPointer:
+  case UTT_IsNullPointer:
+  case UTT_IsReferenceable:
   case UTT_IsLvalueReference:
   case UTT_IsRvalueReference:
   case UTT_IsMemberFunctionPointer:
   case UTT_IsMemberObjectPointer:
   case UTT_IsEnum:
+  case UTT_IsScopedEnum:
   case UTT_IsUnion:
   case UTT_IsClass:
   case UTT_IsFunction:
@@ -4917,6 +4920,8 @@
     return T->isIncompleteArrayType();
   case UTT_IsPointer:
     return T->isAnyPointerType();
+  case UTT_IsNullPointer:
+    return T->isNullPtrType();
   case UTT_IsLvalueReference:
     return T->isLValueReferenceType();
   case UTT_IsRvalueReference:
@@ -4927,6 +4932,8 @@
     return T->isMemberDataPointerType();
   case UTT_IsEnum:
     return T->isEnumeralType();
+  case UTT_IsScopedEnum:
+    return T->isScopedEnumeralType();
   case UTT_IsUnion:
     return T->isUnionType();
   case UTT_IsClass:
@@ -5298,6 +5305,8 @@
     return C.hasUniqueObjectRepresentations(T);
   case UTT_IsTriviallyRelocatable:
     return T.isTriviallyRelocatableType(C);
+  case UTT_IsReferenceable:
+    return T.isReferenceable();
   }
 }
 
Index: clang/lib/Parse/ParseExpr.cpp
===================================================================
--- clang/lib/Parse/ParseExpr.cpp
+++ clang/lib/Parse/ParseExpr.cpp
@@ -1067,20 +1067,20 @@
           REVERTIBLE_TYPE_TRAIT(__is_arithmetic);
           REVERTIBLE_TYPE_TRAIT(__is_array);
           REVERTIBLE_TYPE_TRAIT(__is_assignable);
-          REVERTIBLE_TYPE_TRAIT(__is_bounded_array);
           REVERTIBLE_TYPE_TRAIT(__is_base_of);
+          REVERTIBLE_TYPE_TRAIT(__is_bounded_array);
           REVERTIBLE_TYPE_TRAIT(__is_class);
           REVERTIBLE_TYPE_TRAIT(__is_complete_type);
           REVERTIBLE_TYPE_TRAIT(__is_compound);
           REVERTIBLE_TYPE_TRAIT(__is_const);
           REVERTIBLE_TYPE_TRAIT(__is_constructible);
-          REVERTIBLE_TYPE_TRAIT(__is_convertible);
           REVERTIBLE_TYPE_TRAIT(__is_convertible_to);
+          REVERTIBLE_TYPE_TRAIT(__is_convertible);
           REVERTIBLE_TYPE_TRAIT(__is_destructible);
           REVERTIBLE_TYPE_TRAIT(__is_empty);
           REVERTIBLE_TYPE_TRAIT(__is_enum);
-          REVERTIBLE_TYPE_TRAIT(__is_floating_point);
           REVERTIBLE_TYPE_TRAIT(__is_final);
+          REVERTIBLE_TYPE_TRAIT(__is_floating_point);
           REVERTIBLE_TYPE_TRAIT(__is_function);
           REVERTIBLE_TYPE_TRAIT(__is_fundamental);
           REVERTIBLE_TYPE_TRAIT(__is_integral);
@@ -1094,15 +1094,18 @@
           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);
           REVERTIBLE_TYPE_TRAIT(__is_polymorphic);
           REVERTIBLE_TYPE_TRAIT(__is_reference);
+          REVERTIBLE_TYPE_TRAIT(__is_referenceable);
           REVERTIBLE_TYPE_TRAIT(__is_rvalue_expr);
           REVERTIBLE_TYPE_TRAIT(__is_rvalue_reference);
           REVERTIBLE_TYPE_TRAIT(__is_same);
           REVERTIBLE_TYPE_TRAIT(__is_scalar);
+          REVERTIBLE_TYPE_TRAIT(__is_scoped_enum);
           REVERTIBLE_TYPE_TRAIT(__is_sealed);
           REVERTIBLE_TYPE_TRAIT(__is_signed);
           REVERTIBLE_TYPE_TRAIT(__is_standard_layout);
Index: clang/lib/Parse/ParseDeclCXX.cpp
===================================================================
--- clang/lib/Parse/ParseDeclCXX.cpp
+++ clang/lib/Parse/ParseDeclCXX.cpp
@@ -1605,15 +1605,18 @@
           tok::kw___is_nothrow_assignable,
           tok::kw___is_nothrow_constructible,
           tok::kw___is_nothrow_destructible,
+          tok::kw___is_nullptr,
           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,
Index: clang/include/clang/Basic/TokenKinds.def
===================================================================
--- clang/include/clang/Basic/TokenKinds.def
+++ clang/include/clang/Basic/TokenKinds.def
@@ -520,6 +520,9 @@
 TYPE_TRAIT_1(__is_trivially_relocatable, IsTriviallyRelocatable, KEYCXX)
 TYPE_TRAIT_1(__is_bounded_array, IsBoundedArray, KEYCXX)
 TYPE_TRAIT_1(__is_unbounded_array, IsUnboundedArray, KEYCXX)
+TYPE_TRAIT_1(__is_nullptr, IsNullPointer, KEYCXX)
+TYPE_TRAIT_1(__is_scoped_enum, IsScopedEnum, KEYCXX)
+TYPE_TRAIT_1(__is_referenceable, IsReferenceable, KEYCXX)
 TYPE_TRAIT_2(__reference_binds_to_temporary, ReferenceBindsToTemporary, KEYCXX)
 
 // Embarcadero Expression Traits
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to