diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def --- a/clang/include/clang/Basic/TokenKinds.def +++ b/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 diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/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, diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp --- a/clang/lib/Parse/ParseExpr.cpp +++ b/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); diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/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(); } } diff --git a/clang/test/SemaCXX/type-traits.cpp b/clang/test/SemaCXX/type-traits.cpp --- a/clang/test/SemaCXX/type-traits.cpp +++ b/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() { + static_assert(!__is_scoped_enum(Enum), ""); + static_assert(!__is_scoped_enum(EnumType), ""); + static_assert(!__is_scoped_enum(SignedEnum), ""); + static_assert(!__is_scoped_enum(UnsignedEnum), ""); + + static_assert(__is_scoped_enum(EnumClass), ""); + static_assert(__is_scoped_enum(EnumClassType), ""); + static_assert(__is_scoped_enum(SignedEnumClass), ""); + static_assert(__is_scoped_enum(UnsignedEnumClass), ""); + + static_assert(!__is_scoped_enum(int), ""); + static_assert(!__is_scoped_enum(Union), ""); + static_assert(!__is_scoped_enum(Int), ""); + static_assert(!__is_scoped_enum(IntAr), ""); + static_assert(!__is_scoped_enum(UnionAr), ""); + static_assert(!__is_scoped_enum(Derives), ""); + static_assert(!__is_scoped_enum(ClassType), ""); + static_assert(!__is_scoped_enum(cvoid), ""); + static_assert(!__is_scoped_enum(IntArNB), ""); + static_assert(!__is_scoped_enum(HasAnonymousUnion), ""); +} + struct FinalClass final { }; @@ -766,6 +797,31 @@ (void)__is_unbounded_array(decltype(t32)); // expected-error{{variable length arrays are not supported for '__is_unbounded_array'}} } +void is_referenceable() { + static_assert(__is_referenceable(int), ""); + static_assert(__is_referenceable(const int), ""); + static_assert(__is_referenceable(volatile int), ""); + static_assert(__is_referenceable(const volatile int), ""); + static_assert(__is_referenceable(int *), ""); + static_assert(__is_referenceable(int &), ""); + static_assert(__is_referenceable(int &&), ""); + static_assert(__is_referenceable(int (*)()), ""); + static_assert(__is_referenceable(int (&)()), ""); + static_assert(__is_referenceable(int(&&)()), ""); + static_assert(__is_referenceable(IntAr), ""); + static_assert(__is_referenceable(IntArNB), ""); + static_assert(__is_referenceable(decltype(nullptr)), ""); + static_assert(__is_referenceable(Empty), ""); + static_assert(__is_referenceable(Union), ""); + static_assert(__is_referenceable(Derives), ""); + static_assert(__is_referenceable(Enum), ""); + static_assert(__is_referenceable(EnumClass), ""); + static_assert(__is_referenceable(int Empty::*), ""); + static_assert(__is_referenceable(int(Empty::*)()), ""); + + { int a[F(__is_referenceable(void))]; } +} + template void tmpl_func(T&) {} template struct type_wrapper { @@ -998,6 +1054,42 @@ int t34[F(__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; @@ -3359,6 +3451,8 @@ static_assert(__is_same(remove_cvref_t, M), ""); static_assert(__is_same(remove_pointer_t, M), ""); static_assert(__is_same(remove_reference_t, M), ""); + + static_assert(!__is_referenceable(M), ""); } };