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 all commits
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
45 changes: 15 additions & 30 deletions clang/include/clang/AST/ASTContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -410,14 +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;

/// The identifier '__builtin_common_type'.
mutable IdentifierInfo *BuiltinCommonTypeName = nullptr;
#define BuiltinTemplate(BTName) mutable IdentifierInfo *Name##BTName = nullptr;
#include "clang/Basic/BuiltinTemplates.inc"

QualType ObjCConstantStringType;
mutable RecordDecl *CFConstantStringTagDecl = nullptr;
Expand Down Expand Up @@ -629,9 +623,10 @@ 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(BTName) \
mutable BuiltinTemplateDecl *Decl##BTName = nullptr;
#include "clang/Basic/BuiltinTemplates.inc"

/// The associated SourceManager object.
SourceManager &SourceMgr;
Expand Down Expand Up @@ -1157,9 +1152,9 @@ class ASTContext : public RefCountedBase<ASTContext> {
}

ExternCContextDecl *getExternCContextDecl() const;
BuiltinTemplateDecl *getMakeIntegerSeqDecl() const;
BuiltinTemplateDecl *getTypePackElementDecl() const;
BuiltinTemplateDecl *getBuiltinCommonTypeDecl() const;

#define BuiltinTemplate(BTName) BuiltinTemplateDecl *get##BTName##Decl() const;
#include "clang/Basic/BuiltinTemplates.inc"

// Builtin Types.
CanQualType VoidTy;
Expand Down Expand Up @@ -2107,23 +2102,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;
}

IdentifierInfo *getBuiltinCommonTypeName() const {
if (!BuiltinCommonTypeName)
BuiltinCommonTypeName = &Idents.get("__builtin_common_type");
return BuiltinCommonTypeName;
#define BuiltinTemplate(BTName) \
IdentifierInfo *get##BTName##Name() const { \
if (!Name##BTName) \
Name##BTName = &Idents.get(#BTName); \
return Name##BTName; \
}
#include "clang/Basic/BuiltinTemplates.inc"

/// Retrieve the Objective-C "instancetype" type, if already known;
/// otherwise, returns a NULL type;
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(BTName) PREDEF_DECL##BTName##_ID,
#include "clang/Basic/BuiltinTemplates.inc"

/// The number of declaration IDs that are predefined.
NUM_PREDEF_DECL_IDS
Expand Down
52 changes: 52 additions & 0 deletions clang/include/clang/Basic/BuiltinTemplates.td
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
//===--- 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 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;
}

// template <template <class T, T... Ints> IntSeq, class T, T N>
def __make_integer_seq : BuiltinTemplate<
[Template<[Class<"T">, NTTP<"T", "Ints", /*is_variadic=*/1>], "IntSeq">, Class<"T">, NTTP<"T", "N">]>;

// template <size_t, class... T>
def __type_pack_element : BuiltinTemplate<
[SizeT, Class<"T", /*is_variadic=*/1>]>;

// template <template <class... Args> BaseTemplate,
// template <class TypeMember> HasTypeMember,
// class HasNoTypeMember
// class... Ts>
def __builtin_common_type : BuiltinTemplate<
[Template<[Class<"Args", /*is_variadic=*/1>], "BaseTemplate">,
Template<[Class<"TypeMember">], "HasTypeMember">,
Class<"HasNoTypeMember">,
Class<"Ts", /*is_variadic=*/1>]>;
10 changes: 2 additions & 8 deletions clang/include/clang/Basic/Builtins.h
Original file line number Diff line number Diff line change
Expand Up @@ -459,14 +459,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(BTName) BTK##BTName,
#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 @@ -96,6 +96,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 @@ -1198,28 +1198,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 @@ -5465,15 +5465,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(BTName) \
case BuiltinTemplateKind::BTK##BTName: \
ToD = Importer.getToContext().get##BTName##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 @@ -1581,140 +1581,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
7 changes: 3 additions & 4 deletions clang/lib/Lex/PPMacroExpansion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1831,10 +1831,9 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) {
return true;
} 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)
// Report builtin templates as being builtins.
#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
Loading