https://github.com/philnik777 created https://github.com/llvm/llvm-project/pull/123736
This makes it significantly easier to add new builtin templates, since you only have to modify two places instead of a dozen or so. The `BuiltinTemplates.td` could also be extended to generate documentation from it in the future. >From ae765ca2a5e63ecc22068d7f0ad2aad6c3bc4da3 Mon Sep 17 00:00:00 2001 From: Nikolas Klauser <nikolasklau...@berlin.de> Date: Wed, 4 Sep 2024 13:31:39 +0200 Subject: [PATCH] [Clang] Add BuiltinTemplates.td to generate code for builtin templates --- clang/include/clang/AST/ASTContext.h | 34 ++-- 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(+), 233 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 0e07c5d6ce8fba..eed257e4d92fff 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -410,11 +410,9 @@ 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 +622,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 +1150,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 +2052,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 49964b43c7d1d8..71e28ec1f9c65f 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 00000000000000..3d51088e0bccaf --- /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 63559d977ce6b6..eef96f35095a88 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 56c27bacdb20b8..3fe6d8985b32d8 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 be1dd29d462788..288135e47fc39c 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 0669aa1b809c34..f63e017c33a002 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 40ee3753c24227..de060dc612c317 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 347c13da0ad215..fdbf53b9a623a6 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 e1171d4284c763..abfb0569b5c4ff 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 7361cace49dd7b..f19f71d1482970 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 0ae2157eed4ecc..c21586f79fef01 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 5b072a1ac19698..ce759ec8548d9a 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 00000000000000..8e6d1dbaddea9e --- /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 8b8eadbe7f7e54..e526ff9640c51e 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 0448c94de08e3d..cc58489180ba56 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); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits