[clang] [Clang] Add BuiltinTemplates.td to generate code for builtin templates (PR #123736)

Nikolas Klauser via cfe-commits cfe-commits at lists.llvm.org
Fri Feb 7 14:26:57 PST 2025


https://github.com/philnik777 updated https://github.com/llvm/llvm-project/pull/123736

>From 586dd4edfc79c88cc1583b64d186c1481fbd6ce1 Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <nikolasklauser at berlin.de>
Date: Wed, 4 Sep 2024 13:31:39 +0200
Subject: [PATCH 1/6] [Clang] Add BuiltinTemplates.td to generate code for
 builtin templates

---
 clang/include/clang/AST/ASTContext.h          |  35 ++--
 clang/include/clang/AST/DeclID.h              |  10 +-
 clang/include/clang/Basic/BuiltinTemplates.td |  23 +++
 clang/include/clang/Basic/Builtins.h          |  10 +-
 clang/include/clang/Basic/CMakeLists.txt      |   4 +
 clang/lib/AST/ASTContext.cpp                  |  30 +--
 clang/lib/AST/ASTImporter.cpp                 |  12 +-
 clang/lib/AST/DeclTemplate.cpp                | 133 +------------
 clang/lib/Lex/PPMacroExpansion.cpp            |   5 +-
 clang/lib/Sema/SemaLookup.cpp                 |  18 +-
 clang/lib/Serialization/ASTReader.cpp         |  22 +--
 clang/lib/Serialization/ASTWriter.cpp         |   8 +-
 clang/utils/TableGen/CMakeLists.txt           |   1 +
 .../TableGen/ClangBuiltinTemplatesEmitter.cpp | 184 ++++++++++++++++++
 clang/utils/TableGen/TableGen.cpp             |   6 +
 clang/utils/TableGen/TableGenBackends.h       |   2 +
 16 files changed, 269 insertions(+), 234 deletions(-)
 create mode 100644 clang/include/clang/Basic/BuiltinTemplates.td
 create mode 100644 clang/utils/TableGen/ClangBuiltinTemplatesEmitter.cpp

diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index 0e07c5d6ce8fba5..98db5522d564e90 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -410,11 +410,8 @@ class ASTContext : public RefCountedBase<ASTContext> {
   /// The identifier 'NSCopying'.
   IdentifierInfo *NSCopyingName = nullptr;
 
-  /// The identifier '__make_integer_seq'.
-  mutable IdentifierInfo *MakeIntegerSeqName = nullptr;
-
-  /// The identifier '__type_pack_element'.
-  mutable IdentifierInfo *TypePackElementName = nullptr;
+#define BuiltinTemplate(BTName) mutable IdentifierInfo *Name##BTName = nullptr;
+#include "clang/Basic/BuiltinTemplates.inc"
 
   /// The identifier '__builtin_common_type'.
   mutable IdentifierInfo *BuiltinCommonTypeName = nullptr;
@@ -624,9 +621,9 @@ class ASTContext : public RefCountedBase<ASTContext> {
 
   TranslationUnitDecl *TUDecl = nullptr;
   mutable ExternCContextDecl *ExternCContext = nullptr;
-  mutable BuiltinTemplateDecl *MakeIntegerSeqDecl = nullptr;
-  mutable BuiltinTemplateDecl *TypePackElementDecl = nullptr;
-  mutable BuiltinTemplateDecl *BuiltinCommonTypeDecl = nullptr;
+
+#define BuiltinTemplate(Name) mutable BuiltinTemplateDecl *Decl##Name = nullptr;
+#include "clang/Basic/BuiltinTemplates.inc"
 
   /// The associated SourceManager object.
   SourceManager &SourceMgr;
@@ -1152,9 +1149,9 @@ class ASTContext : public RefCountedBase<ASTContext> {
   }
 
   ExternCContextDecl *getExternCContextDecl() const;
-  BuiltinTemplateDecl *getMakeIntegerSeqDecl() const;
-  BuiltinTemplateDecl *getTypePackElementDecl() const;
-  BuiltinTemplateDecl *getBuiltinCommonTypeDecl() const;
+
+#define BuiltinTemplate(Name) BuiltinTemplateDecl *get##Name##Decl() const;
+#include "clang/Basic/BuiltinTemplates.inc"
 
   // Builtin Types.
   CanQualType VoidTy;
@@ -2054,17 +2051,13 @@ class ASTContext : public RefCountedBase<ASTContext> {
     return BoolName;
   }
 
-  IdentifierInfo *getMakeIntegerSeqName() const {
-    if (!MakeIntegerSeqName)
-      MakeIntegerSeqName = &Idents.get("__make_integer_seq");
-    return MakeIntegerSeqName;
-  }
-
-  IdentifierInfo *getTypePackElementName() const {
-    if (!TypePackElementName)
-      TypePackElementName = &Idents.get("__type_pack_element");
-    return TypePackElementName;
+#define BuiltinTemplate(BTName)                                                \
+  IdentifierInfo *get##BTName##Name() const {                                  \
+    if (!Name##BTName)                                                         \
+      Name##BTName = &Idents.get(#BTName);                                     \
+    return Name##BTName;                                                       \
   }
+#include "clang/Basic/BuiltinTemplates.inc"
 
   IdentifierInfo *getBuiltinCommonTypeName() const {
     if (!BuiltinCommonTypeName)
diff --git a/clang/include/clang/AST/DeclID.h b/clang/include/clang/AST/DeclID.h
index 49964b43c7d1d8d..71e28ec1f9c65f3 100644
--- a/clang/include/clang/AST/DeclID.h
+++ b/clang/include/clang/AST/DeclID.h
@@ -71,20 +71,14 @@ enum PredefinedDeclIDs {
   /// The extern "C" context.
   PREDEF_DECL_EXTERN_C_CONTEXT_ID,
 
-  /// The internal '__make_integer_seq' template.
-  PREDEF_DECL_MAKE_INTEGER_SEQ_ID,
-
   /// The internal '__NSConstantString' typedef.
   PREDEF_DECL_CF_CONSTANT_STRING_ID,
 
   /// The internal '__NSConstantString' tag type.
   PREDEF_DECL_CF_CONSTANT_STRING_TAG_ID,
 
-  /// The internal '__type_pack_element' template.
-  PREDEF_DECL_TYPE_PACK_ELEMENT_ID,
-
-  /// The internal '__builtin_common_type' template.
-  PREDEF_DECL_COMMON_TYPE_ID,
+#define BuiltinTemplate(Name) PREDEF_DECL##Name##_ID,
+#include "clang/Basic/BuiltinTemplates.inc"
 
   /// The number of declaration IDs that are predefined.
   NUM_PREDEF_DECL_IDS
diff --git a/clang/include/clang/Basic/BuiltinTemplates.td b/clang/include/clang/Basic/BuiltinTemplates.td
new file mode 100644
index 000000000000000..3d51088e0bccafe
--- /dev/null
+++ b/clang/include/clang/Basic/BuiltinTemplates.td
@@ -0,0 +1,23 @@
+//===--- BuiltinTemplates.td - Clang builtin template aliases ---*- C++ -*-===//
+//
+// 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 BuiltinTemplate<string prototype> {
+  string Prototype = prototype;
+}
+
+def __make_integer_seq : BuiltinTemplate<
+  "template <template <class T, T... Ints> class IntSeq, class T, T N>">;
+
+def __type_pack_element : BuiltinTemplate<
+  "template <size_t, class... T>">;
+
+def __builtin_common_type : BuiltinTemplate<
+  "template <template <class... Args> class BaseTemplate,"
+  "          template <class TypeMember> class HasTypeMember,"
+  "          class HasNoTypeMember,"
+  "          class... Ts>">;
diff --git a/clang/include/clang/Basic/Builtins.h b/clang/include/clang/Basic/Builtins.h
index 63559d977ce6b6c..eef96f35095a88e 100644
--- a/clang/include/clang/Basic/Builtins.h
+++ b/clang/include/clang/Basic/Builtins.h
@@ -306,14 +306,8 @@ bool evaluateRequiredTargetFeatures(
 
 /// Kinds of BuiltinTemplateDecl.
 enum BuiltinTemplateKind : int {
-  /// This names the __make_integer_seq BuiltinTemplateDecl.
-  BTK__make_integer_seq,
-
-  /// This names the __type_pack_element BuiltinTemplateDecl.
-  BTK__type_pack_element,
-
-  /// This names the __builtin_common_type BuiltinTemplateDecl.
-  BTK__builtin_common_type,
+#define BuiltinTemplate(Name) BTK##Name,
+#include "clang/Basic/BuiltinTemplates.inc"
 };
 
 } // end namespace clang
diff --git a/clang/include/clang/Basic/CMakeLists.txt b/clang/include/clang/Basic/CMakeLists.txt
index 56c27bacdb20b89..3fe6d8985b32d86 100644
--- a/clang/include/clang/Basic/CMakeLists.txt
+++ b/clang/include/clang/Basic/CMakeLists.txt
@@ -77,6 +77,10 @@ clang_tablegen(BuiltinsX86_64.inc -gen-clang-builtins
   SOURCE BuiltinsX86_64.td
   TARGET ClangBuiltinsX86_64)
 
+clang_tablegen(BuiltinTemplates.inc -gen-clang-builtin-templates
+  SOURCE BuiltinTemplates.td
+  TARGET ClangBuiltinTemplates)
+
 # ARM NEON and MVE
 clang_tablegen(arm_neon.inc -gen-arm-neon-sema
   SOURCE arm_neon.td
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index be1dd29d462788e..288135e47fc39cf 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -1195,28 +1195,14 @@ ASTContext::buildBuiltinTemplateDecl(BuiltinTemplateKind BTK,
   return BuiltinTemplate;
 }
 
-BuiltinTemplateDecl *
-ASTContext::getMakeIntegerSeqDecl() const {
-  if (!MakeIntegerSeqDecl)
-    MakeIntegerSeqDecl = buildBuiltinTemplateDecl(BTK__make_integer_seq,
-                                                  getMakeIntegerSeqName());
-  return MakeIntegerSeqDecl;
-}
-
-BuiltinTemplateDecl *
-ASTContext::getTypePackElementDecl() const {
-  if (!TypePackElementDecl)
-    TypePackElementDecl = buildBuiltinTemplateDecl(BTK__type_pack_element,
-                                                   getTypePackElementName());
-  return TypePackElementDecl;
-}
-
-BuiltinTemplateDecl *ASTContext::getBuiltinCommonTypeDecl() const {
-  if (!BuiltinCommonTypeDecl)
-    BuiltinCommonTypeDecl = buildBuiltinTemplateDecl(
-        BTK__builtin_common_type, getBuiltinCommonTypeName());
-  return BuiltinCommonTypeDecl;
-}
+#define BuiltinTemplate(BTName)                                                \
+  BuiltinTemplateDecl *ASTContext::get##BTName##Decl() const {                 \
+    if (!Decl##BTName)                                                         \
+      Decl##BTName =                                                           \
+          buildBuiltinTemplateDecl(BTK##BTName, get##BTName##Name());          \
+    return Decl##BTName;                                                       \
+  }
+#include "clang/Basic/BuiltinTemplates.inc"
 
 RecordDecl *ASTContext::buildImplicitRecord(StringRef Name,
                                             RecordDecl::TagKind TK) const {
diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index 0669aa1b809c348..f63e017c33a0024 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -5461,15 +5461,11 @@ ExpectedDecl ASTNodeImporter::VisitUnresolvedUsingTypenameDecl(
 ExpectedDecl ASTNodeImporter::VisitBuiltinTemplateDecl(BuiltinTemplateDecl *D) {
   Decl* ToD = nullptr;
   switch (D->getBuiltinTemplateKind()) {
-  case BuiltinTemplateKind::BTK__make_integer_seq:
-    ToD = Importer.getToContext().getMakeIntegerSeqDecl();
-    break;
-  case BuiltinTemplateKind::BTK__type_pack_element:
-    ToD = Importer.getToContext().getTypePackElementDecl();
-    break;
-  case BuiltinTemplateKind::BTK__builtin_common_type:
-    ToD = Importer.getToContext().getBuiltinCommonTypeDecl();
+#define BuiltinTemplate(Name)                                                  \
+  case BuiltinTemplateKind::BTK##Name:                                         \
+    ToD = Importer.getToContext().get##Name##Decl();                           \
     break;
+#include "clang/Basic/BuiltinTemplates.inc"
   }
   assert(ToD && "BuiltinTemplateDecl of unsupported kind!");
   Importer.MapImported(D, ToD);
diff --git a/clang/lib/AST/DeclTemplate.cpp b/clang/lib/AST/DeclTemplate.cpp
index 40ee3753c24227d..de060dc612c317a 100644
--- a/clang/lib/AST/DeclTemplate.cpp
+++ b/clang/lib/AST/DeclTemplate.cpp
@@ -1571,140 +1571,11 @@ SourceRange VarTemplatePartialSpecializationDecl::getSourceRange() const {
   return Range;
 }
 
-static TemplateParameterList *
-createMakeIntegerSeqParameterList(const ASTContext &C, DeclContext *DC) {
-  // typename T
-  auto *T = TemplateTypeParmDecl::Create(
-      C, DC, SourceLocation(), SourceLocation(), /*Depth=*/1, /*Position=*/0,
-      /*Id=*/nullptr, /*Typename=*/true, /*ParameterPack=*/false,
-      /*HasTypeConstraint=*/false);
-  T->setImplicit(true);
-
-  // T ...Ints
-  TypeSourceInfo *TI =
-      C.getTrivialTypeSourceInfo(QualType(T->getTypeForDecl(), 0));
-  auto *N = NonTypeTemplateParmDecl::Create(
-      C, DC, SourceLocation(), SourceLocation(), /*Depth=*/0, /*Position=*/1,
-      /*Id=*/nullptr, TI->getType(), /*ParameterPack=*/true, TI);
-  N->setImplicit(true);
-
-  // <typename T, T ...Ints>
-  NamedDecl *P[2] = {T, N};
-  auto *TPL = TemplateParameterList::Create(
-      C, SourceLocation(), SourceLocation(), P, SourceLocation(), nullptr);
-
-  // template <typename T, ...Ints> class IntSeq
-  auto *TemplateTemplateParm = TemplateTemplateParmDecl::Create(
-      C, DC, SourceLocation(), /*Depth=*/0, /*Position=*/0,
-      /*ParameterPack=*/false, /*Id=*/nullptr, /*Typename=*/false, TPL);
-  TemplateTemplateParm->setImplicit(true);
-
-  // typename T
-  auto *TemplateTypeParm = TemplateTypeParmDecl::Create(
-      C, DC, SourceLocation(), SourceLocation(), /*Depth=*/0, /*Position=*/1,
-      /*Id=*/nullptr, /*Typename=*/true, /*ParameterPack=*/false,
-      /*HasTypeConstraint=*/false);
-  TemplateTypeParm->setImplicit(true);
-
-  // T N
-  TypeSourceInfo *TInfo = C.getTrivialTypeSourceInfo(
-      QualType(TemplateTypeParm->getTypeForDecl(), 0));
-  auto *NonTypeTemplateParm = NonTypeTemplateParmDecl::Create(
-      C, DC, SourceLocation(), SourceLocation(), /*Depth=*/0, /*Position=*/2,
-      /*Id=*/nullptr, TInfo->getType(), /*ParameterPack=*/false, TInfo);
-  NamedDecl *Params[] = {TemplateTemplateParm, TemplateTypeParm,
-                         NonTypeTemplateParm};
-
-  // template <template <typename T, T ...Ints> class IntSeq, typename T, T N>
-  return TemplateParameterList::Create(C, SourceLocation(), SourceLocation(),
-                                       Params, SourceLocation(), nullptr);
-}
-
-static TemplateParameterList *
-createTypePackElementParameterList(const ASTContext &C, DeclContext *DC) {
-  // std::size_t Index
-  TypeSourceInfo *TInfo = C.getTrivialTypeSourceInfo(C.getSizeType());
-  auto *Index = NonTypeTemplateParmDecl::Create(
-      C, DC, SourceLocation(), SourceLocation(), /*Depth=*/0, /*Position=*/0,
-      /*Id=*/nullptr, TInfo->getType(), /*ParameterPack=*/false, TInfo);
-
-  // typename ...T
-  auto *Ts = TemplateTypeParmDecl::Create(
-      C, DC, SourceLocation(), SourceLocation(), /*Depth=*/0, /*Position=*/1,
-      /*Id=*/nullptr, /*Typename=*/true, /*ParameterPack=*/true,
-      /*HasTypeConstraint=*/false);
-  Ts->setImplicit(true);
-
-  // template <std::size_t Index, typename ...T>
-  NamedDecl *Params[] = {Index, Ts};
-  return TemplateParameterList::Create(C, SourceLocation(), SourceLocation(),
-                                       llvm::ArrayRef(Params), SourceLocation(),
-                                       nullptr);
-}
-
-static TemplateParameterList *createBuiltinCommonTypeList(const ASTContext &C,
-                                                          DeclContext *DC) {
-  // class... Args
-  auto *Args =
-      TemplateTypeParmDecl::Create(C, DC, SourceLocation(), SourceLocation(),
-                                   /*Depth=*/1, /*Position=*/0, /*Id=*/nullptr,
-                                   /*Typename=*/false, /*ParameterPack=*/true);
-
-  // <class... Args>
-  auto *BaseTemplateList = TemplateParameterList::Create(
-      C, SourceLocation(), SourceLocation(), Args, SourceLocation(), nullptr);
-
-  // template <class... Args> class BaseTemplate
-  auto *BaseTemplate = TemplateTemplateParmDecl::Create(
-      C, DC, SourceLocation(), /*Depth=*/0, /*Position=*/0,
-      /*ParameterPack=*/false, /*Id=*/nullptr,
-      /*Typename=*/false, BaseTemplateList);
-
-  // class TypeMember
-  auto *TypeMember =
-      TemplateTypeParmDecl::Create(C, DC, SourceLocation(), SourceLocation(),
-                                   /*Depth=*/1, /*Position=*/0, /*Id=*/nullptr,
-                                   /*Typename=*/false, /*ParameterPack=*/false);
-
-  // <class TypeMember>
-  auto *HasTypeMemberList =
-      TemplateParameterList::Create(C, SourceLocation(), SourceLocation(),
-                                    TypeMember, SourceLocation(), nullptr);
-
-  // template <class TypeMember> class HasTypeMember
-  auto *HasTypeMember = TemplateTemplateParmDecl::Create(
-      C, DC, SourceLocation(), /*Depth=*/0, /*Position=*/1,
-      /*ParameterPack=*/false, /*Id=*/nullptr,
-      /*Typename=*/false, HasTypeMemberList);
-
-  // class HasNoTypeMember
-  auto *HasNoTypeMember = TemplateTypeParmDecl::Create(
-      C, DC, {}, {}, /*Depth=*/0, /*Position=*/2, /*Id=*/nullptr,
-      /*Typename=*/false, /*ParameterPack=*/false);
-
-  // class... Ts
-  auto *Ts = TemplateTypeParmDecl::Create(
-      C, DC, SourceLocation(), SourceLocation(), /*Depth=*/0, /*Position=*/3,
-      /*Id=*/nullptr, /*Typename=*/false, /*ParameterPack=*/true);
-
-  // template <template <class... Args> class BaseTemplate,
-  //   template <class TypeMember> class HasTypeMember, class HasNoTypeMember,
-  //   class... Ts>
-  return TemplateParameterList::Create(
-      C, SourceLocation(), SourceLocation(),
-      {BaseTemplate, HasTypeMember, HasNoTypeMember, Ts}, SourceLocation(),
-      nullptr);
-}
-
 static TemplateParameterList *createBuiltinTemplateParameterList(
     const ASTContext &C, DeclContext *DC, BuiltinTemplateKind BTK) {
   switch (BTK) {
-  case BTK__make_integer_seq:
-    return createMakeIntegerSeqParameterList(C, DC);
-  case BTK__type_pack_element:
-    return createTypePackElementParameterList(C, DC);
-  case BTK__builtin_common_type:
-    return createBuiltinCommonTypeList(C, DC);
+#define CREATE_BUILTIN_TEMPLATE_PARAMETER_LIST
+#include "clang/Basic/BuiltinTemplates.inc"
   }
 
   llvm_unreachable("unhandled BuiltinTemplateKind!");
diff --git a/clang/lib/Lex/PPMacroExpansion.cpp b/clang/lib/Lex/PPMacroExpansion.cpp
index 347c13da0ad215a..fdbf53b9a623a68 100644
--- a/clang/lib/Lex/PPMacroExpansion.cpp
+++ b/clang/lib/Lex/PPMacroExpansion.cpp
@@ -1831,9 +1831,8 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) {
         } else {
           return llvm::StringSwitch<bool>(II->getName())
               // Report builtin templates as being builtins.
-              .Case("__make_integer_seq", getLangOpts().CPlusPlus)
-              .Case("__type_pack_element", getLangOpts().CPlusPlus)
-              .Case("__builtin_common_type", getLangOpts().CPlusPlus)
+#define BuiltinTemplate(BTName) .Case(#BTName, getLangOpts().CPlusPlus)
+#include "clang/Basic/BuiltinTemplates.inc"
               // Likewise for some builtin preprocessor macros.
               // FIXME: This is inconsistent; we usually suggest detecting
               // builtin macros via #ifdef. Don't add more cases here.
diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp
index e1171d4284c763e..abfb0569b5c4ffd 100644
--- a/clang/lib/Sema/SemaLookup.cpp
+++ b/clang/lib/Sema/SemaLookup.cpp
@@ -924,18 +924,12 @@ bool Sema::LookupBuiltin(LookupResult &R) {
     IdentifierInfo *II = R.getLookupName().getAsIdentifierInfo();
     if (II) {
       if (getLangOpts().CPlusPlus && NameKind == Sema::LookupOrdinaryName) {
-        if (II == getASTContext().getMakeIntegerSeqName()) {
-          R.addDecl(getASTContext().getMakeIntegerSeqDecl());
-          return true;
-        }
-        if (II == getASTContext().getTypePackElementName()) {
-          R.addDecl(getASTContext().getTypePackElementDecl());
-          return true;
-        }
-        if (II == getASTContext().getBuiltinCommonTypeName()) {
-          R.addDecl(getASTContext().getBuiltinCommonTypeDecl());
-          return true;
-        }
+#define BuiltinTemplate(BIName)                                                \
+  if (II == getASTContext().get##BIName##Name()) {                             \
+    R.addDecl(getASTContext().get##BIName##Decl());                            \
+    return true;                                                               \
+  }
+#include "clang/Basic/BuiltinTemplates.inc"
       }
 
       // Check if this is an OpenCL Builtin, and if so, insert its overloads.
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index 7361cace49dd7bf..f19f71d14829701 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -8005,12 +8005,6 @@ Decl *ASTReader::getPredefinedDecl(PredefinedDeclIDs ID) {
     NewLoaded = Context.getExternCContextDecl();
     break;
 
-  case PREDEF_DECL_MAKE_INTEGER_SEQ_ID:
-    if (Context.MakeIntegerSeqDecl)
-      return Context.MakeIntegerSeqDecl;
-    NewLoaded = Context.getMakeIntegerSeqDecl();
-    break;
-
   case PREDEF_DECL_CF_CONSTANT_STRING_ID:
     if (Context.CFConstantStringTypeDecl)
       return Context.CFConstantStringTypeDecl;
@@ -8023,17 +8017,13 @@ Decl *ASTReader::getPredefinedDecl(PredefinedDeclIDs ID) {
     NewLoaded = Context.getCFConstantStringTagDecl();
     break;
 
-  case PREDEF_DECL_TYPE_PACK_ELEMENT_ID:
-    if (Context.TypePackElementDecl)
-      return Context.TypePackElementDecl;
-    NewLoaded = Context.getTypePackElementDecl();
-    break;
-
-  case PREDEF_DECL_COMMON_TYPE_ID:
-    if (Context.BuiltinCommonTypeDecl)
-      return Context.BuiltinCommonTypeDecl;
-    NewLoaded = Context.getBuiltinCommonTypeDecl();
+#define BuiltinTemplate(Name)                                                  \
+  case PREDEF_DECL##Name##_ID:                                                 \
+    if (Context.Decl##Name)                                                    \
+      return Context.Decl##Name;                                               \
+    NewLoaded = Context.get##Name##Decl();                                     \
     break;
+#include "clang/Basic/BuiltinTemplates.inc"
 
   case NUM_PREDEF_DECL_IDS:
     llvm_unreachable("Invalid decl ID");
diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index 0ae2157eed4ecc4..c21586f79fef019 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -5292,15 +5292,13 @@ void ASTWriter::PrepareWritingSpecialDecls(Sema &SemaRef) {
   RegisterPredefDecl(Context.MSGuidTagDecl,
                      PREDEF_DECL_BUILTIN_MS_GUID_ID);
   RegisterPredefDecl(Context.ExternCContext, PREDEF_DECL_EXTERN_C_CONTEXT_ID);
-  RegisterPredefDecl(Context.MakeIntegerSeqDecl,
-                     PREDEF_DECL_MAKE_INTEGER_SEQ_ID);
   RegisterPredefDecl(Context.CFConstantStringTypeDecl,
                      PREDEF_DECL_CF_CONSTANT_STRING_ID);
   RegisterPredefDecl(Context.CFConstantStringTagDecl,
                      PREDEF_DECL_CF_CONSTANT_STRING_TAG_ID);
-  RegisterPredefDecl(Context.TypePackElementDecl,
-                     PREDEF_DECL_TYPE_PACK_ELEMENT_ID);
-  RegisterPredefDecl(Context.BuiltinCommonTypeDecl, PREDEF_DECL_COMMON_TYPE_ID);
+#define BuiltinTemplate(Name)                                                  \
+  RegisterPredefDecl(Context.Decl##Name, PREDEF_DECL##Name##_ID);
+#include "clang/Basic/BuiltinTemplates.inc"
 
   const TranslationUnitDecl *TU = Context.getTranslationUnitDecl();
 
diff --git a/clang/utils/TableGen/CMakeLists.txt b/clang/utils/TableGen/CMakeLists.txt
index 5b072a1ac196989..ce759ec8548d9ac 100644
--- a/clang/utils/TableGen/CMakeLists.txt
+++ b/clang/utils/TableGen/CMakeLists.txt
@@ -8,6 +8,7 @@ add_tablegen(clang-tblgen CLANG
   ClangASTPropertiesEmitter.cpp
   ClangAttrEmitter.cpp
   ClangBuiltinsEmitter.cpp
+  ClangBuiltinTemplatesEmitter.cpp
   ClangCommentCommandInfoEmitter.cpp
   ClangCommentHTMLNamedCharacterReferenceEmitter.cpp
   ClangCommentHTMLTagsEmitter.cpp
diff --git a/clang/utils/TableGen/ClangBuiltinTemplatesEmitter.cpp b/clang/utils/TableGen/ClangBuiltinTemplatesEmitter.cpp
new file mode 100644
index 000000000000000..8e6d1dbaddea9ee
--- /dev/null
+++ b/clang/utils/TableGen/ClangBuiltinTemplatesEmitter.cpp
@@ -0,0 +1,184 @@
+//=- ClangBuiltinsEmitter.cpp - Generate Clang builtin templates-*- C++ -*-===//
+//
+// 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 tablegen backend emits Clang's builtin templates.
+//
+//===----------------------------------------------------------------------===//
+
+#include "TableGenBackends.h"
+#include "llvm/TableGen/Error.h"
+#include "llvm/TableGen/TableGenBackend.h"
+
+using namespace llvm;
+
+std::string TemplateNameList;
+std::string CreateBuiltinTemplateParameterList;
+
+namespace {
+struct ParserState {
+  size_t UniqueCounter = 0;
+  size_t CurrentDepth = 0;
+  bool EmittedSizeTInfo = false;
+};
+
+std::pair<std::string, std::string>
+ParseTemplateParameterList(ParserState &PS, StringRef &TemplateParmList) {
+  auto Alphabetic = [](char c) { return std::isalpha(c); };
+  auto BoolToStr = [](bool b) { return b ? "true" : "false"; };
+
+  std::string Generator;
+  std::vector<std::string> Params;
+  std::unordered_map<std::string, std::string> TemplateNameToParmName;
+  TemplateParmList = TemplateParmList.ltrim();
+  if (!TemplateParmList.consume_front("<"))
+    PrintFatalError("Expected '<' to start the parameter list");
+
+  size_t Position = 0;
+  while (true) {
+    std::string ParmName = "Parm" + std::to_string(PS.UniqueCounter++);
+    if (TemplateParmList.consume_front("size_t")) {
+      if (!PS.EmittedSizeTInfo) {
+        PS.EmittedSizeTInfo = true;
+        Generator += R"C++(
+  TypeSourceInfo *SizeTInfo = C.getTrivialTypeSourceInfo(C.getSizeType());
+)C++";
+      }
+
+      Generator += "  auto *" + ParmName + R"C++(
+    = NonTypeTemplateParmDecl::Create(C, DC, SourceLocation(), SourceLocation(),
+        )C++" + std::to_string(PS.CurrentDepth) +
+                   ", " + std::to_string(Position++) + R"C++(, /*Id=*/nullptr,
+        SizeTInfo->getType(), /*ParameterPack=*/false, SizeTInfo);
+)C++";
+    } else if (TemplateParmList.consume_front("class")) {
+      bool ParameterPack = TemplateParmList.consume_front("...");
+
+      Generator += "  auto *" + ParmName + R"C++(
+    = TemplateTypeParmDecl::Create(C, DC, SourceLocation(), SourceLocation(),
+      )C++" + std::to_string(PS.CurrentDepth) +
+                   ", " + std::to_string(Position++) +
+                   R"C++(, /*Id=*/nullptr, /*Typename=*/false, )C++" +
+                   BoolToStr(ParameterPack) + ");\n";
+    } else if (TemplateParmList.consume_front("template")) {
+      ++PS.CurrentDepth;
+      auto [Code, TPLName] = ParseTemplateParameterList(PS, TemplateParmList);
+      --PS.CurrentDepth;
+      TemplateParmList = TemplateParmList.ltrim();
+      if (!TemplateParmList.consume_front("class")) {
+        PrintFatalError("Expected 'class' after template template list");
+      }
+      Generator += Code;
+      Generator +=
+          "  auto *" + ParmName + R"C++(
+    = TemplateTemplateParmDecl::Create(C, DC, SourceLocation(), )C++" +
+          std::to_string(PS.CurrentDepth) + ", " + std::to_string(Position++) +
+          ", /*ParameterPack=*/false, /*Id=*/nullptr, /*Typename=*/false, " +
+          TPLName + ");\n";
+    } else {
+      auto Name = TemplateParmList.take_while(Alphabetic).str();
+      if (TemplateNameToParmName.find(Name) != TemplateNameToParmName.end()) {
+        TemplateParmList = TemplateParmList.drop_front(Name.size());
+        bool ParameterPack = TemplateParmList.consume_front("...");
+
+        auto TSIName = "TSI" + std::to_string(PS.UniqueCounter++);
+        Generator += "  auto *" + TSIName + R"C++(
+    = C.getTrivialTypeSourceInfo(QualType()C++" +
+                     TemplateNameToParmName[Name] +
+                     R"C++(->getTypeForDecl(), 0));
+  auto *)C++" + ParmName +
+                     R"C++( = NonTypeTemplateParmDecl::Create(
+      C, DC, SourceLocation(), SourceLocation(), )C++" +
+                     std::to_string(PS.CurrentDepth) + ", " +
+                     std::to_string(Position++) + ", /*Id=*/nullptr, " +
+                     TSIName + "->getType(), " + BoolToStr(ParameterPack) +
+                     ", " + TSIName + ");\n";
+      } else {
+        PrintFatalError("Unknown argument");
+      }
+    }
+    TemplateParmList = TemplateParmList.ltrim();
+    auto ID = TemplateParmList.take_while(Alphabetic);
+    if (!ID.empty()) {
+      TemplateNameToParmName[ID.str()] = ParmName;
+      TemplateParmList = TemplateParmList.drop_front(ID.size());
+    }
+
+    Params.emplace_back(std::move(ParmName));
+
+    if (!TemplateParmList.consume_front(","))
+      break;
+    TemplateParmList = TemplateParmList.ltrim();
+  }
+
+  if (!TemplateParmList.consume_front(">")) {
+    PrintWarning("Expected '>' to close template parameter list");
+    PrintWarning(TemplateParmList);
+  }
+
+  auto TPLName = "TPL" + std::to_string(PS.UniqueCounter++);
+  Generator += "  auto *" + TPLName + R"C++( = TemplateParameterList::Create(
+      C, SourceLocation(), SourceLocation(), {)C++";
+
+  if (Params.empty())
+    PrintFatalError(
+        "Expected at least one argument in template parameter list");
+
+  bool First = true;
+  for (auto e : Params) {
+    if (First) {
+      First = false;
+      Generator += e;
+    } else {
+      Generator += ", " + e;
+    }
+  }
+  Generator += "}, SourceLocation(), nullptr);\n";
+
+  return {std::move(Generator), std::move(TPLName)};
+}
+
+void EmitCreateBuiltinTemplateParameterList(StringRef Prototype,
+                                            StringRef Name) {
+  using namespace std::string_literals;
+  CreateBuiltinTemplateParameterList +=
+      "case BTK"s + std::string{Name} + ": {\n"s;
+  if (!Prototype.consume_front("template"))
+    PrintFatalError(
+        "Expected template prototype to start with 'template' keyword");
+
+  ParserState PS;
+  auto [Code, TPLName] = ParseTemplateParameterList(PS, Prototype);
+  CreateBuiltinTemplateParameterList += Code + "\n  return " + TPLName + ";\n";
+
+  CreateBuiltinTemplateParameterList += "  }\n";
+}
+
+void EmitBuiltinTemplate(raw_ostream &OS, const Record *BuiltinTemplate) {
+  auto Prototype = BuiltinTemplate->getValueAsString("Prototype");
+  auto Name = BuiltinTemplate->getName();
+
+  EmitCreateBuiltinTemplateParameterList(Prototype, Name);
+
+  TemplateNameList += "BuiltinTemplate(";
+  TemplateNameList += Name;
+  TemplateNameList += ")\n";
+}
+} // namespace
+
+void clang::EmitClangBuiltinTemplates(const llvm::RecordKeeper &Records,
+                                      llvm::raw_ostream &OS) {
+  emitSourceFileHeader("Tables and code for Clang's builtin templates", OS);
+  for (const auto *Builtin :
+       Records.getAllDerivedDefinitions("BuiltinTemplate"))
+    EmitBuiltinTemplate(OS, Builtin);
+
+  OS << "#if defined(CREATE_BUILTIN_TEMPLATE_PARAMETER_LIST)\n"
+     << CreateBuiltinTemplateParameterList
+     << "#undef CREATE_BUILTIN_TEMPLATE_PARAMETER_LIST\n#else\n"
+     << TemplateNameList << "#undef BuiltinTemplate\n#endif\n";
+}
diff --git a/clang/utils/TableGen/TableGen.cpp b/clang/utils/TableGen/TableGen.cpp
index 8b8eadbe7f7e54f..e526ff9640c51e7 100644
--- a/clang/utils/TableGen/TableGen.cpp
+++ b/clang/utils/TableGen/TableGen.cpp
@@ -47,6 +47,7 @@ enum ActionType {
   GenClangBasicReader,
   GenClangBasicWriter,
   GenClangBuiltins,
+  GenClangBuiltinTemplates,
   GenClangDiagsDefs,
   GenClangDiagsEnums,
   GenClangDiagGroups,
@@ -172,6 +173,8 @@ cl::opt<ActionType> Action(
                    "Generate clang attribute traverser"),
         clEnumValN(GenClangBuiltins, "gen-clang-builtins",
                    "Generate clang builtins list"),
+        clEnumValN(GenClangBuiltinTemplates, "gen-clang-builtin-templates",
+                   "Generate clang builtins list"),
         clEnumValN(GenClangDiagsDefs, "gen-clang-diags-defs",
                    "Generate Clang diagnostics definitions"),
         clEnumValN(GenClangDiagsEnums, "gen-clang-diags-enums",
@@ -387,6 +390,9 @@ bool ClangTableGenMain(raw_ostream &OS, const RecordKeeper &Records) {
   case GenClangBuiltins:
     EmitClangBuiltins(Records, OS);
     break;
+  case GenClangBuiltinTemplates:
+    EmitClangBuiltinTemplates(Records, OS);
+    break;
   case GenClangDiagsDefs:
     EmitClangDiagsDefs(Records, OS, ClangComponent);
     break;
diff --git a/clang/utils/TableGen/TableGenBackends.h b/clang/utils/TableGen/TableGenBackends.h
index 0448c94de08e3d5..cc58489180ba56e 100644
--- a/clang/utils/TableGen/TableGenBackends.h
+++ b/clang/utils/TableGen/TableGenBackends.h
@@ -86,6 +86,8 @@ void EmitClangAttrDocTable(const llvm::RecordKeeper &Records,
 
 void EmitClangBuiltins(const llvm::RecordKeeper &Records,
                        llvm::raw_ostream &OS);
+void EmitClangBuiltinTemplates(const llvm::RecordKeeper &Records,
+                               llvm::raw_ostream &OS);
 
 void EmitClangDiagsDefs(const llvm::RecordKeeper &Records,
                         llvm::raw_ostream &OS, const std::string &Component);

>From dc4232eab5fb22d8e7e25f4beb1895d067b05cb5 Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <nikolasklauser at berlin.de>
Date: Sat, 25 Jan 2025 11:02:04 +0100
Subject: [PATCH 2/6] Use BTName everywhere

---
 clang/include/clang/AST/ASTContext.h  |  8 +++-----
 clang/include/clang/AST/DeclID.h      |  2 +-
 clang/include/clang/Basic/Builtins.h  |  2 +-
 clang/lib/AST/ASTImporter.cpp         |  6 +++---
 clang/lib/Serialization/ASTReader.cpp | 10 +++++-----
 clang/lib/Serialization/ASTWriter.cpp |  4 ++--
 6 files changed, 15 insertions(+), 17 deletions(-)

diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index 98db5522d564e90..f8cef3b86046db0 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -413,9 +413,6 @@ class ASTContext : public RefCountedBase<ASTContext> {
 #define BuiltinTemplate(BTName) mutable IdentifierInfo *Name##BTName = nullptr;
 #include "clang/Basic/BuiltinTemplates.inc"
 
-  /// The identifier '__builtin_common_type'.
-  mutable IdentifierInfo *BuiltinCommonTypeName = nullptr;
-
   QualType ObjCConstantStringType;
   mutable RecordDecl *CFConstantStringTagDecl = nullptr;
   mutable TypedefDecl *CFConstantStringTypeDecl = nullptr;
@@ -622,7 +619,8 @@ class ASTContext : public RefCountedBase<ASTContext> {
   TranslationUnitDecl *TUDecl = nullptr;
   mutable ExternCContextDecl *ExternCContext = nullptr;
 
-#define BuiltinTemplate(Name) mutable BuiltinTemplateDecl *Decl##Name = nullptr;
+#define BuiltinTemplate(BTName)                                                \
+  mutable BuiltinTemplateDecl *Decl##BTName = nullptr;
 #include "clang/Basic/BuiltinTemplates.inc"
 
   /// The associated SourceManager object.
@@ -1150,7 +1148,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
 
   ExternCContextDecl *getExternCContextDecl() const;
 
-#define BuiltinTemplate(Name) BuiltinTemplateDecl *get##Name##Decl() const;
+#define BuiltinTemplate(BTName) BuiltinTemplateDecl *get##BTName##Decl() const;
 #include "clang/Basic/BuiltinTemplates.inc"
 
   // Builtin Types.
diff --git a/clang/include/clang/AST/DeclID.h b/clang/include/clang/AST/DeclID.h
index 71e28ec1f9c65f3..384f7b031e00779 100644
--- a/clang/include/clang/AST/DeclID.h
+++ b/clang/include/clang/AST/DeclID.h
@@ -77,7 +77,7 @@ enum PredefinedDeclIDs {
   /// The internal '__NSConstantString' tag type.
   PREDEF_DECL_CF_CONSTANT_STRING_TAG_ID,
 
-#define BuiltinTemplate(Name) PREDEF_DECL##Name##_ID,
+#define BuiltinTemplate(BTName) PREDEF_DECL##BTName##_ID,
 #include "clang/Basic/BuiltinTemplates.inc"
 
   /// The number of declaration IDs that are predefined.
diff --git a/clang/include/clang/Basic/Builtins.h b/clang/include/clang/Basic/Builtins.h
index eef96f35095a88e..fd9b3c942b36f7b 100644
--- a/clang/include/clang/Basic/Builtins.h
+++ b/clang/include/clang/Basic/Builtins.h
@@ -306,7 +306,7 @@ bool evaluateRequiredTargetFeatures(
 
 /// Kinds of BuiltinTemplateDecl.
 enum BuiltinTemplateKind : int {
-#define BuiltinTemplate(Name) BTK##Name,
+#define BuiltinTemplate(BTName) BTK##BTName,
 #include "clang/Basic/BuiltinTemplates.inc"
 };
 
diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index f63e017c33a0024..64fe18cf3434c6d 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -5461,9 +5461,9 @@ ExpectedDecl ASTNodeImporter::VisitUnresolvedUsingTypenameDecl(
 ExpectedDecl ASTNodeImporter::VisitBuiltinTemplateDecl(BuiltinTemplateDecl *D) {
   Decl* ToD = nullptr;
   switch (D->getBuiltinTemplateKind()) {
-#define BuiltinTemplate(Name)                                                  \
-  case BuiltinTemplateKind::BTK##Name:                                         \
-    ToD = Importer.getToContext().get##Name##Decl();                           \
+#define BuiltinTemplate(BTName)                                                \
+  case BuiltinTemplateKind::BTK##BTName:                                       \
+    ToD = Importer.getToContext().get##BTName##Decl();                         \
     break;
 #include "clang/Basic/BuiltinTemplates.inc"
   }
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index f19f71d14829701..3d251b242961ff3 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -8017,11 +8017,11 @@ Decl *ASTReader::getPredefinedDecl(PredefinedDeclIDs ID) {
     NewLoaded = Context.getCFConstantStringTagDecl();
     break;
 
-#define BuiltinTemplate(Name)                                                  \
-  case PREDEF_DECL##Name##_ID:                                                 \
-    if (Context.Decl##Name)                                                    \
-      return Context.Decl##Name;                                               \
-    NewLoaded = Context.get##Name##Decl();                                     \
+#define BuiltinTemplate(BTName)                                                \
+  case PREDEF_DECL##BTName##_ID:                                               \
+    if (Context.Decl##BTName)                                                  \
+      return Context.Decl##BTName;                                             \
+    NewLoaded = Context.get##BTName##Decl();                                   \
     break;
 #include "clang/Basic/BuiltinTemplates.inc"
 
diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index c21586f79fef019..e0333663bf8bd80 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -5296,8 +5296,8 @@ void ASTWriter::PrepareWritingSpecialDecls(Sema &SemaRef) {
                      PREDEF_DECL_CF_CONSTANT_STRING_ID);
   RegisterPredefDecl(Context.CFConstantStringTagDecl,
                      PREDEF_DECL_CF_CONSTANT_STRING_TAG_ID);
-#define BuiltinTemplate(Name)                                                  \
-  RegisterPredefDecl(Context.Decl##Name, PREDEF_DECL##Name##_ID);
+#define BuiltinTemplate(BTName)                                                \
+  RegisterPredefDecl(Context.Decl##BTName, PREDEF_DECL##BTName##_ID);
 #include "clang/Basic/BuiltinTemplates.inc"
 
   const TranslationUnitDecl *TU = Context.getTranslationUnitDecl();

>From 86111211f879b816929b1988def4c858c4ab011d Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <nikolasklauser at berlin.de>
Date: Sat, 25 Jan 2025 12:03:54 +0100
Subject: [PATCH 3/6] Use stringstream

---
 clang/include/clang/AST/ASTContext.h          |  6 --
 .../TableGen/ClangBuiltinTemplatesEmitter.cpp | 74 ++++++++++---------
 2 files changed, 38 insertions(+), 42 deletions(-)

diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index f8cef3b86046db0..d03dc9e28eae7ee 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -2057,12 +2057,6 @@ class ASTContext : public RefCountedBase<ASTContext> {
   }
 #include "clang/Basic/BuiltinTemplates.inc"
 
-  IdentifierInfo *getBuiltinCommonTypeName() const {
-    if (!BuiltinCommonTypeName)
-      BuiltinCommonTypeName = &Idents.get("__builtin_common_type");
-    return BuiltinCommonTypeName;
-  }
-
   /// Retrieve the Objective-C "instancetype" type, if already known;
   /// otherwise, returns a NULL type;
   QualType getObjCInstanceType() {
diff --git a/clang/utils/TableGen/ClangBuiltinTemplatesEmitter.cpp b/clang/utils/TableGen/ClangBuiltinTemplatesEmitter.cpp
index 8e6d1dbaddea9ee..aa13473a69accb0 100644
--- a/clang/utils/TableGen/ClangBuiltinTemplatesEmitter.cpp
+++ b/clang/utils/TableGen/ClangBuiltinTemplatesEmitter.cpp
@@ -14,10 +14,12 @@
 #include "llvm/TableGen/Error.h"
 #include "llvm/TableGen/TableGenBackend.h"
 
+#include <sstream>
+
 using namespace llvm;
 
-std::string TemplateNameList;
-std::string CreateBuiltinTemplateParameterList;
+static std::string TemplateNameList;
+static std::string CreateBuiltinTemplateParameterList;
 
 namespace {
 struct ParserState {
@@ -29,9 +31,9 @@ struct ParserState {
 std::pair<std::string, std::string>
 ParseTemplateParameterList(ParserState &PS, StringRef &TemplateParmList) {
   auto Alphabetic = [](char c) { return std::isalpha(c); };
-  auto BoolToStr = [](bool b) { return b ? "true" : "false"; };
 
-  std::string Generator;
+  std::ostringstream Generator;
+  Generator << std::boolalpha;
   std::vector<std::string> Params;
   std::unordered_map<std::string, std::string> TemplateNameToParmName;
   TemplateParmList = TemplateParmList.ltrim();
@@ -44,26 +46,26 @@ ParseTemplateParameterList(ParserState &PS, StringRef &TemplateParmList) {
     if (TemplateParmList.consume_front("size_t")) {
       if (!PS.EmittedSizeTInfo) {
         PS.EmittedSizeTInfo = true;
-        Generator += R"C++(
+        Generator << R"C++(
   TypeSourceInfo *SizeTInfo = C.getTrivialTypeSourceInfo(C.getSizeType());
 )C++";
       }
 
-      Generator += "  auto *" + ParmName + R"C++(
+      Generator << "  auto *" << ParmName << R"C++(
     = NonTypeTemplateParmDecl::Create(C, DC, SourceLocation(), SourceLocation(),
-        )C++" + std::to_string(PS.CurrentDepth) +
-                   ", " + std::to_string(Position++) + R"C++(, /*Id=*/nullptr,
+        )C++" << PS.CurrentDepth
+                << ", " << Position++ << R"C++(, /*Id=*/nullptr,
         SizeTInfo->getType(), /*ParameterPack=*/false, SizeTInfo);
 )C++";
     } else if (TemplateParmList.consume_front("class")) {
       bool ParameterPack = TemplateParmList.consume_front("...");
 
-      Generator += "  auto *" + ParmName + R"C++(
+      Generator << "  auto *" << ParmName << R"C++(
     = TemplateTypeParmDecl::Create(C, DC, SourceLocation(), SourceLocation(),
-      )C++" + std::to_string(PS.CurrentDepth) +
-                   ", " + std::to_string(Position++) +
-                   R"C++(, /*Id=*/nullptr, /*Typename=*/false, )C++" +
-                   BoolToStr(ParameterPack) + ");\n";
+      )C++" << PS.CurrentDepth
+                << ", " << Position++
+                << R"C++(, /*Id=*/nullptr, /*Typename=*/false, )C++"
+                << ParameterPack << ");\n";
     } else if (TemplateParmList.consume_front("template")) {
       ++PS.CurrentDepth;
       auto [Code, TPLName] = ParseTemplateParameterList(PS, TemplateParmList);
@@ -72,13 +74,13 @@ ParseTemplateParameterList(ParserState &PS, StringRef &TemplateParmList) {
       if (!TemplateParmList.consume_front("class")) {
         PrintFatalError("Expected 'class' after template template list");
       }
-      Generator += Code;
-      Generator +=
-          "  auto *" + ParmName + R"C++(
-    = TemplateTemplateParmDecl::Create(C, DC, SourceLocation(), )C++" +
-          std::to_string(PS.CurrentDepth) + ", " + std::to_string(Position++) +
-          ", /*ParameterPack=*/false, /*Id=*/nullptr, /*Typename=*/false, " +
-          TPLName + ");\n";
+      Generator << Code;
+      Generator
+          << "  auto *" << ParmName << R"C++(
+    = TemplateTemplateParmDecl::Create(C, DC, SourceLocation(), )C++"
+          << PS.CurrentDepth << ", " << Position++
+          << ", /*ParameterPack=*/false, /*Id=*/nullptr, /*Typename=*/false, "
+          << TPLName << ");\n";
     } else {
       auto Name = TemplateParmList.take_while(Alphabetic).str();
       if (TemplateNameToParmName.find(Name) != TemplateNameToParmName.end()) {
@@ -86,17 +88,17 @@ ParseTemplateParameterList(ParserState &PS, StringRef &TemplateParmList) {
         bool ParameterPack = TemplateParmList.consume_front("...");
 
         auto TSIName = "TSI" + std::to_string(PS.UniqueCounter++);
-        Generator += "  auto *" + TSIName + R"C++(
-    = C.getTrivialTypeSourceInfo(QualType()C++" +
-                     TemplateNameToParmName[Name] +
-                     R"C++(->getTypeForDecl(), 0));
-  auto *)C++" + ParmName +
-                     R"C++( = NonTypeTemplateParmDecl::Create(
-      C, DC, SourceLocation(), SourceLocation(), )C++" +
-                     std::to_string(PS.CurrentDepth) + ", " +
-                     std::to_string(Position++) + ", /*Id=*/nullptr, " +
-                     TSIName + "->getType(), " + BoolToStr(ParameterPack) +
-                     ", " + TSIName + ");\n";
+        Generator << "  auto *" << TSIName << R"C++(
+    = C.getTrivialTypeSourceInfo(QualType()C++"
+                  << TemplateNameToParmName[Name] <<
+            R"C++(->getTypeForDecl(), 0));
+  auto *)C++" << ParmName
+                  <<
+            R"C++( = NonTypeTemplateParmDecl::Create(
+      C, DC, SourceLocation(), SourceLocation(), )C++"
+                  << PS.CurrentDepth << ", " << Position++
+                  << ", /*Id=*/nullptr, " << TSIName << "->getType(), "
+                  << ParameterPack << ", " << TSIName << ");\n";
       } else {
         PrintFatalError("Unknown argument");
       }
@@ -121,7 +123,7 @@ ParseTemplateParameterList(ParserState &PS, StringRef &TemplateParmList) {
   }
 
   auto TPLName = "TPL" + std::to_string(PS.UniqueCounter++);
-  Generator += "  auto *" + TPLName + R"C++( = TemplateParameterList::Create(
+  Generator << "  auto *" << TPLName << R"C++( = TemplateParameterList::Create(
       C, SourceLocation(), SourceLocation(), {)C++";
 
   if (Params.empty())
@@ -132,14 +134,14 @@ ParseTemplateParameterList(ParserState &PS, StringRef &TemplateParmList) {
   for (auto e : Params) {
     if (First) {
       First = false;
-      Generator += e;
+      Generator << e;
     } else {
-      Generator += ", " + e;
+      Generator << ", " << e;
     }
   }
-  Generator += "}, SourceLocation(), nullptr);\n";
+  Generator << "}, SourceLocation(), nullptr);\n";
 
-  return {std::move(Generator), std::move(TPLName)};
+  return {std::move(Generator).str(), std::move(TPLName)};
 }
 
 void EmitCreateBuiltinTemplateParameterList(StringRef Prototype,

>From 417b15f8e28625e696c4254d20626034e79736b8 Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <nikolasklauser at berlin.de>
Date: Sat, 25 Jan 2025 12:06:21 +0100
Subject: [PATCH 4/6] Rename protoype to temaplate_head

---
 clang/include/clang/Basic/BuiltinTemplates.td        |  4 ++--
 .../utils/TableGen/ClangBuiltinTemplatesEmitter.cpp  | 12 ++++++------
 2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/clang/include/clang/Basic/BuiltinTemplates.td b/clang/include/clang/Basic/BuiltinTemplates.td
index 3d51088e0bccafe..60e6bf25a04b8cf 100644
--- a/clang/include/clang/Basic/BuiltinTemplates.td
+++ b/clang/include/clang/Basic/BuiltinTemplates.td
@@ -6,8 +6,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-class BuiltinTemplate<string prototype> {
-  string Prototype = prototype;
+class BuiltinTemplate<string template_head> {
+  string TemplateHead = template_head;
 }
 
 def __make_integer_seq : BuiltinTemplate<
diff --git a/clang/utils/TableGen/ClangBuiltinTemplatesEmitter.cpp b/clang/utils/TableGen/ClangBuiltinTemplatesEmitter.cpp
index aa13473a69accb0..2c3b3cc9a605994 100644
--- a/clang/utils/TableGen/ClangBuiltinTemplatesEmitter.cpp
+++ b/clang/utils/TableGen/ClangBuiltinTemplatesEmitter.cpp
@@ -144,27 +144,27 @@ ParseTemplateParameterList(ParserState &PS, StringRef &TemplateParmList) {
   return {std::move(Generator).str(), std::move(TPLName)};
 }
 
-void EmitCreateBuiltinTemplateParameterList(StringRef Prototype,
+void EmitCreateBuiltinTemplateParameterList(StringRef TemplateHead,
                                             StringRef Name) {
   using namespace std::string_literals;
   CreateBuiltinTemplateParameterList +=
       "case BTK"s + std::string{Name} + ": {\n"s;
-  if (!Prototype.consume_front("template"))
+  if (!TemplateHead.consume_front("template"))
     PrintFatalError(
-        "Expected template prototype to start with 'template' keyword");
+        "Expected template head to start with 'template' keyword");
 
   ParserState PS;
-  auto [Code, TPLName] = ParseTemplateParameterList(PS, Prototype);
+  auto [Code, TPLName] = ParseTemplateParameterList(PS, TemplateHead);
   CreateBuiltinTemplateParameterList += Code + "\n  return " + TPLName + ";\n";
 
   CreateBuiltinTemplateParameterList += "  }\n";
 }
 
 void EmitBuiltinTemplate(raw_ostream &OS, const Record *BuiltinTemplate) {
-  auto Prototype = BuiltinTemplate->getValueAsString("Prototype");
+  auto TemplateHead = BuiltinTemplate->getValueAsString("TemplateHead");
   auto Name = BuiltinTemplate->getName();
 
-  EmitCreateBuiltinTemplateParameterList(Prototype, Name);
+  EmitCreateBuiltinTemplateParameterList(TemplateHead, Name);
 
   TemplateNameList += "BuiltinTemplate(";
   TemplateNameList += Name;

>From c517ac94601ec33dd35d4996714e9286a6b52072 Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <nikolasklauser at berlin.de>
Date: Fri, 7 Feb 2025 23:26:10 +0100
Subject: [PATCH 5/6] Address comments

---
 clang/include/clang/Basic/BuiltinTemplates.td |  42 +++++
 .../TableGen/ClangBuiltinTemplatesEmitter.cpp | 162 ++++++++----------
 2 files changed, 111 insertions(+), 93 deletions(-)

diff --git a/clang/include/clang/Basic/BuiltinTemplates.td b/clang/include/clang/Basic/BuiltinTemplates.td
index 60e6bf25a04b8cf..2007e814b9aad6a 100644
--- a/clang/include/clang/Basic/BuiltinTemplates.td
+++ b/clang/include/clang/Basic/BuiltinTemplates.td
@@ -6,6 +6,47 @@
 //
 //===----------------------------------------------------------------------===//
 
+class TemplateArg<string name> {
+  string Name = name;
+}
+
+class Template<list<TemplateArg> args, string name> : TemplateArg<name> {
+  list<TemplateArg> Args = args;
+}
+
+class Class<string name, bit is_variadic = 0> : TemplateArg<name> {
+  bit IsVariadic = is_variadic;
+}
+
+class NTTP<string type_name, string name, bit is_variadic = 0> : TemplateArg<name> {
+  string TypeName = type_name;
+  bit IsVariadic = is_variadic;
+}
+
+class BuiltinNTTP<string type_name> : TemplateArg<""> {
+  string TypeName = type_name;
+}
+
+def SizeT : BuiltinNTTP<"size_t"> {}
+
+class BuiltinTemplate<list<TemplateArg> template_head> {
+  list<TemplateArg> TemplateHead = template_head;
+}
+
+def __make_integer_seq : BuiltinTemplate<
+  [Template<[Class<"T">, NTTP<"T", "Ints", /*is_variadic=*/1>], "IntSeq">, Class<"T">, NTTP<"T", "N">]>;
+
+def __type_pack_element : BuiltinTemplate<
+  [SizeT, Class<"T", /*is_variadic=*/1>]>;
+
+def __builtin_common_type : BuiltinTemplate<
+  [Template<[Class<"Args", /*is_variadic=*/1>], "BaseTemplate">,
+   Template<[Class<"TypeMember">], "HasTypeMember">,
+   Class<"HasNoTypeMember">,
+   Class<"Ts", /*is_variadic=*/1>]>;
+
+/*
+
 class BuiltinTemplate<string template_head> {
   string TemplateHead = template_head;
 }
@@ -21,3 +62,4 @@ def __builtin_common_type : BuiltinTemplate<
   "          template <class TypeMember> class HasTypeMember,"
   "          class HasNoTypeMember,"
   "          class... Ts>">;
+*/
diff --git a/clang/utils/TableGen/ClangBuiltinTemplatesEmitter.cpp b/clang/utils/TableGen/ClangBuiltinTemplatesEmitter.cpp
index 2c3b3cc9a605994..a9a6b7e8793fbc8 100644
--- a/clang/utils/TableGen/ClangBuiltinTemplatesEmitter.cpp
+++ b/clang/utils/TableGen/ClangBuiltinTemplatesEmitter.cpp
@@ -29,141 +29,117 @@ struct ParserState {
 };
 
 std::pair<std::string, std::string>
-ParseTemplateParameterList(ParserState &PS, StringRef &TemplateParmList) {
-  auto Alphabetic = [](char c) { return std::isalpha(c); };
-
-  std::ostringstream Generator;
-  Generator << std::boolalpha;
+ParseTemplateParameterList(ParserState &PS,
+                           ArrayRef<const Record *> TemplateArgs) {
   std::vector<std::string> Params;
   std::unordered_map<std::string, std::string> TemplateNameToParmName;
-  TemplateParmList = TemplateParmList.ltrim();
-  if (!TemplateParmList.consume_front("<"))
-    PrintFatalError("Expected '<' to start the parameter list");
+
+  std::ostringstream Code;
+  Code << std::boolalpha;
 
   size_t Position = 0;
-  while (true) {
+  for (const Record *Arg : TemplateArgs) {
     std::string ParmName = "Parm" + std::to_string(PS.UniqueCounter++);
-    if (TemplateParmList.consume_front("size_t")) {
-      if (!PS.EmittedSizeTInfo) {
-        PS.EmittedSizeTInfo = true;
-        Generator << R"C++(
-  TypeSourceInfo *SizeTInfo = C.getTrivialTypeSourceInfo(C.getSizeType());
-)C++";
-      }
-
-      Generator << "  auto *" << ParmName << R"C++(
-    = NonTypeTemplateParmDecl::Create(C, DC, SourceLocation(), SourceLocation(),
-        )C++" << PS.CurrentDepth
-                << ", " << Position++ << R"C++(, /*Id=*/nullptr,
-        SizeTInfo->getType(), /*ParameterPack=*/false, SizeTInfo);
-)C++";
-    } else if (TemplateParmList.consume_front("class")) {
-      bool ParameterPack = TemplateParmList.consume_front("...");
-
-      Generator << "  auto *" << ParmName << R"C++(
-    = TemplateTypeParmDecl::Create(C, DC, SourceLocation(), SourceLocation(),
-      )C++" << PS.CurrentDepth
-                << ", " << Position++
-                << R"C++(, /*Id=*/nullptr, /*Typename=*/false, )C++"
-                << ParameterPack << ");\n";
-    } else if (TemplateParmList.consume_front("template")) {
+    if (Arg->isSubClassOf("Template")) {
       ++PS.CurrentDepth;
-      auto [Code, TPLName] = ParseTemplateParameterList(PS, TemplateParmList);
+      auto [TemplateCode, TPLName] =
+          ParseTemplateParameterList(PS, Arg->getValueAsListOfDefs("Args"));
       --PS.CurrentDepth;
-      TemplateParmList = TemplateParmList.ltrim();
-      if (!TemplateParmList.consume_front("class")) {
-        PrintFatalError("Expected 'class' after template template list");
+      Code << TemplateCode << " auto *" << ParmName
+           << " = TemplateTemplateParmDecl::Create(C, DC, SourceLocation(), "
+           << PS.CurrentDepth << ", " << Position++
+           << ", /*ParameterPack=*/false, /*Id=*/nullptr, /*Typename=*/false, "
+           << TPLName << ");\n";
+    } else if (Arg->isSubClassOf("Class")) {
+      Code << " auto *" << ParmName
+           << " = TemplateTypeParmDecl::Create(C, DC, SourceLocation(), "
+              "SourceLocation(), "
+           << PS.CurrentDepth << ", " << Position++
+           << ", /*Id=*/nullptr, /*Typename=*/false, "
+           << Arg->getValueAsBit("IsVariadic") << ");\n";
+    } else if (Arg->isSubClassOf("NTTP")) {
+      auto Type = Arg->getValueAsString("TypeName");
+
+      if (TemplateNameToParmName.find(Type.str()) ==
+          TemplateNameToParmName.end()) {
+        PrintFatalError("Unkown Type Name");
       }
-      Generator << Code;
-      Generator
-          << "  auto *" << ParmName << R"C++(
-    = TemplateTemplateParmDecl::Create(C, DC, SourceLocation(), )C++"
-          << PS.CurrentDepth << ", " << Position++
-          << ", /*ParameterPack=*/false, /*Id=*/nullptr, /*Typename=*/false, "
-          << TPLName << ");\n";
-    } else {
-      auto Name = TemplateParmList.take_while(Alphabetic).str();
-      if (TemplateNameToParmName.find(Name) != TemplateNameToParmName.end()) {
-        TemplateParmList = TemplateParmList.drop_front(Name.size());
-        bool ParameterPack = TemplateParmList.consume_front("...");
-
-        auto TSIName = "TSI" + std::to_string(PS.UniqueCounter++);
-        Generator << "  auto *" << TSIName << R"C++(
-    = C.getTrivialTypeSourceInfo(QualType()C++"
-                  << TemplateNameToParmName[Name] <<
-            R"C++(->getTypeForDecl(), 0));
-  auto *)C++" << ParmName
-                  <<
-            R"C++( = NonTypeTemplateParmDecl::Create(
-      C, DC, SourceLocation(), SourceLocation(), )C++"
-                  << PS.CurrentDepth << ", " << Position++
-                  << ", /*Id=*/nullptr, " << TSIName << "->getType(), "
-                  << ParameterPack << ", " << TSIName << ");\n";
-      } else {
-        PrintFatalError("Unknown argument");
+
+      auto TSIName = "TSI" + std::to_string(PS.UniqueCounter++);
+      Code << " auto *" << TSIName << " = C.getTrivialTypeSourceInfo(QualType("
+           << TemplateNameToParmName[Type.str()] << "->getTypeForDecl(), 0));\n"
+           << " auto *" << ParmName
+           << " = NonTypeTemplateParmDecl::Create(C, DC, SourceLocation(), "
+              "SourceLocation(), "
+           << PS.CurrentDepth << ", " << Position++ << ", /*Id=*/nullptr, "
+           << TSIName << "->getType(), " << Arg->getValueAsBit("IsVariadic")
+           << ", " << TSIName << ");\n";
+    } else if (Arg->isSubClassOf("BuiltinNTTP")) {
+      if (Arg->getValueAsString("TypeName") != "size_t")
+        PrintFatalError("Unkown Type Name");
+      if (!PS.EmittedSizeTInfo) {
+        Code << "TypeSourceInfo *SizeTInfo = "
+                "C.getTrivialTypeSourceInfo(C.getSizeType());\n";
+        PS.EmittedSizeTInfo = true;
       }
-    }
-    TemplateParmList = TemplateParmList.ltrim();
-    auto ID = TemplateParmList.take_while(Alphabetic);
-    if (!ID.empty()) {
-      TemplateNameToParmName[ID.str()] = ParmName;
-      TemplateParmList = TemplateParmList.drop_front(ID.size());
+      Code << " auto *" << ParmName
+           << " = NonTypeTemplateParmDecl::Create(C, DC, SourceLocation(), "
+              "SourceLocation(), "
+           << PS.CurrentDepth << ", " << Position++
+           << ", /*Id=*/nullptr, SizeTInfo->getType(), "
+              "/*ParameterPack=*/false, SizeTInfo);\n";
+    } else {
+      PrintFatalError("Unknown Argument Type");
     }
 
+    TemplateNameToParmName[Arg->getValueAsString("Name").str()] = ParmName;
     Params.emplace_back(std::move(ParmName));
-
-    if (!TemplateParmList.consume_front(","))
-      break;
-    TemplateParmList = TemplateParmList.ltrim();
-  }
-
-  if (!TemplateParmList.consume_front(">")) {
-    PrintWarning("Expected '>' to close template parameter list");
-    PrintWarning(TemplateParmList);
   }
 
   auto TPLName = "TPL" + std::to_string(PS.UniqueCounter++);
-  Generator << "  auto *" << TPLName << R"C++( = TemplateParameterList::Create(
-      C, SourceLocation(), SourceLocation(), {)C++";
+  Code << " auto *" << TPLName
+       << " = TemplateParameterList::Create(C, SourceLocation(), "
+          "SourceLocation(), {";
 
-  if (Params.empty())
+  if (Params.empty()) {
     PrintFatalError(
         "Expected at least one argument in template parameter list");
+  }
 
   bool First = true;
   for (auto e : Params) {
     if (First) {
       First = false;
-      Generator << e;
+      Code << e;
     } else {
-      Generator << ", " << e;
+      Code << ", " << e;
     }
   }
-  Generator << "}, SourceLocation(), nullptr);\n";
+  Code << "}, SourceLocation(), nullptr);\n";
 
-  return {std::move(Generator).str(), std::move(TPLName)};
+  return {std::move(Code).str(), std::move(TPLName)};
 }
 
-void EmitCreateBuiltinTemplateParameterList(StringRef TemplateHead,
-                                            StringRef Name) {
+static void
+EmitCreateBuiltinTemplateParameterList(std::vector<const Record *> TemplateArgs,
+                                       StringRef Name) {
   using namespace std::string_literals;
   CreateBuiltinTemplateParameterList +=
       "case BTK"s + std::string{Name} + ": {\n"s;
-  if (!TemplateHead.consume_front("template"))
-    PrintFatalError(
-        "Expected template head to start with 'template' keyword");
 
   ParserState PS;
-  auto [Code, TPLName] = ParseTemplateParameterList(PS, TemplateHead);
+  auto [Code, TPLName] = ParseTemplateParameterList(PS, TemplateArgs);
   CreateBuiltinTemplateParameterList += Code + "\n  return " + TPLName + ";\n";
 
   CreateBuiltinTemplateParameterList += "  }\n";
 }
 
 void EmitBuiltinTemplate(raw_ostream &OS, const Record *BuiltinTemplate) {
-  auto TemplateHead = BuiltinTemplate->getValueAsString("TemplateHead");
   auto Name = BuiltinTemplate->getName();
 
+  std::vector<const Record *> TemplateHead =
+      BuiltinTemplate->getValueAsListOfDefs("TemplateHead");
+
   EmitCreateBuiltinTemplateParameterList(TemplateHead, Name);
 
   TemplateNameList += "BuiltinTemplate(";

>From 9a582a15e584a1cb20781b15dc7a1d5b3a2ead6a Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <nikolasklauser at berlin.de>
Date: Fri, 7 Feb 2025 23:26:38 +0100
Subject: [PATCH 6/6] Remove old code

---
 clang/include/clang/Basic/BuiltinTemplates.td | 19 -------------------
 1 file changed, 19 deletions(-)

diff --git a/clang/include/clang/Basic/BuiltinTemplates.td b/clang/include/clang/Basic/BuiltinTemplates.td
index 2007e814b9aad6a..e04b9728e3b0120 100644
--- a/clang/include/clang/Basic/BuiltinTemplates.td
+++ b/clang/include/clang/Basic/BuiltinTemplates.td
@@ -44,22 +44,3 @@ def __builtin_common_type : BuiltinTemplate<
    Template<[Class<"TypeMember">], "HasTypeMember">,
    Class<"HasNoTypeMember">,
    Class<"Ts", /*is_variadic=*/1>]>;
-
-/*
-
-class BuiltinTemplate<string template_head> {
-  string TemplateHead = template_head;
-}
-
-def __make_integer_seq : BuiltinTemplate<
-  "template <template <class T, T... Ints> class IntSeq, class T, T N>">;
-
-def __type_pack_element : BuiltinTemplate<
-  "template <size_t, class... T>">;
-
-def __builtin_common_type : BuiltinTemplate<
-  "template <template <class... Args> class BaseTemplate,"
-  "          template <class TypeMember> class HasTypeMember,"
-  "          class HasNoTypeMember,"
-  "          class... Ts>">;
-*/



More information about the cfe-commits mailing list