https://github.com/Tsche created https://github.com/llvm/llvm-project/pull/201491
This patch moves all traits to a tablegen file. The motivation for this change is a review comment in https://github.com/llvm/llvm-project/pull/142341 - since then about a year has passed and we've accumulated 9 standard names that are maintained separately from their corresponding trait definitions. While this is still a reasonably low number, it is definitely going to keep increasing. >From a38bd10dbb2143164d23424848bc645fbd676152 Mon Sep 17 00:00:00 2001 From: Matthias Wippich <[email protected]> Date: Thu, 4 Jun 2026 00:52:13 +0200 Subject: [PATCH] [clang][NFC] move traits to tablegen --- clang/include/clang/AST/TypeBase.h | 2 +- clang/include/clang/Basic/CMakeLists.txt | 4 + clang/include/clang/Basic/ExpressionTraits.h | 4 +- clang/include/clang/Basic/Specifiers.h | 2 +- clang/include/clang/Basic/TokenKinds.def | 140 +---- clang/include/clang/Basic/Traits.td | 556 ++++++++++++++++++ .../clang/Basic/TransformTypeTraits.def | 29 - clang/include/clang/Basic/TypeTraits.h | 53 +- clang/include/clang/Sema/DeclSpec.h | 4 +- clang/lib/AST/ItaniumMangle.cpp | 2 +- clang/lib/AST/JSONNodeDumper.cpp | 2 +- clang/lib/AST/TextNodeDumper.cpp | 2 +- clang/lib/AST/TypePrinter.cpp | 2 +- clang/lib/ASTMatchers/Dynamic/Marshallers.cpp | 2 +- clang/lib/ASTMatchers/Dynamic/Marshallers.h | 2 +- clang/lib/Basic/ExpressionTraits.cpp | 4 +- clang/lib/Basic/TypeTraits.cpp | 57 +- clang/lib/Format/FormatToken.h | 2 +- clang/lib/Format/TokenAnnotator.cpp | 2 +- clang/lib/Lex/Lexer.cpp | 2 +- clang/lib/Lex/PPMacroExpansion.cpp | 2 +- clang/lib/Parse/ParseDecl.cpp | 2 +- clang/lib/Parse/ParseDeclCXX.cpp | 82 +-- clang/lib/Parse/ParseExpr.cpp | 4 +- clang/lib/Parse/ParseExprCXX.cpp | 15 +- clang/lib/Parse/ParseStmt.cpp | 2 +- clang/lib/Parse/ParseTentative.cpp | 6 +- clang/lib/Sema/DeclSpec.cpp | 10 +- clang/lib/Sema/SemaDecl.cpp | 2 +- clang/lib/Sema/SemaTemplateVariadic.cpp | 2 +- clang/lib/Sema/SemaType.cpp | 4 +- clang/lib/Sema/SemaTypeTraits.cpp | 12 +- clang/utils/TableGen/CMakeLists.txt | 1 + clang/utils/TableGen/ClangTraitsEmitter.cpp | 195 ++++++ clang/utils/TableGen/TableGen.cpp | 16 +- clang/utils/TableGen/TableGenBackends.h | 2 + 36 files changed, 869 insertions(+), 361 deletions(-) create mode 100644 clang/include/clang/Basic/Traits.td delete mode 100644 clang/include/clang/Basic/TransformTypeTraits.def create mode 100644 clang/utils/TableGen/ClangTraitsEmitter.cpp diff --git a/clang/include/clang/AST/TypeBase.h b/clang/include/clang/AST/TypeBase.h index c64eee11fd91e..fac1e9c9eb92f 100644 --- a/clang/include/clang/AST/TypeBase.h +++ b/clang/include/clang/AST/TypeBase.h @@ -6463,7 +6463,7 @@ class UnaryTransformType : public Type, public llvm::FoldingSetNode { public: enum UTTKind { #define TRANSFORM_TYPE_TRAIT_DEF(Enum, _) Enum, -#include "clang/Basic/TransformTypeTraits.def" +#include "clang/Basic/Traits.inc" }; private: diff --git a/clang/include/clang/Basic/CMakeLists.txt b/clang/include/clang/Basic/CMakeLists.txt index 20172622ca424..0dbbfffc7ed51 100644 --- a/clang/include/clang/Basic/CMakeLists.txt +++ b/clang/include/clang/Basic/CMakeLists.txt @@ -150,6 +150,10 @@ clang_tablegen(BuiltinTemplates.inc -gen-clang-builtin-templates SOURCE BuiltinTemplates.td TARGET ClangBuiltinTemplates) +clang_tablegen(Traits.inc -gen-clang-traits + SOURCE Traits.td + TARGET ClangTraits) + # ARM NEON and MVE clang_tablegen(arm_neon.inc -gen-arm-neon-sema SOURCE arm_neon.td diff --git a/clang/include/clang/Basic/ExpressionTraits.h b/clang/include/clang/Basic/ExpressionTraits.h index b38ebd9ac60b9..48ae69cf1ae17 100644 --- a/clang/include/clang/Basic/ExpressionTraits.h +++ b/clang/include/clang/Basic/ExpressionTraits.h @@ -20,10 +20,10 @@ namespace clang { enum ExpressionTrait { #define EXPRESSION_TRAIT(Spelling, Name, Key) ET_##Name, -#include "clang/Basic/TokenKinds.def" +#include "clang/Basic/Traits.inc" ET_Last = -1 // ET_Last == last ET_XX in the enum. #define EXPRESSION_TRAIT(Spelling, Name, Key) +1 -#include "clang/Basic/TokenKinds.def" +#include "clang/Basic/Traits.inc" }; /// Return the internal name of type trait \p T. Never null. diff --git a/clang/include/clang/Basic/Specifiers.h b/clang/include/clang/Basic/Specifiers.h index 8da6fd4cf454a..6aeca806730b1 100644 --- a/clang/include/clang/Basic/Specifiers.h +++ b/clang/include/clang/Basic/Specifiers.h @@ -89,7 +89,7 @@ namespace clang { TST_typeof_unqualExpr, // C23 typeof_unqual(expression) TST_decltype, // C++11 decltype #define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) TST_##Trait, -#include "clang/Basic/TransformTypeTraits.def" +#include "clang/Basic/Traits.inc" TST_auto, // C++11 auto TST_decltype_auto, // C++1y decltype(auto) TST_auto_type, // __auto_type extension diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def index f07d8ebb75035..9e907dba35b62 100644 --- a/clang/include/clang/Basic/TokenKinds.def +++ b/clang/include/clang/Basic/TokenKinds.def @@ -327,8 +327,6 @@ KEYWORD(register , KEYALL) KEYWORD(return , KEYALL) KEYWORD(short , KEYALL) KEYWORD(signed , KEYALL) -UNARY_EXPR_OR_TYPE_TRAIT(sizeof, SizeOf, KEYALL) -UNARY_EXPR_OR_TYPE_TRAIT(__datasizeof, DataSizeOf, KEYCXX) KEYWORD(static , KEYALL) KEYWORD(struct , KEYALL) KEYWORD(switch , KEYALL) @@ -362,9 +360,6 @@ KEYWORD(__ptrauth , KEYALL) KEYWORD(__ob_wrap , KEYALL) KEYWORD(__ob_trap , KEYALL) -// C2y -UNARY_EXPR_OR_TYPE_TRAIT(_Countof, CountOf, KEYNOCXX) - // C++ 2.11p1: Keywords. KEYWORD(asm , KEYCXX|KEYGNU) KEYWORD(bool , BOOLSUPPORT|KEYC23) @@ -417,8 +412,6 @@ C99_KEYWORD(inline , KEYCXX|KEYGNU) // C++11 keywords CXX11_KEYWORD(alignas , KEYC23) -// alignof and _Alignof return the required ABI alignment -CXX11_UNARY_EXPR_OR_TYPE_TRAIT(alignof, AlignOf, KEYC23) CXX11_KEYWORD(char16_t , KEYNOMS18) CXX11_KEYWORD(char32_t , KEYNOMS18) CXX11_KEYWORD(constexpr , KEYC23) @@ -466,9 +459,6 @@ KEYWORD(_Decimal32 , KEYALL) KEYWORD(_Decimal64 , KEYALL) KEYWORD(_Decimal128 , KEYALL) KEYWORD(__null , KEYCXX) -// __alignof returns the preferred alignment of a type, the alignment -// clang will attempt to give an object of the type if allowed by ABI. -UNARY_EXPR_OR_TYPE_TRAIT(__alignof, PreferredAlignOf, KEYALL) KEYWORD(__attribute , KEYALL) KEYWORD(__builtin_choose_expr , KEYALL) KEYWORD(__builtin_offsetof , KEYALL) @@ -480,9 +470,6 @@ KEYWORD(__builtin_LINE , KEYALL) KEYWORD(__builtin_COLUMN , KEYALL) KEYWORD(__builtin_source_location , KEYCXX) -// __builtin_types_compatible_p is a GNU C extension that we handle like a C++ -// type trait. -TYPE_TRAIT_2(__builtin_types_compatible_p, TypeCompatible, KEYNOCXX) KEYWORD(__builtin_va_arg , KEYALL) KEYWORD(__extension__ , KEYALL) KEYWORD(__float128 , KEYALL) @@ -501,122 +488,12 @@ KEYWORD(__FUNCDNAME__ , KEYMS) KEYWORD(__FUNCSIG__ , KEYMS) KEYWORD(L__FUNCTION__ , KEYMS) KEYWORD(L__FUNCSIG__ , KEYMS) -TYPE_TRAIT_1(__is_interface_class, IsInterfaceClass, KEYMS) -TYPE_TRAIT_1(__is_sealed, IsSealed, KEYMS) - -// MSVC12.0 / VS2013 Type Traits -TYPE_TRAIT_1(__is_destructible, IsDestructible, KEYALL) -TYPE_TRAIT_1(__is_trivially_destructible, IsTriviallyDestructible, KEYCXX) -TYPE_TRAIT_1(__is_nothrow_destructible, IsNothrowDestructible, KEYALL) -TYPE_TRAIT_2(__is_nothrow_assignable, IsNothrowAssignable, KEYCXX) -TYPE_TRAIT_N(__is_constructible, IsConstructible, KEYCXX) -TYPE_TRAIT_N(__is_nothrow_constructible, IsNothrowConstructible, KEYCXX) - -// MSVC14.0 / VS2015 Type Traits -TYPE_TRAIT_2(__is_assignable, IsAssignable, KEYCXX) - -// MSVC Type Traits of unknown vintage -TYPE_TRAIT_1(__has_nothrow_move_assign, HasNothrowMoveAssign, KEYCXX) -TYPE_TRAIT_1(__has_trivial_move_assign, HasTrivialMoveAssign, KEYCXX) -TYPE_TRAIT_1(__has_trivial_move_constructor, HasTrivialMoveConstructor, KEYCXX) // GNU and MS Type Traits -TYPE_TRAIT_1(__builtin_is_implicit_lifetime, IsImplicitLifetime, KEYCXX) -TYPE_TRAIT_2(__builtin_is_virtual_base_of, IsVirtualBaseOf, KEYCXX) -TYPE_TRAIT_1(__has_nothrow_assign, HasNothrowAssign, KEYCXX) -TYPE_TRAIT_1(__has_nothrow_copy, HasNothrowCopy, KEYCXX) -TYPE_TRAIT_1(__has_nothrow_constructor, HasNothrowConstructor, KEYCXX) -TYPE_TRAIT_1(__has_trivial_assign, HasTrivialAssign, KEYCXX) -TYPE_TRAIT_1(__has_trivial_copy, HasTrivialCopy, KEYCXX) -TYPE_TRAIT_1(__has_trivial_constructor, HasTrivialDefaultConstructor, KEYCXX) -TYPE_TRAIT_1(__has_trivial_destructor, HasTrivialDestructor, KEYCXX) -TYPE_TRAIT_1(__has_virtual_destructor, HasVirtualDestructor, KEYCXX) -TYPE_TRAIT_1(__is_abstract, IsAbstract, KEYCXX) -TYPE_TRAIT_1(__is_aggregate, IsAggregate, KEYCXX) -TYPE_TRAIT_2(__is_base_of, IsBaseOf, KEYCXX) -TYPE_TRAIT_1(__is_class, IsClass, KEYCXX) -TYPE_TRAIT_2(__is_convertible_to, IsConvertibleTo, KEYCXX) -TYPE_TRAIT_1(__is_empty, IsEmpty, KEYCXX) -TYPE_TRAIT_1(__is_enum, IsEnum, KEYCXX) -TYPE_TRAIT_1(__is_final, IsFinal, KEYCXX) -TYPE_TRAIT_1(__is_literal, IsLiteral, KEYCXX) // Name for GCC 4.6 compatibility - people have already written libraries using // this name unfortunately. ALIAS("__is_literal_type", __is_literal, KEYCXX) -TYPE_TRAIT_1(__is_pod, IsPOD, KEYCXX) -TYPE_TRAIT_1(__is_polymorphic, IsPolymorphic, KEYCXX) -TYPE_TRAIT_1(__is_standard_layout, IsStandardLayout, KEYCXX) -TYPE_TRAIT_1(__is_trivial, IsTrivial, KEYCXX) -TYPE_TRAIT_2(__is_trivially_assignable, IsTriviallyAssignable, KEYCXX) -TYPE_TRAIT_N(__is_trivially_constructible, IsTriviallyConstructible, KEYCXX) -TYPE_TRAIT_1(__is_trivially_copyable, IsTriviallyCopyable, KEYCXX) -TYPE_TRAIT_1(__is_union, IsUnion, KEYCXX) -TYPE_TRAIT_1(__has_unique_object_representations, - HasUniqueObjectRepresentations, KEYCXX) -TYPE_TRAIT_2(__is_layout_compatible, IsLayoutCompatible, KEYCXX) -TYPE_TRAIT_2(__is_pointer_interconvertible_base_of, IsPointerInterconvertibleBaseOf, KEYCXX) - -#include "clang/Basic/TransformTypeTraits.def" - -// Clang-only C++ Type Traits -TYPE_TRAIT_1(__is_trivially_equality_comparable, IsTriviallyEqualityComparable, KEYCXX) -TYPE_TRAIT_1(__is_bounded_array, IsBoundedArray, KEYCXX) -TYPE_TRAIT_1(__is_unbounded_array, IsUnboundedArray, KEYCXX) -TYPE_TRAIT_1(__is_scoped_enum, IsScopedEnum, KEYCXX) -TYPE_TRAIT_1(__can_pass_in_regs, CanPassInRegs, KEYCXX) -TYPE_TRAIT_2(__reference_binds_to_temporary, ReferenceBindsToTemporary, KEYCXX) -TYPE_TRAIT_2(__reference_constructs_from_temporary, ReferenceConstructsFromTemporary, KEYCXX) -TYPE_TRAIT_2(__reference_converts_from_temporary, ReferenceConvertsFromTemporary, KEYCXX) -TYPE_TRAIT_2(__builtin_lt_synthesizes_from_spaceship, LtSynthesizesFromSpaceship, KEYCXX) -TYPE_TRAIT_2(__builtin_le_synthesizes_from_spaceship, LeSynthesizesFromSpaceship, KEYCXX) -TYPE_TRAIT_2(__builtin_gt_synthesizes_from_spaceship, GtSynthesizesFromSpaceship, KEYCXX) -TYPE_TRAIT_2(__builtin_ge_synthesizes_from_spaceship, GeSynthesizesFromSpaceship, KEYCXX) -// IsDeducible is only used internally by clang for CTAD implementation and -// is not exposed to users. -TYPE_TRAIT_2(/*EmptySpellingName*/, IsDeducible, KEYCXX) - -// __is_trivially_relocatable is deprecated -TYPE_TRAIT_1(__builtin_is_cpp_trivially_relocatable, IsCppTriviallyRelocatable, KEYCXX) -TYPE_TRAIT_1(__is_trivially_relocatable, IsTriviallyRelocatable, KEYCXX) -TYPE_TRAIT_1(__is_bitwise_cloneable, IsBitwiseCloneable, KEYALL) -TYPE_TRAIT_1(__builtin_structured_binding_size, StructuredBindingSize, KEYCXX) - - - -// Embarcadero Expression Traits -EXPRESSION_TRAIT(__is_lvalue_expr, IsLValueExpr, KEYCXX) -EXPRESSION_TRAIT(__is_rvalue_expr, IsRValueExpr, KEYCXX) - -// Embarcadero Unary Type Traits -TYPE_TRAIT_1(__is_arithmetic, IsArithmetic, KEYCXX) -TYPE_TRAIT_1(__is_floating_point, IsFloatingPoint, KEYCXX) -TYPE_TRAIT_1(__is_integral, IsIntegral, KEYCXX) -TYPE_TRAIT_1(__is_complete_type, IsCompleteType, KEYCXX) -TYPE_TRAIT_1(__is_void, IsVoid, KEYCXX) -TYPE_TRAIT_1(__is_array, IsArray, KEYCXX) -TYPE_TRAIT_1(__is_function, IsFunction, KEYCXX) -TYPE_TRAIT_1(__is_reference, IsReference, KEYCXX) -TYPE_TRAIT_1(__is_lvalue_reference, IsLvalueReference, KEYCXX) -TYPE_TRAIT_1(__is_rvalue_reference, IsRvalueReference, KEYCXX) -TYPE_TRAIT_1(__is_fundamental, IsFundamental, KEYCXX) -TYPE_TRAIT_1(__is_object, IsObject, KEYCXX) -TYPE_TRAIT_1(__is_scalar, IsScalar, KEYCXX) -TYPE_TRAIT_1(__is_compound, IsCompound, KEYCXX) -TYPE_TRAIT_1(__is_pointer, IsPointer, KEYCXX) -TYPE_TRAIT_1(__is_member_object_pointer, IsMemberObjectPointer, KEYCXX) -TYPE_TRAIT_1(__is_member_function_pointer, IsMemberFunctionPointer, KEYCXX) -TYPE_TRAIT_1(__is_member_pointer, IsMemberPointer, KEYCXX) -TYPE_TRAIT_1(__is_const, IsConst, KEYCXX) -TYPE_TRAIT_1(__is_volatile, IsVolatile, KEYCXX) -TYPE_TRAIT_1(__is_signed, IsSigned, KEYCXX) -TYPE_TRAIT_1(__is_unsigned, IsUnsigned, KEYCXX) - -// Embarcadero Binary Type Traits -TYPE_TRAIT_2(__is_same, IsSame, KEYCXX) -TYPE_TRAIT_2(__is_convertible, IsConvertible, KEYCXX) -TYPE_TRAIT_2(__is_nothrow_convertible, IsNothrowConvertible, KEYCXX) -ARRAY_TYPE_TRAIT(__array_rank, ArrayRank, KEYCXX) -ARRAY_TYPE_TRAIT(__array_extent, ArrayExtent, KEYCXX) + // Name for GCC 6 compatibility. ALIAS("__is_same_as", __is_same, KEYCXX) @@ -624,8 +501,6 @@ ALIAS("__is_same_as", __is_same, KEYCXX) KEYWORD(__private_extern__ , KEYALL) KEYWORD(__module_private__ , KEYALL) -UNARY_EXPR_OR_TYPE_TRAIT(__builtin_ptrauth_type_discriminator, PtrAuthTypeDiscriminator, KEYALL) - // Extension that will be enabled for Microsoft, Borland and PS4, but can be // disabled via '-fno-declspec'. KEYWORD(__declspec , 0) @@ -664,7 +539,6 @@ ALIAS("write_only", __write_only , KEYOPENCLC | KEYOPENCLCXX) ALIAS("read_write", __read_write , KEYOPENCLC | KEYOPENCLCXX) // OpenCL builtins KEYWORD(__builtin_astype , KEYOPENCLC | KEYOPENCLCXX) -UNARY_EXPR_OR_TYPE_TRAIT(vec_step, VecStep, KEYOPENCLC | KEYOPENCLCXX | KEYALTIVEC | KEYZVECTOR) #define GENERIC_IMAGE_TYPE(ImgType, Id) KEYWORD(ImgType##_t, KEYOPENCLC | KEYOPENCLCXX) #include "clang/Basic/OpenCLImageTypes.def" KEYWORD(pipe , KEYOPENCLC | KEYOPENCLCXX) @@ -687,15 +561,6 @@ KEYWORD(column_major , KEYHLSL) #define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) KEYWORD(Name, KEYHLSL) #include "clang/Basic/HLSLIntangibleTypes.def" -// HLSL Type traits -TYPE_TRAIT_2(__builtin_hlsl_is_scalarized_layout_compatible, IsScalarizedLayoutCompatible, KEYHLSL) -TYPE_TRAIT_1(__builtin_hlsl_is_intangible, IsIntangibleType, KEYHLSL) -TYPE_TRAIT_1(__builtin_hlsl_is_typed_resource_element_compatible, IsTypedResourceElementCompatible, KEYHLSL) -TYPE_TRAIT_1(__builtin_hlsl_is_constant_buffer_element_compatible, IsConstantBufferElementCompatible, KEYHLSL) - -// OpenMP Type Traits -UNARY_EXPR_OR_TYPE_TRAIT(__builtin_omp_required_simd_align, OpenMPRequiredSimdAlign, KEYALL) - // Borland Extensions. KEYWORD(__pascal , KEYALL) @@ -815,7 +680,6 @@ ALIAS("_pascal" , __pascal , KEYBORLAND) // Clang Extensions. KEYWORD(__builtin_convertvector , KEYALL) -UNARY_EXPR_OR_TYPE_TRAIT(__builtin_vectorelements, VectorElements, KEYALL) ALIAS("__char16_t" , char16_t , KEYCXX) ALIAS("__char32_t" , char32_t , KEYCXX) KEYWORD(__builtin_bit_cast , KEYALL) @@ -1060,6 +924,8 @@ ANNOTATION(repl_input_end) // Annotation for #embed ANNOTATION(embed) +#include "clang/Basic/Traits.inc" + #undef PRAGMA_ANNOTATION #undef ANNOTATION #undef TESTING_KEYWORD diff --git a/clang/include/clang/Basic/Traits.td b/clang/include/clang/Basic/Traits.td new file mode 100644 index 0000000000000..d13f75b9dacd9 --- /dev/null +++ b/clang/include/clang/Basic/Traits.td @@ -0,0 +1,556 @@ +class Trait<string P> { + string Prefix = P; + string Spelling = ""; + string StdName = ""; + string KeyFlag = "KEYCXX"; +} +class TypeTrait<string P> : Trait<P>; + +class UnaryTrait : TypeTrait<"UTT">; +class BinaryTrait : TypeTrait<"BTT">; +class VariadicTrait : TypeTrait<"TT">; +class ArrayTrait : Trait<"ATT">; +class ExpressionTrait : Trait<"ET">; +class UnaryExprOrTypeTrait : Trait<"UETT">; +class CXX11UnaryExprOrTypeTrait : Trait<"UETT">; +class TransformTypeTrait : Trait<"TST">; + +// C99 6.4.1: Keywords. These turn into kw_* tokens. +def SizeOf : UnaryExprOrTypeTrait { + let Spelling = "sizeof"; + let KeyFlag = "KEYALL"; +} + +def DataSizeOf : UnaryExprOrTypeTrait { + let Spelling = "__datasizeof"; +} + +// C2y +def CountOf : UnaryExprOrTypeTrait { + let Spelling = "_Countof"; + let KeyFlag = "KEYNOCXX"; +} + +// C++11 keywords +// alignof and _Alignof return the required ABI alignment +def AlignOf : CXX11UnaryExprOrTypeTrait { + let Spelling = "alignof"; + let KeyFlag = "KEYC23"; +} + +// GNU Extensions (in impl-reserved namespace) + +// __alignof returns the preferred alignment of a type, the alignment +// clang will attempt to give an object of the type if allowed by ABI. +def PreferredAlignOf : UnaryExprOrTypeTrait { + let Spelling = "__alignof"; + let KeyFlag = "KEYALL"; +} + +// __builtin_types_compatible_p is a GNU C extension that we handle like a C++ +// type trait. +def TypeCompatible : BinaryTrait { + let Spelling = "__builtin_types_compatible_p"; + let KeyFlag = "KEYNOCXX"; +} + +// MS Extensions +def IsInterfaceClass : UnaryTrait { + let Spelling = "__is_interface_class"; + let KeyFlag = "KEYMS"; +} + +def IsSealed : UnaryTrait { + let Spelling = "__is_sealed"; + let KeyFlag = "KEYMS"; +} + +// MSVC12.0 / VS2013 Type Traits +def IsDestructible : UnaryTrait { + let Spelling = "__is_destructible"; + let KeyFlag = "KEYALL"; +} + +def IsTriviallyDestructible : UnaryTrait { + let Spelling = "__is_trivially_destructible"; +} + +def IsNothrowDestructible : UnaryTrait { + let Spelling = "__is_nothrow_destructible"; + let KeyFlag = "KEYALL"; +} + +def IsNothrowAssignable : BinaryTrait { + let Spelling = "__is_nothrow_assignable"; +} + +def IsConstructible : VariadicTrait { + let Spelling = "__is_constructible"; + let StdName = "is_constructible"; +} + +def IsNothrowConstructible : VariadicTrait { + let Spelling = "__is_nothrow_constructible"; +} + +// MSVC14.0 / VS2015 Type Traits +def IsAssignable : BinaryTrait { + let Spelling = "__is_assignable"; + let StdName = "is_assignable"; +} + +// MSVC Type Traits of unknown vintage +def HasNothrowMoveAssign : UnaryTrait { + let Spelling = "__has_nothrow_move_assign"; +} + +def HasTrivialMoveAssign : UnaryTrait { + let Spelling = "__has_trivial_move_assign"; +} + +def HasTrivialMoveConstructor : UnaryTrait { + let Spelling = "__has_trivial_move_constructor"; +} + +// GNU and MS Type Traits +def IsImplicitLifetime : UnaryTrait { + let Spelling = "__builtin_is_implicit_lifetime"; +} + +def IsVirtualBaseOf : BinaryTrait { + let Spelling = "__builtin_is_virtual_base_of"; +} + +def HasNothrowAssign : UnaryTrait { + let Spelling = "__has_nothrow_assign"; +} + +def HasNothrowCopy : UnaryTrait { + let Spelling = "__has_nothrow_copy"; +} + +def HasNothrowConstructor : UnaryTrait { + let Spelling = "__has_nothrow_constructor"; +} + +def HasTrivialAssign : UnaryTrait { + let Spelling = "__has_trivial_assign"; +} + +def HasTrivialCopy : UnaryTrait { + let Spelling = "__has_trivial_copy"; +} + +def HasTrivialDefaultConstructor : UnaryTrait { + let Spelling = "__has_trivial_constructor"; +} + +def HasTrivialDestructor : UnaryTrait { + let Spelling = "__has_trivial_destructor"; +} + +def HasVirtualDestructor : UnaryTrait { + let Spelling = "__has_virtual_destructor"; +} + +def IsAbstract : UnaryTrait { + let Spelling = "__is_abstract"; + let StdName = "is_abstract"; +} + +def IsAggregate : UnaryTrait { + let Spelling = "__is_aggregate"; + let StdName = "is_aggregate"; +} + +def IsBaseOf : BinaryTrait { + let Spelling = "__is_base_of"; +} + +def IsClass : UnaryTrait { + let Spelling = "__is_class"; +} + +def IsConvertibleTo : BinaryTrait { + let Spelling = "__is_convertible_to"; +} + +def IsEmpty : UnaryTrait { + let Spelling = "__is_empty"; + let StdName = "is_empty"; +} + +def IsEnum : UnaryTrait { + let Spelling = "__is_enum"; +} + +def IsFinal : UnaryTrait { + let Spelling = "__is_final"; + let StdName = "is_final"; +} + +def IsLiteral : UnaryTrait { + let Spelling = "__is_literal"; +} + +def IsPOD : UnaryTrait { + let Spelling = "__is_pod"; +} + +def IsPolymorphic : UnaryTrait { + let Spelling = "__is_polymorphic"; +} + +def IsStandardLayout : UnaryTrait { + let Spelling = "__is_standard_layout"; + let StdName = "is_standard_layout"; +} + +def IsTrivial : UnaryTrait { + let Spelling = "__is_trivial"; +} + +def IsTriviallyAssignable : BinaryTrait { + let Spelling = "__is_trivially_assignable"; +} + +def IsTriviallyConstructible : VariadicTrait { + let Spelling = "__is_trivially_constructible"; +} + +def IsTriviallyCopyable : UnaryTrait { + let Spelling = "__is_trivially_copyable"; + let StdName = "is_trivially_copyable"; +} + +def IsUnion : UnaryTrait { + let Spelling = "__is_union"; +} + +def HasUniqueObjectRepresentations : UnaryTrait { + let Spelling = "__has_unique_object_representations"; +} + +def IsLayoutCompatible : BinaryTrait { + let Spelling = "__is_layout_compatible"; +} + +def IsPointerInterconvertibleBaseOf : BinaryTrait { + let Spelling = "__is_pointer_interconvertible_base_of"; +} + +def AddLvalueReference : TransformTypeTrait { + let Spelling = "__add_lvalue_reference"; + let StdName = "add_lvalue_reference"; +} + +def AddPointer : TransformTypeTrait { + let Spelling = "__add_pointer"; + let StdName = "add_pointer"; +} + +def AddRvalueReference : TransformTypeTrait { + let Spelling = "__add_rvalue_reference"; + let StdName = "add_rvalue_reference"; +} + +def Decay : TransformTypeTrait { + let Spelling = "__decay"; + let StdName = "decay"; +} + +def MakeSigned : TransformTypeTrait { + let Spelling = "__make_signed"; + let StdName = "make_signed"; +} + +def MakeUnsigned : TransformTypeTrait { + let Spelling = "__make_unsigned"; + let StdName = "make_unsigned"; +} + +def RemoveAllExtents : TransformTypeTrait { + let Spelling = "__remove_all_extents"; + let StdName = "remove_all_extents"; +} + +def RemoveConst : TransformTypeTrait { + let Spelling = "__remove_const"; + let StdName = "remove_const"; +} + +def RemoveCV : TransformTypeTrait { + let Spelling = "__remove_cv"; + let StdName = "remove_cv"; +} + +def RemoveCVRef : TransformTypeTrait { + let Spelling = "__remove_cvref"; + let StdName = "remove_cvref"; +} + +def RemoveExtent : TransformTypeTrait { + let Spelling = "__remove_extent"; + let StdName = "remove_extent"; +} + +def RemovePointer : TransformTypeTrait { + let Spelling = "__remove_pointer"; + let StdName = "remove_pointer"; +} + +def RemoveReference : TransformTypeTrait { + let Spelling = "__remove_reference_t"; + let StdName = "remove_reference_t"; +} + +def RemoveRestrict : TransformTypeTrait { + let Spelling = "__remove_restrict"; + let StdName = "remove_restrict"; +} + +def RemoveVolatile : TransformTypeTrait { + let Spelling = "__remove_volatile"; + let StdName = "remove_volatile"; +} + +def EnumUnderlyingType : TransformTypeTrait { + let Spelling = "__underlying_type"; + let StdName = "underlying_type"; +} + +// Clang-only C++ Type Traits +def IsTriviallyEqualityComparable : UnaryTrait { + let Spelling = "__is_trivially_equality_comparable"; +} + +def IsBoundedArray : UnaryTrait { + let Spelling = "__is_bounded_array"; +} + +def IsUnboundedArray : UnaryTrait { + let Spelling = "__is_unbounded_array"; +} + +def IsScopedEnum : UnaryTrait { + let Spelling = "__is_scoped_enum"; +} + +def CanPassInRegs : UnaryTrait { + let Spelling = "__can_pass_in_regs"; +} + +def ReferenceBindsToTemporary : BinaryTrait { + let Spelling = "__reference_binds_to_temporary"; +} + +def ReferenceConstructsFromTemporary : BinaryTrait { + let Spelling = "__reference_constructs_from_temporary"; +} + +def ReferenceConvertsFromTemporary : BinaryTrait { + let Spelling = "__reference_converts_from_temporary"; +} + +def LtSynthesizesFromSpaceship : BinaryTrait { + let Spelling = "__builtin_lt_synthesizes_from_spaceship"; +} + +def LeSynthesizesFromSpaceship : BinaryTrait { + let Spelling = "__builtin_le_synthesizes_from_spaceship"; +} + +def GtSynthesizesFromSpaceship : BinaryTrait { + let Spelling = "__builtin_gt_synthesizes_from_spaceship"; +} + +def GeSynthesizesFromSpaceship : BinaryTrait { + let Spelling = "__builtin_ge_synthesizes_from_spaceship"; +} + +// IsDeducible is only used internally by clang for CTAD implementation and +// is not exposed to users. +def IsDeducible : BinaryTrait {} + +// __is_trivially_relocatable is deprecated +def IsCppTriviallyRelocatable : UnaryTrait { + let Spelling = "__builtin_is_cpp_trivially_relocatable"; + let StdName = "is_trivially_relocatable"; +} + +def IsTriviallyRelocatable : UnaryTrait { + let Spelling = "__is_trivially_relocatable"; +} + +def IsBitwiseCloneable : UnaryTrait { + let Spelling = "__is_bitwise_cloneable"; + let KeyFlag = "KEYALL"; +} + +def StructuredBindingSize : UnaryTrait { + let Spelling = "__builtin_structured_binding_size"; +} + +// Embarcadero Expression Traits +def IsLValueExpr : ExpressionTrait { + let Spelling = "__is_lvalue_expr"; +} + +def IsRValueExpr : ExpressionTrait { + let Spelling = "__is_rvalue_expr"; +} + +// Embarcadero Unary Type Traits +def IsArithmetic : UnaryTrait { + let Spelling = "__is_arithmetic"; +} + +def IsFloatingPoint : UnaryTrait { + let Spelling = "__is_floating_point"; +} + +def IsIntegral : UnaryTrait { + let Spelling = "__is_integral"; +} + +def IsCompleteType : UnaryTrait { + let Spelling = "__is_complete_type"; +} + +def IsVoid : UnaryTrait { + let Spelling = "__is_void"; +} + +def IsArray : UnaryTrait { + let Spelling = "__is_array"; +} + +def IsFunction : UnaryTrait { + let Spelling = "__is_function"; +} + +def IsReference : UnaryTrait { + let Spelling = "__is_reference"; +} + +def IsLvalueReference : UnaryTrait { + let Spelling = "__is_lvalue_reference"; +} + +def IsRvalueReference : UnaryTrait { + let Spelling = "__is_rvalue_reference"; +} + +def IsFundamental : UnaryTrait { + let Spelling = "__is_fundamental"; +} + +def IsObject : UnaryTrait { + let Spelling = "__is_object"; +} + +def IsScalar : UnaryTrait { + let Spelling = "__is_scalar"; +} + +def IsCompound : UnaryTrait { + let Spelling = "__is_compound"; +} + +def IsPointer : UnaryTrait { + let Spelling = "__is_pointer"; +} + +def IsMemberObjectPointer : UnaryTrait { + let Spelling = "__is_member_object_pointer"; +} + +def IsMemberFunctionPointer : UnaryTrait { + let Spelling = "__is_member_function_pointer"; +} + +def IsMemberPointer : UnaryTrait { + let Spelling = "__is_member_pointer"; +} + +def IsConst : UnaryTrait { + let Spelling = "__is_const"; +} + +def IsVolatile : UnaryTrait { + let Spelling = "__is_volatile"; +} + +def IsSigned : UnaryTrait { + let Spelling = "__is_signed"; +} + +def IsUnsigned : UnaryTrait { + let Spelling = "__is_unsigned"; +} + +// Embarcadero Binary Type Traits +def IsSame : BinaryTrait { + let Spelling = "__is_same"; +} + +def IsConvertible : BinaryTrait { + let Spelling = "__is_convertible"; +} + +def IsNothrowConvertible : BinaryTrait { + let Spelling = "__is_nothrow_convertible"; +} + +def ArrayRank : ArrayTrait { + let Spelling = "__array_rank"; +} + +def ArrayExtent : ArrayTrait { + let Spelling = "__array_extent"; +} + +// Apple Extension. +def PtrAuthTypeDiscriminator : UnaryExprOrTypeTrait { + let Spelling = "__builtin_ptrauth_type_discriminator"; + let KeyFlag = "KEYALL"; +} + +// OpenCL builtins +def VecStep : UnaryExprOrTypeTrait { + let Spelling = "vec_step"; + let KeyFlag = "KEYOPENCLC | KEYOPENCLCXX | KEYALTIVEC | KEYZVECTOR"; +} + +// HLSL Type traits +def IsScalarizedLayoutCompatible : BinaryTrait { + let Spelling = "__builtin_hlsl_is_scalarized_layout_compatible"; + let KeyFlag = "KEYHLSL"; +} + +def IsIntangibleType : UnaryTrait { + let Spelling = "__builtin_hlsl_is_intangible"; + let KeyFlag = "KEYHLSL"; +} + +def IsTypedResourceElementCompatible : UnaryTrait { + let Spelling = "__builtin_hlsl_is_typed_resource_element_compatible"; + let KeyFlag = "KEYHLSL"; +} + +def IsConstantBufferElementCompatible : UnaryTrait { + let Spelling = "__builtin_hlsl_is_constant_buffer_element_compatible"; + let KeyFlag = "KEYHLSL"; +} + +// OpenMP Type Traits +def OpenMPRequiredSimdAlign : UnaryExprOrTypeTrait { + let Spelling = "__builtin_omp_required_simd_align"; + let KeyFlag = "KEYALL"; +} + +// Clang Extensions. +def VectorElements : UnaryExprOrTypeTrait { + let Spelling = "__builtin_vectorelements"; + let KeyFlag = "KEYALL"; +} diff --git a/clang/include/clang/Basic/TransformTypeTraits.def b/clang/include/clang/Basic/TransformTypeTraits.def deleted file mode 100644 index e27a2719a9680..0000000000000 --- a/clang/include/clang/Basic/TransformTypeTraits.def +++ /dev/null @@ -1,29 +0,0 @@ -//==--- TransformTypeTraits.def - type trait transformations --------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines transform type traits' names. -// -//===----------------------------------------------------------------------===// - -TRANSFORM_TYPE_TRAIT_DEF(AddLvalueReference, add_lvalue_reference) -TRANSFORM_TYPE_TRAIT_DEF(AddPointer, add_pointer) -TRANSFORM_TYPE_TRAIT_DEF(AddRvalueReference, add_rvalue_reference) -TRANSFORM_TYPE_TRAIT_DEF(Decay, decay) -TRANSFORM_TYPE_TRAIT_DEF(MakeSigned, make_signed) -TRANSFORM_TYPE_TRAIT_DEF(MakeUnsigned, make_unsigned) -TRANSFORM_TYPE_TRAIT_DEF(RemoveAllExtents, remove_all_extents) -TRANSFORM_TYPE_TRAIT_DEF(RemoveConst, remove_const) -TRANSFORM_TYPE_TRAIT_DEF(RemoveCV, remove_cv) -TRANSFORM_TYPE_TRAIT_DEF(RemoveCVRef, remove_cvref) -TRANSFORM_TYPE_TRAIT_DEF(RemoveExtent, remove_extent) -TRANSFORM_TYPE_TRAIT_DEF(RemovePointer, remove_pointer) -TRANSFORM_TYPE_TRAIT_DEF(RemoveReference, remove_reference_t) -TRANSFORM_TYPE_TRAIT_DEF(RemoveRestrict, remove_restrict) -TRANSFORM_TYPE_TRAIT_DEF(RemoveVolatile, remove_volatile) -TRANSFORM_TYPE_TRAIT_DEF(EnumUnderlyingType, underlying_type) -#undef TRANSFORM_TYPE_TRAIT_DEF diff --git a/clang/include/clang/Basic/TypeTraits.h b/clang/include/clang/Basic/TypeTraits.h index eb8b1923152db..017b8699de89e 100644 --- a/clang/include/clang/Basic/TypeTraits.h +++ b/clang/include/clang/Basic/TypeTraits.h @@ -18,45 +18,28 @@ namespace clang { /// Names for traits that operate specifically on types. -enum TypeTrait { -#define TYPE_TRAIT_1(Spelling, Name, Key) UTT_##Name, -#include "clang/Basic/TokenKinds.def" - UTT_Last = -1 // UTT_Last == last UTT_XX in the enum. -#define TYPE_TRAIT_1(Spelling, Name, Key) +1 -#include "clang/Basic/TokenKinds.def" - , -#define TYPE_TRAIT_2(Spelling, Name, Key) BTT_##Name, -#include "clang/Basic/TokenKinds.def" - BTT_Last = UTT_Last // BTT_Last == last BTT_XX in the enum. -#define TYPE_TRAIT_2(Spelling, Name, Key) +1 -#include "clang/Basic/TokenKinds.def" - , -#define TYPE_TRAIT_N(Spelling, Name, Key) TT_##Name, -#include "clang/Basic/TokenKinds.def" - TT_Last = BTT_Last // TT_Last == last TT_XX in the enum. -#define TYPE_TRAIT_N(Spelling, Name, Key) +1 -#include "clang/Basic/TokenKinds.def" -}; +// enum TypeTrait { +// UTT_ ... +// UTT_Last == last UTT_XX in the enum. +// BTT_ ... +// BTT_Last == last BTT_XX in the enum. +// TT_ ... +// TT_Last == last TT_XX in the enum. +// }; /// Names for the array type traits. -enum ArrayTypeTrait { -#define ARRAY_TYPE_TRAIT(Spelling, Name, Key) ATT_##Name, -#include "clang/Basic/TokenKinds.def" - ATT_Last = -1 // ATT_Last == last ATT_XX in the enum. -#define ARRAY_TYPE_TRAIT(Spelling, Name, Key) +1 -#include "clang/Basic/TokenKinds.def" -}; +// enum ArrayTypeTrait { +// ATT_ ... +// ATT_Last == last ATT_XX in the enum. +// }; /// Names for the "expression or type" traits. -enum UnaryExprOrTypeTrait { -#define UNARY_EXPR_OR_TYPE_TRAIT(Spelling, Name, Key) UETT_##Name, -#define CXX11_UNARY_EXPR_OR_TYPE_TRAIT(Spelling, Name, Key) UETT_##Name, -#include "clang/Basic/TokenKinds.def" - UETT_Last = -1 // UETT_Last == last UETT_XX in the enum. -#define UNARY_EXPR_OR_TYPE_TRAIT(Spelling, Name, Key) +1 -#define CXX11_UNARY_EXPR_OR_TYPE_TRAIT(Spelling, Name, Key) +1 -#include "clang/Basic/TokenKinds.def" -}; +// enum UnaryExprOrTypeTrait { +// UETT_ ... +// UETT_Last == last UETT_XX in the enum. +// }; +#define EMIT_ENUMS +#include "clang/Basic/Traits.inc" /// Return the internal name of type trait \p T. Never null. const char *getTraitName(TypeTrait T) LLVM_READONLY; diff --git a/clang/include/clang/Sema/DeclSpec.h b/clang/include/clang/Sema/DeclSpec.h index b3c459821c79c..6edac57e04d7d 100644 --- a/clang/include/clang/Sema/DeclSpec.h +++ b/clang/include/clang/Sema/DeclSpec.h @@ -287,7 +287,7 @@ class DeclSpec { clang::TST_typename_pack_indexing; #define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) \ static const TST TST_##Trait = clang::TST_##Trait; -#include "clang/Basic/TransformTypeTraits.def" +#include "clang/Basic/Traits.inc" static const TST TST_auto = clang::TST_auto; static const TST TST_auto_type = clang::TST_auto_type; static const TST TST_unknown_anytype = clang::TST_unknown_anytype; @@ -458,7 +458,7 @@ class DeclSpec { static bool isTransformTypeTrait(TST T) { constexpr std::array<TST, 16> Traits = { #define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) TST_##Trait, -#include "clang/Basic/TransformTypeTraits.def" +#include "clang/Basic/Traits.inc" }; return T >= Traits.front() && T <= Traits.back(); diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index 2e74aeb558e3d..f19ed5ae855a6 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -4569,7 +4569,7 @@ void CXXNameMangler::mangleType(const UnaryTransformType *T) { case UnaryTransformType::Enum: \ BuiltinName = "__" #Trait; \ break; -#include "clang/Basic/TransformTypeTraits.def" +#include "clang/Basic/Traits.inc" } mangleVendorType(BuiltinName); } diff --git a/clang/lib/AST/JSONNodeDumper.cpp b/clang/lib/AST/JSONNodeDumper.cpp index 8373dd8e373e0..428ec70f2f129 100644 --- a/clang/lib/AST/JSONNodeDumper.cpp +++ b/clang/lib/AST/JSONNodeDumper.cpp @@ -771,7 +771,7 @@ void JSONNodeDumper::VisitUnaryTransformType(const UnaryTransformType *UTT) { case UnaryTransformType::Enum: \ JOS.attribute("transformKind", #Trait); \ break; -#include "clang/Basic/TransformTypeTraits.def" +#include "clang/Basic/Traits.inc" } } diff --git a/clang/lib/AST/TextNodeDumper.cpp b/clang/lib/AST/TextNodeDumper.cpp index 2b1c0cac25b6d..67dc947eb4b09 100644 --- a/clang/lib/AST/TextNodeDumper.cpp +++ b/clang/lib/AST/TextNodeDumper.cpp @@ -2212,7 +2212,7 @@ void TextNodeDumper::VisitUnaryTransformType(const UnaryTransformType *T) { case UnaryTransformType::Enum: \ OS << " " #Trait; \ break; -#include "clang/Basic/TransformTypeTraits.def" +#include "clang/Basic/Traits.inc" } } diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp index d85ed244f643a..9216a7737d9d3 100644 --- a/clang/lib/AST/TypePrinter.cpp +++ b/clang/lib/AST/TypePrinter.cpp @@ -1370,7 +1370,7 @@ void TypePrinter::printUnaryTransformBefore(const UnaryTransformType *T, static const llvm::DenseMap<int, const char *> Transformation = {{ #define TRANSFORM_TYPE_TRAIT_DEF(Enum, Trait) \ {UnaryTransformType::Enum, "__" #Trait}, -#include "clang/Basic/TransformTypeTraits.def" +#include "clang/Basic/Traits.inc" }}; OS << Transformation.lookup(T->getUTTKind()) << '('; print(T->getBaseType(), OS, StringRef()); diff --git a/clang/lib/ASTMatchers/Dynamic/Marshallers.cpp b/clang/lib/ASTMatchers/Dynamic/Marshallers.cpp index 37c91abb5c839..155bc08e5d45f 100644 --- a/clang/lib/ASTMatchers/Dynamic/Marshallers.cpp +++ b/clang/lib/ASTMatchers/Dynamic/Marshallers.cpp @@ -102,7 +102,7 @@ clang::ast_matchers::dynamic::internal::ArgTypeTraits< static constexpr llvm::StringRef Allowed[] = { #define UNARY_EXPR_OR_TYPE_TRAIT(Spelling, Name, Key) "UETT_" #Name, #define CXX11_UNARY_EXPR_OR_TYPE_TRAIT(Spelling, Name, Key) "UETT_" #Name, -#include "clang/Basic/TokenKinds.def" +#include "clang/Basic/Traits.inc" }; if (Value.isString()) return ::getBestGuess(Value.getString(), llvm::ArrayRef(Allowed), "UETT_"); diff --git a/clang/lib/ASTMatchers/Dynamic/Marshallers.h b/clang/lib/ASTMatchers/Dynamic/Marshallers.h index d44e42a524f27..6c88ebc7252a0 100644 --- a/clang/lib/ASTMatchers/Dynamic/Marshallers.h +++ b/clang/lib/ASTMatchers/Dynamic/Marshallers.h @@ -276,7 +276,7 @@ template <> struct ArgTypeTraits<UnaryExprOrTypeTrait> { #define UNARY_EXPR_OR_TYPE_TRAIT(Spelling, Name, Key) .Case(#Name, UETT_##Name) #define CXX11_UNARY_EXPR_OR_TYPE_TRAIT(Spelling, Name, Key) \ .Case(#Name, UETT_##Name) -#include "clang/Basic/TokenKinds.def" +#include "clang/Basic/Traits.inc" .Default(std::nullopt); } diff --git a/clang/lib/Basic/ExpressionTraits.cpp b/clang/lib/Basic/ExpressionTraits.cpp index 0d642f7149130..67126ff1d8a05 100644 --- a/clang/lib/Basic/ExpressionTraits.cpp +++ b/clang/lib/Basic/ExpressionTraits.cpp @@ -16,12 +16,12 @@ using namespace clang; static constexpr const char *ExpressionTraitNames[] = { #define EXPRESSION_TRAIT(Spelling, Name, Key) #Name, -#include "clang/Basic/TokenKinds.def" +#include "clang/Basic/Traits.inc" }; static constexpr const char *ExpressionTraitSpellings[] = { #define EXPRESSION_TRAIT(Spelling, Name, Key) #Spelling, -#include "clang/Basic/TokenKinds.def" +#include "clang/Basic/Traits.inc" }; const char *clang::getTraitName(ExpressionTrait T) { diff --git a/clang/lib/Basic/TypeTraits.cpp b/clang/lib/Basic/TypeTraits.cpp index bd88186bf911c..8307cf9e5afbd 100644 --- a/clang/lib/Basic/TypeTraits.cpp +++ b/clang/lib/Basic/TypeTraits.cpp @@ -15,54 +15,15 @@ #include <cstring> using namespace clang; -static constexpr const char *TypeTraitNames[] = { -#define TYPE_TRAIT_1(Spelling, Name, Key) #Name, -#include "clang/Basic/TokenKinds.def" -#define TYPE_TRAIT_2(Spelling, Name, Key) #Name, -#include "clang/Basic/TokenKinds.def" -#define TYPE_TRAIT_N(Spelling, Name, Key) #Name, -#include "clang/Basic/TokenKinds.def" -}; - -static constexpr const char *TypeTraitSpellings[] = { -#define TYPE_TRAIT_1(Spelling, Name, Key) #Spelling, -#include "clang/Basic/TokenKinds.def" -#define TYPE_TRAIT_2(Spelling, Name, Key) #Spelling, -#include "clang/Basic/TokenKinds.def" -#define TYPE_TRAIT_N(Spelling, Name, Key) #Spelling, -#include "clang/Basic/TokenKinds.def" -}; - -static constexpr const char *ArrayTypeTraitNames[] = { -#define ARRAY_TYPE_TRAIT(Spelling, Name, Key) #Name, -#include "clang/Basic/TokenKinds.def" -}; - -static constexpr const char *ArrayTypeTraitSpellings[] = { -#define ARRAY_TYPE_TRAIT(Spelling, Name, Key) #Spelling, -#include "clang/Basic/TokenKinds.def" -}; - -static constexpr const char *UnaryExprOrTypeTraitNames[] = { -#define UNARY_EXPR_OR_TYPE_TRAIT(Spelling, Name, Key) #Name, -#define CXX11_UNARY_EXPR_OR_TYPE_TRAIT(Spelling, Name, Key) #Name, -#include "clang/Basic/TokenKinds.def" -}; - -static constexpr const char *UnaryExprOrTypeTraitSpellings[] = { -#define UNARY_EXPR_OR_TYPE_TRAIT(Spelling, Name, Key) #Spelling, -#define CXX11_UNARY_EXPR_OR_TYPE_TRAIT(Spelling, Name, Key) #Spelling, -#include "clang/Basic/TokenKinds.def" -}; - -static constexpr const unsigned TypeTraitArities[] = { -#define TYPE_TRAIT_1(Spelling, Name, Key) 1, -#include "clang/Basic/TokenKinds.def" -#define TYPE_TRAIT_2(Spelling, Name, Key) 2, -#include "clang/Basic/TokenKinds.def" -#define TYPE_TRAIT_N(Spelling, Name, Key) 0, -#include "clang/Basic/TokenKinds.def" -}; +// static constexpr const char *TypeTraitNames[] = {...}; +// static constexpr const char *TypeTraitSpellings[] = {...}; +// static constexpr const char *ArrayTypeTraitNames[] = {...}; +// static constexpr const char *ArrayTypeTraitSpellings[] = {...}; +// static constexpr const char *UnaryExprOrTypeTraitNames[] = {...}; +// static constexpr const char *UnaryExprOrTypeTraitSpellings[] = {...}; +// static constexpr const unsigned TypeTraitArities[] = {...}; +#define EMIT_ARRAYS +#include "clang/Basic/Traits.inc" const char *clang::getTraitName(TypeTrait T) { assert(T <= TT_Last && "invalid enum value!"); diff --git a/clang/lib/Format/FormatToken.h b/clang/lib/Format/FormatToken.h index 556bb0f3dd0af..d4442b3e94f96 100644 --- a/clang/lib/Format/FormatToken.h +++ b/clang/lib/Format/FormatToken.h @@ -827,7 +827,7 @@ struct FormatToken { tok::kw_decltype, tok::kw_noexcept, tok::kw_static_assert, tok::kw__Atomic, #define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) tok::kw___##Trait, -#include "clang/Basic/TransformTypeTraits.def" +#include "clang/Basic/Traits.inc" tok::kw_requires); } diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index 43e4f6796b6dd..8dd87faf774ca 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -449,7 +449,7 @@ class AnnotatingParser { } else if (PrevNonComment->isOneOf(TT_TypenameMacro, tok::kw_decltype, tok::kw_typeof, #define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) tok::kw___##Trait, -#include "clang/Basic/TransformTypeTraits.def" +#include "clang/Basic/Traits.inc" tok::kw__Atomic)) { OpeningParen.setType(TT_TypeDeclarationParen); // decltype() and typeof() usually contain expressions. diff --git a/clang/lib/Lex/Lexer.cpp b/clang/lib/Lex/Lexer.cpp index 2797212c229f5..eb7031bf2b65f 100644 --- a/clang/lib/Lex/Lexer.cpp +++ b/clang/lib/Lex/Lexer.cpp @@ -115,7 +115,7 @@ bool Token::isSimpleTypeSpecifier(const LangOptions &LangOpts) const { case tok::kw__Fract: case tok::kw__Sat: #define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) case tok::kw___##Trait: -#include "clang/Basic/TransformTypeTraits.def" +#include "clang/Basic/Traits.inc" case tok::kw___auto_type: case tok::kw_char16_t: case tok::kw_char32_t: diff --git a/clang/lib/Lex/PPMacroExpansion.cpp b/clang/lib/Lex/PPMacroExpansion.cpp index 5fd3512d2f45c..b600c7332ae73 100644 --- a/clang/lib/Lex/PPMacroExpansion.cpp +++ b/clang/lib/Lex/PPMacroExpansion.cpp @@ -1573,7 +1573,7 @@ static bool IsBuiltinTrait(Token &Tok) { switch (Tok.getKind()) { default: return false; -#include "clang/Basic/TokenKinds.def" +#include "clang/Basic/Traits.inc" } } diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 405dddf7991b4..2105af9ba66b4 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -4603,7 +4603,7 @@ void Parser::ParseDeclarationSpecifiers( continue; #define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) case tok::kw___##Trait: -#include "clang/Basic/TransformTypeTraits.def" +#include "clang/Basic/Traits.inc" // HACK: libstdc++ already uses '__remove_cv' as an alias template so we // work around this by expecting all transform type traits to be suffixed // with '('. They're an identifier otherwise. diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index 893989bd2398f..292ff93907b0b 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -1241,7 +1241,7 @@ DeclSpec::TST Parser::TypeTransformTokToDeclSpec() { #define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) \ case tok::kw___##Trait: \ return DeclSpec::TST_##Trait; -#include "clang/Basic/TransformTypeTraits.def" +#include "clang/Basic/Traits.inc" default: llvm_unreachable("passed in an unhandled type transformation built-in"); } @@ -1604,64 +1604,32 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, !Tok.isAnnotation() && Tok.getIdentifierInfo() && 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_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, +#include "clang/Basic/Traits.inc" + 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_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 diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp index 2987d32d6e0d2..cde0f1672e4b5 100644 --- a/clang/lib/Parse/ParseExpr.cpp +++ b/clang/lib/Parse/ParseExpr.cpp @@ -710,7 +710,7 @@ bool Parser::isRevertibleTypeTrait(const IdentifierInfo *II, REVERTIBLE_TYPE_TRAIT(__reference_binds_to_temporary); #define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) \ REVERTIBLE_TYPE_TRAIT(RTT_JOIN(__, Trait)); -#include "clang/Basic/TransformTypeTraits.def" +#include "clang/Basic/Traits.inc" #undef REVERTIBLE_TYPE_TRAIT #undef RTT_JOIN } @@ -1563,7 +1563,7 @@ Parser::ParseCastExpression(CastParseKind ParseKind, bool isAddressOfOperand, return ExprError(); } #define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) case tok::kw___##Trait: -#include "clang/Basic/TransformTypeTraits.def" +#include "clang/Basic/Traits.inc" // HACK: libstdc++ uses some of the transform-type-traits as alias // templates, so we need to work around this. if (!NextToken().is(tok::l_paren)) { diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp index ae49fc20e36f2..741c5812adb29 100644 --- a/clang/lib/Parse/ParseExprCXX.cpp +++ b/clang/lib/Parse/ParseExprCXX.cpp @@ -375,7 +375,7 @@ bool Parser::ParseOptionalCXXScopeSpecifier( switch (Tok.getKind()) { #define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) case tok::kw___##Trait: -#include "clang/Basic/TransformTypeTraits.def" +#include "clang/Basic/Traits.inc" if (!NextToken().is(tok::l_paren)) { Tok.setKind(tok::identifier); Diag(Tok, diag::ext_keyword_as_ident) @@ -2823,7 +2823,7 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, ParsedType ObjectType, switch (Tok.getKind()) { #define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) case tok::kw___##Trait: -#include "clang/Basic/TransformTypeTraits.def" +#include "clang/Basic/Traits.inc" if (!NextToken().is(tok::l_paren)) { Tok.setKind(tok::identifier); Diag(Tok, diag::ext_keyword_as_ident) @@ -3404,9 +3404,10 @@ case tok::kw_ ## Spelling: return UTT_ ## Name; #define TYPE_TRAIT_2(Spelling, Name, Key) \ case tok::kw_ ## Spelling: return BTT_ ## Name; #include "clang/Basic/TokenKinds.def" -#define TYPE_TRAIT_N(Spelling, Name, Key) \ - case tok::kw_ ## Spelling: return TT_ ## Name; -#include "clang/Basic/TokenKinds.def" +#define TYPE_TRAIT_N(Spelling, Name, Key) \ + case tok::kw_##Spelling: \ + return TT_##Name; +#include "clang/Basic/Traits.inc" } } @@ -3417,7 +3418,7 @@ static ArrayTypeTrait ArrayTypeTraitFromTokKind(tok::TokenKind kind) { #define ARRAY_TYPE_TRAIT(Spelling, Name, Key) \ case tok::kw_##Spelling: \ return ATT_##Name; -#include "clang/Basic/TokenKinds.def" +#include "clang/Basic/Traits.inc" } } @@ -3428,7 +3429,7 @@ static ExpressionTrait ExpressionTraitFromTokKind(tok::TokenKind kind) { #define EXPRESSION_TRAIT(Spelling, Name, Key) \ case tok::kw_##Spelling: \ return ET_##Name; -#include "clang/Basic/TokenKinds.def" +#include "clang/Basic/Traits.inc" } } diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp index 37f142e059930..2c98f853250e6 100644 --- a/clang/lib/Parse/ParseStmt.cpp +++ b/clang/lib/Parse/ParseStmt.cpp @@ -241,7 +241,7 @@ StmtResult Parser::ParseStatementOrDeclarationAfterAttributes( switch (Tok.getKind()) { #define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) case tok::kw___##Trait: -#include "clang/Basic/TransformTypeTraits.def" +#include "clang/Basic/Traits.inc" if (NextToken().is(tok::less)) { Tok.setKind(tok::identifier); Diag(Tok, diag::ext_keyword_as_ident) diff --git a/clang/lib/Parse/ParseTentative.cpp b/clang/lib/Parse/ParseTentative.cpp index 1477fc38bcc6d..61bcd17c3a0f3 100644 --- a/clang/lib/Parse/ParseTentative.cpp +++ b/clang/lib/Parse/ParseTentative.cpp @@ -174,7 +174,7 @@ Parser::TPResult Parser::TryConsumeDeclarationSpecifier() { case tok::kw_typeof_unqual: case tok::kw___attribute: #define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) case tok::kw___##Trait: -#include "clang/Basic/TransformTypeTraits.def" +#include "clang/Basic/Traits.inc" { ConsumeToken(); if (Tok.isNot(tok::l_paren)) @@ -1550,7 +1550,7 @@ Parser::isCXXDeclarationSpecifier(ImplicitTypenameContext AllowImplicitTypename, } #define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) case tok::kw___##Trait: -#include "clang/Basic/TransformTypeTraits.def" +#include "clang/Basic/Traits.inc" return TPResult::True; // C11 _Alignas @@ -1594,7 +1594,7 @@ bool Parser::isCXXDeclarationSpecifierAType() { case tok::kw_typeof: case tok::kw_typeof_unqual: #define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) case tok::kw___##Trait: -#include "clang/Basic/TransformTypeTraits.def" +#include "clang/Basic/Traits.inc" return true; // elaborated-type-specifier diff --git a/clang/lib/Sema/DeclSpec.cpp b/clang/lib/Sema/DeclSpec.cpp index 660b1805c450e..b7c067de8a6c4 100644 --- a/clang/lib/Sema/DeclSpec.cpp +++ b/clang/lib/Sema/DeclSpec.cpp @@ -365,7 +365,7 @@ bool Declarator::isDeclarationOfFunction() const { return false; #define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) case TST_##Trait: -#include "clang/Basic/TransformTypeTraits.def" +#include "clang/Basic/Traits.inc" case TST_typename: case TST_typeof_unqualType: case TST_typeofType: { @@ -573,9 +573,11 @@ const char *DeclSpec::getSpecifierName(DeclSpec::TST T, #define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) \ case DeclSpec::TST_##Trait: \ return "__" #Trait; -#include "clang/Basic/TransformTypeTraits.def" - case DeclSpec::TST_unknown_anytype: return "__unknown_anytype"; - case DeclSpec::TST_atomic: return "_Atomic"; +#include "clang/Basic/Traits.inc" + case DeclSpec::TST_unknown_anytype: + return "__unknown_anytype"; + case DeclSpec::TST_atomic: + return "_Atomic"; case DeclSpec::TST_BFloat16: return "__bf16"; #define GENERIC_IMAGE_TYPE(ImgType, Id) \ case DeclSpec::TST_##ImgType##_t: \ diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index cddcf3a010279..fdab838d37862 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -6225,7 +6225,7 @@ static bool RebuildDeclaratorInCurrentInstantiation(Sema &S, Declarator &D, case DeclSpec::TST_typeofType: case DeclSpec::TST_typeof_unqualType: #define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) case DeclSpec::TST_##Trait: -#include "clang/Basic/TransformTypeTraits.def" +#include "clang/Basic/Traits.inc" case DeclSpec::TST_atomic: { // Grab the type from the parser. TypeSourceInfo *TSI = nullptr; diff --git a/clang/lib/Sema/SemaTemplateVariadic.cpp b/clang/lib/Sema/SemaTemplateVariadic.cpp index 5b1aad3fa8470..b0d9d0c8e9ffa 100644 --- a/clang/lib/Sema/SemaTemplateVariadic.cpp +++ b/clang/lib/Sema/SemaTemplateVariadic.cpp @@ -1141,7 +1141,7 @@ bool Sema::containsUnexpandedParameterPacks(Declarator &D) { case TST_typeof_unqualType: case TST_typeofType: #define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) case TST_##Trait: -#include "clang/Basic/TransformTypeTraits.def" +#include "clang/Basic/Traits.inc" case TST_atomic: { QualType T = DS.getRepAsType().get(); if (!T.isNull() && T->containsUnexpandedParameterPack()) diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 6283fe4f41f36..f15829d530c94 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -888,7 +888,7 @@ TSTToUnaryTransformType(DeclSpec::TST SwitchTST) { #define TRANSFORM_TYPE_TRAIT_DEF(Enum, Trait) \ case TST_##Trait: \ return UnaryTransformType::Enum; -#include "clang/Basic/TransformTypeTraits.def" +#include "clang/Basic/Traits.inc" default: llvm_unreachable("attempted to parse a non-unary transform builtin"); } @@ -1308,7 +1308,7 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { } #define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) case DeclSpec::TST_##Trait: -#include "clang/Basic/TransformTypeTraits.def" +#include "clang/Basic/Traits.inc" Result = S.GetTypeFromParser(DS.getRepAsType()); assert(!Result.isNull() && "Didn't get a type for the transformation?"); Result = S.BuildUnaryTransformType( diff --git a/clang/lib/Sema/SemaTypeTraits.cpp b/clang/lib/Sema/SemaTypeTraits.cpp index c79b3f7045ca6..9e52c8b7007b8 100644 --- a/clang/lib/Sema/SemaTypeTraits.cpp +++ b/clang/lib/Sema/SemaTypeTraits.cpp @@ -1953,16 +1953,8 @@ ExprResult Sema::BuildExpressionTrait(ExpressionTrait ET, SourceLocation KWLoc, static std::optional<TypeTrait> StdNameToTypeTrait(StringRef Name) { return llvm::StringSwitch<std::optional<TypeTrait>>(Name) - .Case("is_trivially_relocatable", - TypeTrait::UTT_IsCppTriviallyRelocatable) - .Case("is_trivially_copyable", TypeTrait::UTT_IsTriviallyCopyable) - .Case("is_assignable", TypeTrait::BTT_IsAssignable) - .Case("is_empty", TypeTrait::UTT_IsEmpty) - .Case("is_standard_layout", TypeTrait::UTT_IsStandardLayout) - .Case("is_aggregate", TypeTrait::UTT_IsAggregate) - .Case("is_constructible", TypeTrait::TT_IsConstructible) - .Case("is_final", TypeTrait::UTT_IsFinal) - .Case("is_abstract", TypeTrait::UTT_IsAbstract) +#define EMIT_STD_NAME_CASES +#include "clang/Basic/Traits.inc" .Default(std::nullopt); } diff --git a/clang/utils/TableGen/CMakeLists.txt b/clang/utils/TableGen/CMakeLists.txt index 8b5e00c189cb9..722a14bf609ee 100644 --- a/clang/utils/TableGen/CMakeLists.txt +++ b/clang/utils/TableGen/CMakeLists.txt @@ -21,6 +21,7 @@ add_tablegen(clang-tblgen CLANG ClangSACheckersEmitter.cpp ClangSyntaxEmitter.cpp ClangTypeNodesEmitter.cpp + ClangTraitsEmitter.cpp HLSLEmitter.cpp MveEmitter.cpp NeonEmitter.cpp diff --git a/clang/utils/TableGen/ClangTraitsEmitter.cpp b/clang/utils/TableGen/ClangTraitsEmitter.cpp new file mode 100644 index 0000000000000..f7cbc1ea521e6 --- /dev/null +++ b/clang/utils/TableGen/ClangTraitsEmitter.cpp @@ -0,0 +1,195 @@ +#include "TableGenBackends.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/TableGen/Record.h" + +using namespace llvm; + +namespace { + +StringRef recordKindToMacro(const Record *R) { + if (R->isSubClassOf("UnaryTrait")) + return "TYPE_TRAIT_1"; + if (R->isSubClassOf("BinaryTrait")) + return "TYPE_TRAIT_2"; + if (R->isSubClassOf("VariadicTrait")) + return "TYPE_TRAIT_N"; + if (R->isSubClassOf("ArrayTrait")) + return "ARRAY_TYPE_TRAIT"; + if (R->isSubClassOf("ExpressionTrait")) + return "EXPRESSION_TRAIT"; + if (R->isSubClassOf("UnaryExprOrTypeTrait")) + return "UNARY_EXPR_OR_TYPE_TRAIT"; + if (R->isSubClassOf("CXX11UnaryExprOrTypeTrait")) + return "CXX11_UNARY_EXPR_OR_TYPE_TRAIT"; + if (R->isSubClassOf("TransformTypeTrait")) + return "TRANSFORM_TYPE_TRAIT_DEF"; + + llvm_unreachable("unexpected Trait subclass"); +} + +void emitMacro(const Record *R, raw_ostream &OS) { + OS << recordKindToMacro(R) << "("; + if (R->isSubClassOf("TransformTypeTrait")) { + const StringRef StdName = R->getValueAsString("StdName"); + OS << R->getName() << ", " << StdName; + } else { + OS << R->getValueAsString("Spelling") << ", " << R->getName() << ", " + << R->getValueAsString("KeyFlag"); + } + OS << ")\n"; +} + +void emitMacroDefs(const RecordKeeper &Records, raw_ostream &OS) { + constexpr std::pair<StringRef, StringRef> MacroDefs[] = { + {"TYPE_TRAIT_1", "(I,E,K)"}, + {"TYPE_TRAIT_2", "(I,E,K)"}, + {"TYPE_TRAIT_N", "(I,E,K)"}, + {"ARRAY_TYPE_TRAIT", "(I,E,K)"}, + {"UNARY_EXPR_OR_TYPE_TRAIT", "(I,E,K)"}, + {"CXX11_UNARY_EXPR_OR_TYPE_TRAIT", "(I,E,K)"}, + {"EXPRESSION_TRAIT", "(I,E,K)"}, + {"TRANSFORM_TYPE_TRAIT_DEF", "(K, Trait)"}, + }; + + for (const auto &[MacroName, MacroArgs] : MacroDefs) { + OS << "#ifndef " << MacroName << "\n" + << "#define " << MacroName << MacroArgs << "\n" + << "#endif\n"; + } + + OS << '\n'; + + for (const Record *R : Records.getAllDerivedDefinitions("Trait")) + emitMacro(R, OS); + + for (const auto &[MacroName, _] : reverse(MacroDefs)) + OS << "#undef " << MacroName << "\n"; +} + +template <typename RangeT> +void emitEnumerators(raw_ostream &OS, RangeT &&Range) { + for (const Record *R : Range) + OS << " " << R->getValueAsString("Prefix") << '_' << R->getName() << ",\n"; +} + +void emitEnums(const RecordKeeper &Records, raw_ostream &OS) { + const auto UnaryTraits = Records.getAllDerivedDefinitions("UnaryTrait"); + const auto BinaryTraits = Records.getAllDerivedDefinitions("BinaryTrait"); + const auto VariadicTraits = Records.getAllDerivedDefinitions("VariadicTrait"); + + OS << "/// Names for traits that operate specifically on types.\n" + "enum TypeTrait {\n"; + emitEnumerators(OS, UnaryTraits); + OS << " UTT_Last = " << UnaryTraits.size() - 1 + << ", // UTT_Last == last UTT_XX in the enum.\n"; + + emitEnumerators(OS, BinaryTraits); + OS << " BTT_Last = " << UnaryTraits.size() + BinaryTraits.size() - 1 + << ", // BTT_Last == last BTT_XX in the enum.\n"; + + emitEnumerators(OS, VariadicTraits); + OS << " TT_Last = " + << UnaryTraits.size() + BinaryTraits.size() + VariadicTraits.size() - 1 + << " // TT_Last == last TT_XX in the enum.\n" + << "};\n\n"; + + const auto ArrayTraits = Records.getAllDerivedDefinitions("ArrayTrait"); + OS << "/// Names for the array type traits.\n" + "enum ArrayTypeTrait {\n"; + emitEnumerators(OS, ArrayTraits); + OS << " ATT_Last = " << ArrayTraits.size() - 1 + << " // ATT_Last == last ATT\n" + << "};\n\n"; + + const auto UETTs = Records.getAllDerivedDefinitions("UnaryExprOrTypeTrait"); + const auto CXX11UETTs = + Records.getAllDerivedDefinitions("CXX11UnaryExprOrTypeTrait"); + OS << "/// Names for the \"expression or type\" traits.\n" + "enum UnaryExprOrTypeTrait {\n"; + emitEnumerators(OS, concat<const Record *const>(UETTs, CXX11UETTs)); + OS << " UETT_Last = " << UETTs.size() + CXX11UETTs.size() - 1 + << " // UETT_Last == last UETT_XX in the enum.\n" + << "};\n\n"; +} + +template <typename RangeT> +void emitNamesAndSpellings(raw_ostream &OS, StringRef Name, RangeT Range) { + OS << "static constexpr const char *" << Name << "Names[] = {\n"; + for (const Record *R : Range) { + OS << " \"" << R->getName() << "\",\n"; + } + OS << "};\n\n"; + + OS << "static constexpr const char *" << Name << "Spellings[] = {\n"; + for (const Record *R : Range) { + OS << " \"" << R->getValueAsString("Spelling") << "\",\n"; + } + OS << "};\n\n"; +} + +void emitArrays(const RecordKeeper &Records, raw_ostream &OS) { + const auto UnaryTraits = Records.getAllDerivedDefinitions("UnaryTrait"); + const auto BinaryTraits = Records.getAllDerivedDefinitions("BinaryTrait"); + const auto VariadicTraits = Records.getAllDerivedDefinitions("VariadicTrait"); + + emitNamesAndSpellings( + OS, "TypeTrait", + concat<const Record *const>(UnaryTraits, BinaryTraits, VariadicTraits)); + + OS << "static constexpr const unsigned TypeTraitArities[] = {\n"; + interleaveComma(UnaryTraits, OS, [&](auto) { OS << '1'; }); + if (!UnaryTraits.empty()) + OS << ",\n"; + interleaveComma(BinaryTraits, OS, [&](auto) { OS << '2'; }); + if (!BinaryTraits.empty()) + OS << ",\n"; + interleaveComma(VariadicTraits, OS, [&](auto) { OS << '0'; }); + OS << "\n};\n\n"; + + emitNamesAndSpellings(OS, "ArrayTypeTrait", + Records.getAllDerivedDefinitions("ArrayTrait")); + emitNamesAndSpellings( + OS, "UnaryExprOrTypeTrait", + concat<const Record *const>( + Records.getAllDerivedDefinitions("UnaryExprOrTypeTrait"), + Records.getAllDerivedDefinitions("CXX11UnaryExprOrTypeTrait"))); +} + +void emitStdNameCases(const RecordKeeper &Records, raw_ostream &OS) { + for (const Record *R : Records.getAllDerivedDefinitions("TypeTrait")) { + const StringRef StdName = R->getValueAsString("StdName"); + if (StdName.empty()) + continue; + + OS << " .Case(\"" << StdName + << "\", TypeTrait::" << R->getValueAsString("Prefix") << '_' + << R->getName() << ")\n"; + } +} + +} // namespace + +void clang::EmitClangTraits(const RecordKeeper &Records, raw_ostream &OS) { + OS << "#if defined(EMIT_ENUMS)\n"; + emitEnums(Records, OS); + + OS << "#elif defined(EMIT_ARRAYS)\n"; + emitArrays(Records, OS); + + OS << "#elif defined(EMIT_STD_NAME_CASES)\n"; + emitStdNameCases(Records, OS); + + OS << "#else\n"; + emitMacroDefs(Records, OS); + + OS << "#endif\n\n" + << R"( +#undef EMIT_ARRAYS +#undef EMIT_ENUMS +#undef EMIT_STD_NAME_CASES +)"; +} diff --git a/clang/utils/TableGen/TableGen.cpp b/clang/utils/TableGen/TableGen.cpp index 0ce9d8306ae16..ed0d0c6defeb4 100644 --- a/clang/utils/TableGen/TableGen.cpp +++ b/clang/utils/TableGen/TableGen.cpp @@ -125,7 +125,8 @@ enum ActionType { GenDiagDocs, GenOptDocs, GenDataCollectors, - GenTestPragmaAttributeSupportedAttributes + GenTestPragmaAttributeSupportedAttributes, + GenClangTraits }; namespace { @@ -366,12 +367,14 @@ cl::opt<ActionType> Action( clEnumValN(GenTestPragmaAttributeSupportedAttributes, "gen-clang-test-pragma-attribute-supported-attributes", "Generate a list of attributes supported by #pragma clang " - "attribute for testing purposes"))); + "attribute for testing purposes"), + clEnumValN(GenClangTraits, "gen-clang-traits", + "Generate Traits.inc for clang"))); cl::opt<std::string> -ClangComponent("clang-component", - cl::desc("Only use warnings from specified component"), - cl::value_desc("component"), cl::Hidden); + ClangComponent("clang-component", + cl::desc("Only use warnings from specified component"), + cl::value_desc("component"), cl::Hidden); bool ClangTableGenMain(raw_ostream &OS, const RecordKeeper &Records) { switch (Action) { @@ -686,6 +689,9 @@ bool ClangTableGenMain(raw_ostream &OS, const RecordKeeper &Records) { case GenTestPragmaAttributeSupportedAttributes: EmitTestPragmaAttributeSupportedAttributes(Records, OS); break; + case GenClangTraits: + EmitClangTraits(Records, OS); + break; } return false; diff --git a/clang/utils/TableGen/TableGenBackends.h b/clang/utils/TableGen/TableGenBackends.h index f9bd7ccf9d0d8..038cd0e94e0b7 100644 --- a/clang/utils/TableGen/TableGenBackends.h +++ b/clang/utils/TableGen/TableGenBackends.h @@ -215,6 +215,8 @@ void EmitClangDataCollectors(const llvm::RecordKeeper &Records, void EmitTestPragmaAttributeSupportedAttributes( const llvm::RecordKeeper &Records, llvm::raw_ostream &OS); +void EmitClangTraits(const llvm::RecordKeeper &Records, llvm::raw_ostream &OS); + } // end namespace clang #endif _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
