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

Reply via email to