https://github.com/Tsche updated https://github.com/llvm/llvm-project/pull/201491
>From 53f7e81a734babb6dd186845a3590b6f0497ac33 Mon Sep 17 00:00:00 2001 From: Matthias Wippich <[email protected]> Date: Thu, 4 Jun 2026 00:52:13 +0200 Subject: [PATCH 1/3] [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 c9658775f0470..bd7e415936a74 100644 --- a/clang/include/clang/AST/TypeBase.h +++ b/clang/include/clang/AST/TypeBase.h @@ -6465,7 +6465,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 d334c1d41e475..baae7bc0245f5 100644 --- a/clang/include/clang/Basic/CMakeLists.txt +++ b/clang/include/clang/Basic/CMakeLists.txt @@ -154,6 +154,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 6e7f9cd6e3d38..d91de5cb1da7a 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 172a19f8f3537..eaaa3ce423798 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -4580,7 +4580,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 9799c86510001..45b99e0c4bc65 100644 --- a/clang/lib/AST/TextNodeDumper.cpp +++ b/clang/lib/AST/TextNodeDumper.cpp @@ -2238,7 +2238,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 e8fbffb9f954d..244781c168839 100644 --- a/clang/lib/AST/TypePrinter.cpp +++ b/clang/lib/AST/TypePrinter.cpp @@ -1395,7 +1395,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 8c0ee465b3eb3..799df88c95827 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 0eeb95950ea2b..5c90a73c45cfc 100644 --- a/clang/lib/Format/FormatToken.h +++ b/clang/lib/Format/FormatToken.h @@ -831,7 +831,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 df640cf503c9d..2a354dcbd48d5 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 32ad310ca2672..16e4275306604 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 e09e80a063c4e..eb8f04c248b79 100644 --- a/clang/lib/Lex/PPMacroExpansion.cpp +++ b/clang/lib/Lex/PPMacroExpansion.cpp @@ -1609,7 +1609,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 e3fddf04e555b..ad3fb9011cb1f 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -4606,7 +4606,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 74209f579776d..6ca036664094e 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 6b8ab6ce89909..14550f0f08957 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 df01c91c065a1..d2718598efc12 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 2add7c6aa3080..32b5c474b4a58 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 1d5a98f96d4ea..db3bc296e4da9 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -6226,7 +6226,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 19bff5abfbdc7..c26a96eae9f66 100644 --- a/clang/lib/Sema/SemaTemplateVariadic.cpp +++ b/clang/lib/Sema/SemaTemplateVariadic.cpp @@ -1145,7 +1145,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 1378c7baca92e..87c11e83d6b41 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 e3ae6095c846c..fe3d3c5acf7be 100644 --- a/clang/lib/Sema/SemaTypeTraits.cpp +++ b/clang/lib/Sema/SemaTypeTraits.cpp @@ -1954,16 +1954,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 cc02b08167894..5ce12af610a3d 100644 --- a/clang/utils/TableGen/TableGen.cpp +++ b/clang/utils/TableGen/TableGen.cpp @@ -126,7 +126,8 @@ enum ActionType { GenDiagDocs, GenOptDocs, GenDataCollectors, - GenTestPragmaAttributeSupportedAttributes + GenTestPragmaAttributeSupportedAttributes, + GenClangTraits }; namespace { @@ -370,12 +371,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) { @@ -693,6 +696,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 87a6ddda2271d..fc71e112f86e7 100644 --- a/clang/utils/TableGen/TableGenBackends.h +++ b/clang/utils/TableGen/TableGenBackends.h @@ -217,6 +217,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 >From 78c7afe09af7de6bb1455b946cfd3c73c66b0208 Mon Sep 17 00:00:00 2001 From: Matthias Wippich <[email protected]> Date: Sat, 11 Jul 2026 01:35:20 +0200 Subject: [PATCH 2/3] revert accidental formatting changes --- clang/lib/Parse/ParseDeclCXX.cpp | 78 ++++++++++++++++++++++--------- clang/lib/Parse/ParseExprCXX.cpp | 5 +- clang/lib/Sema/DeclSpec.cpp | 6 +-- clang/utils/TableGen/TableGen.cpp | 6 +-- 4 files changed, 62 insertions(+), 33 deletions(-) diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index 292ff93907b0b..c9e9f4fc16433 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -1605,31 +1605,63 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, Tok.isOneOf( #define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) tok::kw___##Trait, #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_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/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp index 14550f0f08957..f9182800abb07 100644 --- a/clang/lib/Parse/ParseExprCXX.cpp +++ b/clang/lib/Parse/ParseExprCXX.cpp @@ -3404,9 +3404,8 @@ 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; +#define TYPE_TRAIT_N(Spelling, Name, Key) \ + case tok::kw_ ## Spelling: return TT_ ## Name; #include "clang/Basic/Traits.inc" } } diff --git a/clang/lib/Sema/DeclSpec.cpp b/clang/lib/Sema/DeclSpec.cpp index 32b5c474b4a58..8d5f0e444c3d1 100644 --- a/clang/lib/Sema/DeclSpec.cpp +++ b/clang/lib/Sema/DeclSpec.cpp @@ -574,10 +574,8 @@ const char *DeclSpec::getSpecifierName(DeclSpec::TST T, case DeclSpec::TST_##Trait: \ return "__" #Trait; #include "clang/Basic/Traits.inc" - case DeclSpec::TST_unknown_anytype: - return "__unknown_anytype"; - case DeclSpec::TST_atomic: - return "_Atomic"; + 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/utils/TableGen/TableGen.cpp b/clang/utils/TableGen/TableGen.cpp index 5ce12af610a3d..5ea37d8e160ca 100644 --- a/clang/utils/TableGen/TableGen.cpp +++ b/clang/utils/TableGen/TableGen.cpp @@ -376,9 +376,9 @@ cl::opt<ActionType> Action( "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) { >From cbee3bf76d91d59ec41fcc2bd9161fb0e139a4c9 Mon Sep 17 00:00:00 2001 From: Matthias Wippich <[email protected]> Date: Sat, 11 Jul 2026 03:19:42 +0200 Subject: [PATCH 3/3] address review comments, add Alias class --- clang/include/clang/Basic/TokenKinds.def | 11 -- clang/include/clang/Basic/Traits.td | 121 +++++++++++++++++--- clang/utils/TableGen/ClangTraitsEmitter.cpp | 77 ++++++++++--- 3 files changed, 161 insertions(+), 48 deletions(-) diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def index 9e907dba35b62..3d8d42caa39cf 100644 --- a/clang/include/clang/Basic/TokenKinds.def +++ b/clang/include/clang/Basic/TokenKinds.def @@ -489,14 +489,6 @@ KEYWORD(__FUNCSIG__ , KEYMS) KEYWORD(L__FUNCTION__ , KEYMS) KEYWORD(L__FUNCSIG__ , KEYMS) -// GNU and MS Type Traits -// Name for GCC 4.6 compatibility - people have already written libraries using -// this name unfortunately. -ALIAS("__is_literal_type", __is_literal, KEYCXX) - -// Name for GCC 6 compatibility. -ALIAS("__is_same_as", __is_same, KEYCXX) - // Apple Extension. KEYWORD(__private_extern__ , KEYALL) KEYWORD(__module_private__ , KEYALL) @@ -589,7 +581,6 @@ KEYWORD(__kindof , KEYOBJC) // Alternate spelling for various tokens. There are GCC extensions in all // languages, but should not be disabled in strict conformance mode. -ALIAS("__alignof__" , __alignof , KEYALL) ALIAS("__asm" , asm , KEYALL) ALIAS("__asm__" , asm , KEYALL) ALIAS("__attribute__" , __attribute , KEYALL) @@ -644,12 +635,10 @@ ALIAS("__int8" , char , KEYMS) ALIAS("__int16" , short , KEYMS) ALIAS("__int32" , int , KEYMS) ALIAS("__wchar_t" , wchar_t , KEYMS) -ALIAS("__builtin_alignof", __alignof , KEYMS) // Microsoft single-underscore prefixed aliases for double-underscore prefixed // keywords. ALIAS("_asm" , asm , KEYMS) -ALIAS("_alignof" , __alignof , KEYMS) ALIAS("_cdecl" , __cdecl , KEYMS | KEYBORLAND) ALIAS("_declspec" , __declspec , KEYMS) ALIAS("_fastcall" , __fastcall , KEYMS | KEYBORLAND) diff --git a/clang/include/clang/Basic/Traits.td b/clang/include/clang/Basic/Traits.td index d13f75b9dacd9..f5546acdb17c4 100644 --- a/clang/include/clang/Basic/Traits.td +++ b/clang/include/clang/Basic/Traits.td @@ -1,8 +1,59 @@ +//==--- Traits.td - expression and type traits ----------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +class TokenKey<int V> { + int Value = V; +} + +def KEYC99 : TokenKey<0x1>; +def KEYCXX : TokenKey<0x2>; +def KEYCXX11 : TokenKey<0x4>; +def KEYGNU : TokenKey<0x8>; +def KEYMS : TokenKey<0x10>; +def BOOLSUPPORT : TokenKey<0x20>; +def KEYALTIVEC : TokenKey<0x40>; +def KEYNOCXX : TokenKey<0x80>; +def KEYBORLAND : TokenKey<0x100>; +def KEYOPENCLC : TokenKey<0x200>; +def KEYC23 : TokenKey<0x400>; +def KEYNOMS18 : TokenKey<0x800>; +def KEYNOOPENCL : TokenKey<0x1000>; +def WCHARSUPPORT : TokenKey<0x2000>; +def HALFSUPPORT : TokenKey<0x4000>; +def CHAR8SUPPORT : TokenKey<0x8000>; +def KEYOBJC : TokenKey<0x10000>; +def KEYZVECTOR : TokenKey<0x20000>; +def KEYCOROUTINES : TokenKey<0x40000>; +def KEYMODULES : TokenKey<0x80000>; +def KEYCXX20 : TokenKey<0x100000>; +def KEYOPENCLCXX : TokenKey<0x200000>; +def KEYMSCOMPAT : TokenKey<0x400000>; +def KEYSYCL : TokenKey<0x800000>; +def KEYCUDA : TokenKey<0x1000000>; +def KEYZOS : TokenKey<0x2000000>; +def KEYNOZOS : TokenKey<0x4000000>; +def KEYHLSL : TokenKey<0x8000000>; +def KEYFIXEDPOINT : TokenKey<0x10000000>; +def KEYDEFERTS : TokenKey<0x20000000>; +def KEYNOHLSL : TokenKey<0x40000000>; + +def KEYMAX : TokenKey<KEYNOHLSL.Value>; +def KEYALLCXX : TokenKey<!or(KEYCXX.Value, KEYCXX11.Value, KEYCXX20.Value)>; +def KEYALL : TokenKey<!and(!or(KEYMAX.Value, !sub(KEYMAX.Value, 1)), + !xor(KEYNOMS18.Value, -1), + !xor(KEYNOOPENCL.Value, -1), + !xor(KEYNOZOS.Value, -1), + !xor(KEYNOHLSL.Value, -1))>; class Trait<string P> { string Prefix = P; string Spelling = ""; string StdName = ""; - string KeyFlag = "KEYCXX"; + list<TokenKey> KeyFlags = [KEYCXX]; } class TypeTrait<string P> : Trait<P>; @@ -15,10 +66,16 @@ class UnaryExprOrTypeTrait : Trait<"UETT">; class CXX11UnaryExprOrTypeTrait : Trait<"UETT">; class TransformTypeTrait : Trait<"TST">; +class Alias<Trait P> { + Trait Primary = P; + string Spelling = ""; + list<TokenKey> KeyFlags = [KEYCXX]; +} + // C99 6.4.1: Keywords. These turn into kw_* tokens. def SizeOf : UnaryExprOrTypeTrait { let Spelling = "sizeof"; - let KeyFlag = "KEYALL"; + let KeyFlags = [KEYALL]; } def DataSizeOf : UnaryExprOrTypeTrait { @@ -28,14 +85,14 @@ def DataSizeOf : UnaryExprOrTypeTrait { // C2y def CountOf : UnaryExprOrTypeTrait { let Spelling = "_Countof"; - let KeyFlag = "KEYNOCXX"; + let KeyFlags = [KEYNOCXX]; } // C++11 keywords // alignof and _Alignof return the required ABI alignment def AlignOf : CXX11UnaryExprOrTypeTrait { let Spelling = "alignof"; - let KeyFlag = "KEYC23"; + let KeyFlags = [KEYC23]; } // GNU Extensions (in impl-reserved namespace) @@ -44,31 +101,46 @@ def AlignOf : CXX11UnaryExprOrTypeTrait { // clang will attempt to give an object of the type if allowed by ABI. def PreferredAlignOf : UnaryExprOrTypeTrait { let Spelling = "__alignof"; - let KeyFlag = "KEYALL"; + let KeyFlags = [KEYALL]; +} + +def PreferredAlignOfAlt : Alias<PreferredAlignOf> { + let Spelling = "__alignof__"; + let KeyFlags = [KEYALL]; +} + +def BuiltinAlignOf : Alias<PreferredAlignOf> { + let Spelling = "__builtin_alignof"; + let KeyFlags = [KEYMS]; +} + +def MSAlignOf : Alias<PreferredAlignOf> { + let Spelling = "_alignof"; + let KeyFlags = [KEYMS]; } // __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"; + let KeyFlags = [KEYNOCXX]; } // MS Extensions def IsInterfaceClass : UnaryTrait { let Spelling = "__is_interface_class"; - let KeyFlag = "KEYMS"; + let KeyFlags = [KEYMS]; } def IsSealed : UnaryTrait { let Spelling = "__is_sealed"; - let KeyFlag = "KEYMS"; + let KeyFlags = [KEYMS]; } // MSVC12.0 / VS2013 Type Traits def IsDestructible : UnaryTrait { let Spelling = "__is_destructible"; - let KeyFlag = "KEYALL"; + let KeyFlags = [KEYALL]; } def IsTriviallyDestructible : UnaryTrait { @@ -77,7 +149,7 @@ def IsTriviallyDestructible : UnaryTrait { def IsNothrowDestructible : UnaryTrait { let Spelling = "__is_nothrow_destructible"; - let KeyFlag = "KEYALL"; + let KeyFlags = [KEYALL]; } def IsNothrowAssignable : BinaryTrait { @@ -193,6 +265,12 @@ def IsLiteral : UnaryTrait { let Spelling = "__is_literal"; } +// Name for GCC 4.6 compatibility - people have already written libraries using +// this name unfortunately. +def IsLiteralType : Alias<IsLiteral> { + let Spelling = "__is_literal_type"; +} + def IsPOD : UnaryTrait { let Spelling = "__is_pod"; } @@ -384,7 +462,7 @@ def IsTriviallyRelocatable : UnaryTrait { def IsBitwiseCloneable : UnaryTrait { let Spelling = "__is_bitwise_cloneable"; - let KeyFlag = "KEYALL"; + let KeyFlags = [KEYALL]; } def StructuredBindingSize : UnaryTrait { @@ -494,6 +572,11 @@ def IsSame : BinaryTrait { let Spelling = "__is_same"; } +// Name for GCC 6 compatibility +def IsSameAs : Alias<IsSame> { + let Spelling = "__is_same_as"; +} + def IsConvertible : BinaryTrait { let Spelling = "__is_convertible"; } @@ -513,44 +596,44 @@ def ArrayExtent : ArrayTrait { // Apple Extension. def PtrAuthTypeDiscriminator : UnaryExprOrTypeTrait { let Spelling = "__builtin_ptrauth_type_discriminator"; - let KeyFlag = "KEYALL"; + let KeyFlags = [KEYALL]; } // OpenCL builtins def VecStep : UnaryExprOrTypeTrait { let Spelling = "vec_step"; - let KeyFlag = "KEYOPENCLC | KEYOPENCLCXX | KEYALTIVEC | KEYZVECTOR"; + let KeyFlags = [KEYOPENCLC, KEYOPENCLCXX, KEYALTIVEC, KEYZVECTOR]; } // HLSL Type traits def IsScalarizedLayoutCompatible : BinaryTrait { let Spelling = "__builtin_hlsl_is_scalarized_layout_compatible"; - let KeyFlag = "KEYHLSL"; + let KeyFlags = [KEYHLSL]; } def IsIntangibleType : UnaryTrait { let Spelling = "__builtin_hlsl_is_intangible"; - let KeyFlag = "KEYHLSL"; + let KeyFlags = [KEYHLSL]; } def IsTypedResourceElementCompatible : UnaryTrait { let Spelling = "__builtin_hlsl_is_typed_resource_element_compatible"; - let KeyFlag = "KEYHLSL"; + let KeyFlags = [KEYHLSL]; } def IsConstantBufferElementCompatible : UnaryTrait { let Spelling = "__builtin_hlsl_is_constant_buffer_element_compatible"; - let KeyFlag = "KEYHLSL"; + let KeyFlags = [KEYHLSL]; } // OpenMP Type Traits def OpenMPRequiredSimdAlign : UnaryExprOrTypeTrait { let Spelling = "__builtin_omp_required_simd_align"; - let KeyFlag = "KEYALL"; + let KeyFlags = [KEYALL]; } // Clang Extensions. def VectorElements : UnaryExprOrTypeTrait { let Spelling = "__builtin_vectorelements"; - let KeyFlag = "KEYALL"; + let KeyFlags = [KEYALL]; } diff --git a/clang/utils/TableGen/ClangTraitsEmitter.cpp b/clang/utils/TableGen/ClangTraitsEmitter.cpp index f7cbc1ea521e6..4f52e71078d13 100644 --- a/clang/utils/TableGen/ClangTraitsEmitter.cpp +++ b/clang/utils/TableGen/ClangTraitsEmitter.cpp @@ -1,3 +1,11 @@ +//==--- Traits.td - Generate expression and type traits -------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + #include "TableGenBackends.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/STLExtras.h" @@ -5,11 +13,29 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" #include "llvm/TableGen/Record.h" +#include "llvm/TableGen/TableGenBackend.h" using namespace llvm; namespace { +std::vector<const Record *> +getAllDerivedDefsInDeclOrder(const RecordKeeper &Records, StringRef ClassName) { + std::vector<const Record *> Defs = + Records.getAllDerivedDefinitions(ClassName); + llvm::sort(Defs, [](const Record *A, const Record *B) { + return A->getID() < B->getID(); + }); + return Defs; +} + +void emitKeyFlags(ArrayRef<const Record *> KeyFlags, raw_ostream &OS) { + assert(!KeyFlags.empty() && "KeyFlags should never be empty"); + interleave( + KeyFlags, OS, [&](const Record *KeyFlag) { OS << KeyFlag->getName(); }, + " | "); +} + StringRef recordKindToMacro(const Record *R) { if (R->isSubClassOf("UnaryTrait")) return "TYPE_TRAIT_1"; @@ -27,7 +53,8 @@ StringRef recordKindToMacro(const Record *R) { return "CXX11_UNARY_EXPR_OR_TYPE_TRAIT"; if (R->isSubClassOf("TransformTypeTrait")) return "TRANSFORM_TYPE_TRAIT_DEF"; - + if (R->isSubClassOf("Alias")) + return "ALIAS"; llvm_unreachable("unexpected Trait subclass"); } @@ -36,9 +63,14 @@ void emitMacro(const Record *R, raw_ostream &OS) { if (R->isSubClassOf("TransformTypeTrait")) { const StringRef StdName = R->getValueAsString("StdName"); OS << R->getName() << ", " << StdName; + } else if (R->isSubClassOf("Alias")) { + const Record *Primary = R->getValueAsDef("Primary"); + OS << "\"" << R->getValueAsString("Spelling") << "\", " + << Primary->getValueAsString("Spelling") << ", "; + emitKeyFlags(R->getValueAsListOfDefs("KeyFlags"), OS); } else { - OS << R->getValueAsString("Spelling") << ", " << R->getName() << ", " - << R->getValueAsString("KeyFlag"); + OS << R->getValueAsString("Spelling") << ", " << R->getName() << ", "; + emitKeyFlags(R->getValueAsListOfDefs("KeyFlags"), OS); } OS << ")\n"; } @@ -53,7 +85,7 @@ void emitMacroDefs(const RecordKeeper &Records, raw_ostream &OS) { {"CXX11_UNARY_EXPR_OR_TYPE_TRAIT", "(I,E,K)"}, {"EXPRESSION_TRAIT", "(I,E,K)"}, {"TRANSFORM_TYPE_TRAIT_DEF", "(K, Trait)"}, - }; + {"ALIAS", "(X,Y,Z)"}}; for (const auto &[MacroName, MacroArgs] : MacroDefs) { OS << "#ifndef " << MacroName << "\n" @@ -63,7 +95,9 @@ void emitMacroDefs(const RecordKeeper &Records, raw_ostream &OS) { OS << '\n'; - for (const Record *R : Records.getAllDerivedDefinitions("Trait")) + const auto Traits = getAllDerivedDefsInDeclOrder(Records, "Trait"); + const auto Aliases = getAllDerivedDefsInDeclOrder(Records, "Alias"); + for (const Record *R : concat<const Record *const>(Traits, Aliases)) emitMacro(R, OS); for (const auto &[MacroName, _] : reverse(MacroDefs)) @@ -77,9 +111,11 @@ void emitEnumerators(raw_ostream &OS, RangeT &&Range) { } 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"); + const auto UnaryTraits = getAllDerivedDefsInDeclOrder(Records, "UnaryTrait"); + const auto BinaryTraits = + getAllDerivedDefsInDeclOrder(Records, "BinaryTrait"); + const auto VariadicTraits = + getAllDerivedDefsInDeclOrder(Records, "VariadicTrait"); OS << "/// Names for traits that operate specifically on types.\n" "enum TypeTrait {\n"; @@ -97,7 +133,7 @@ void emitEnums(const RecordKeeper &Records, raw_ostream &OS) { << " // TT_Last == last TT_XX in the enum.\n" << "};\n\n"; - const auto ArrayTraits = Records.getAllDerivedDefinitions("ArrayTrait"); + const auto ArrayTraits = getAllDerivedDefsInDeclOrder(Records, "ArrayTrait"); OS << "/// Names for the array type traits.\n" "enum ArrayTypeTrait {\n"; emitEnumerators(OS, ArrayTraits); @@ -105,9 +141,10 @@ void emitEnums(const RecordKeeper &Records, raw_ostream &OS) { << " // ATT_Last == last ATT\n" << "};\n\n"; - const auto UETTs = Records.getAllDerivedDefinitions("UnaryExprOrTypeTrait"); + const auto UETTs = + getAllDerivedDefsInDeclOrder(Records, "UnaryExprOrTypeTrait"); const auto CXX11UETTs = - Records.getAllDerivedDefinitions("CXX11UnaryExprOrTypeTrait"); + getAllDerivedDefsInDeclOrder(Records, "CXX11UnaryExprOrTypeTrait"); OS << "/// Names for the \"expression or type\" traits.\n" "enum UnaryExprOrTypeTrait {\n"; emitEnumerators(OS, concat<const Record *const>(UETTs, CXX11UETTs)); @@ -132,9 +169,11 @@ void emitNamesAndSpellings(raw_ostream &OS, StringRef Name, RangeT Range) { } 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"); + const auto UnaryTraits = getAllDerivedDefsInDeclOrder(Records, "UnaryTrait"); + const auto BinaryTraits = + getAllDerivedDefsInDeclOrder(Records, "BinaryTrait"); + const auto VariadicTraits = + getAllDerivedDefsInDeclOrder(Records, "VariadicTrait"); emitNamesAndSpellings( OS, "TypeTrait", @@ -151,16 +190,16 @@ void emitArrays(const RecordKeeper &Records, raw_ostream &OS) { OS << "\n};\n\n"; emitNamesAndSpellings(OS, "ArrayTypeTrait", - Records.getAllDerivedDefinitions("ArrayTrait")); + getAllDerivedDefsInDeclOrder(Records, "ArrayTrait")); emitNamesAndSpellings( OS, "UnaryExprOrTypeTrait", concat<const Record *const>( - Records.getAllDerivedDefinitions("UnaryExprOrTypeTrait"), - Records.getAllDerivedDefinitions("CXX11UnaryExprOrTypeTrait"))); + getAllDerivedDefsInDeclOrder(Records, "UnaryExprOrTypeTrait"), + getAllDerivedDefsInDeclOrder(Records, "CXX11UnaryExprOrTypeTrait"))); } void emitStdNameCases(const RecordKeeper &Records, raw_ostream &OS) { - for (const Record *R : Records.getAllDerivedDefinitions("TypeTrait")) { + for (const Record *R : getAllDerivedDefsInDeclOrder(Records, "TypeTrait")) { const StringRef StdName = R->getValueAsString("StdName"); if (StdName.empty()) continue; @@ -174,6 +213,7 @@ void emitStdNameCases(const RecordKeeper &Records, raw_ostream &OS) { } // namespace void clang::EmitClangTraits(const RecordKeeper &Records, raw_ostream &OS) { + emitSourceFileHeader("Type and expression traits", OS, Records); OS << "#if defined(EMIT_ENUMS)\n"; emitEnums(Records, OS); @@ -191,5 +231,6 @@ void clang::EmitClangTraits(const RecordKeeper &Records, raw_ostream &OS) { #undef EMIT_ARRAYS #undef EMIT_ENUMS #undef EMIT_STD_NAME_CASES + )"; } _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
