Skip to content

[Clang] Add BuiltinTemplates.td to generate code for builtin templates #123736

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Feb 26, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 14 additions & 21 deletions clang/include/clang/AST/ASTContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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)
Expand Down
10 changes: 2 additions & 8 deletions clang/include/clang/AST/DeclID.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
23 changes: 23 additions & 0 deletions clang/include/clang/Basic/BuiltinTemplates.td
Original file line number Diff line number Diff line change
@@ -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>">;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Its unfortunate that we have this much "just arbitrary text" here. I don't have a better idea, and no real wish to try to make it 'better', but this makes me grumpy and I wanted to let you know.

ALSO, and something that IS actionable: Can we document the importance of the defined 'name'? Since it is the actual name of the builtin that we're exposing to the user? Typically these (names in .td files) are internal names that are generally arbitrary, so it would be nice to document that:

"An entry here will introduce a template builtin with the name X, and whatever-else-we-are-doing-here."

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you think it would be better to give the templates an internal name to be more consistent?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought about this over the weekend. I really think that we want some sort of structures to define the template head here. The base needs a name, then we need a Type, an Non-Type, a Template-Template, and a Variadic (for now).

But having us try to parse this is really going to be error prone and difficult to extend.


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>">;
10 changes: 2 additions & 8 deletions clang/include/clang/Basic/Builtins.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 4 additions & 0 deletions clang/include/clang/Basic/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
30 changes: 8 additions & 22 deletions clang/lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
12 changes: 4 additions & 8 deletions clang/lib/AST/ASTImporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
133 changes: 2 additions & 131 deletions clang/lib/AST/DeclTemplate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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!");
Expand Down
5 changes: 2 additions & 3 deletions clang/lib/Lex/PPMacroExpansion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
18 changes: 6 additions & 12 deletions clang/lib/Sema/SemaLookup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
Loading
Loading