Skip to content

Commit 639a7ac

Browse files
authored
[Clang][AST] Store injected template arguments in TemplateParameterList (#113579)
Currently, we store injected template arguments in `RedeclarableTemplateDecl::CommonBase`. This approach has a couple problems: 1. We can only access the injected template arguments of `RedeclarableTemplateDecl` derived types, but other `Decl` kinds still make use of the injected arguments (e.g. `ClassTemplatePartialSpecializationDecl`, `VarTemplatePartialSpecializationDecl`, and `TemplateTemplateParmDecl`). 2. Accessing the injected template arguments requires the common data structure to be allocated. This may occur before we determine whether a previous declaration exists (e.g. when comparing constraints), so if the template _is_ a redeclaration, we end up discarding the common data structure. This patch moves the storage and access of injected template arguments from `RedeclarableTemplateDecl` to `TemplateParameterList`.
1 parent 4abc357 commit 639a7ac

File tree

6 files changed

+54
-109
lines changed

6 files changed

+54
-109
lines changed

clang/include/clang/AST/ASTContext.h

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
239239
mutable llvm::ContextualFoldingSet<DependentTemplateSpecializationType,
240240
ASTContext&>
241241
DependentTemplateSpecializationTypes;
242-
llvm::FoldingSet<PackExpansionType> PackExpansionTypes;
242+
mutable llvm::FoldingSet<PackExpansionType> PackExpansionTypes;
243243
mutable llvm::FoldingSet<ObjCObjectTypeImpl> ObjCObjectTypes;
244244
mutable llvm::FoldingSet<ObjCObjectPointerType> ObjCObjectPointerTypes;
245245
mutable llvm::FoldingSet<DependentUnaryTransformType>
@@ -1778,13 +1778,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
17781778
ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS,
17791779
const IdentifierInfo *Name, ArrayRef<TemplateArgument> Args) const;
17801780

1781-
TemplateArgument getInjectedTemplateArg(NamedDecl *ParamDecl);
1782-
1783-
/// Get a template argument list with one argument per template parameter
1784-
/// in a template parameter list, such as for the injected class name of
1785-
/// a class template.
1786-
void getInjectedTemplateArgs(const TemplateParameterList *Params,
1787-
SmallVectorImpl<TemplateArgument> &Args);
1781+
TemplateArgument getInjectedTemplateArg(NamedDecl *ParamDecl) const;
17881782

17891783
/// Form a pack expansion type with the given pattern.
17901784
/// \param NumExpansions The number of expansions for the pack, if known.
@@ -1795,7 +1789,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
17951789
/// if this is the canonical type of another pack expansion type.
17961790
QualType getPackExpansionType(QualType Pattern,
17971791
std::optional<unsigned> NumExpansions,
1798-
bool ExpectPackInType = true);
1792+
bool ExpectPackInType = true) const;
17991793

18001794
QualType getObjCInterfaceType(const ObjCInterfaceDecl *Decl,
18011795
ObjCInterfaceDecl *PrevDecl = nullptr) const;

clang/include/clang/AST/DeclTemplate.h

Lines changed: 20 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,9 @@ NamedDecl *getAsNamedDecl(TemplateParameter P);
7171
class TemplateParameterList final
7272
: private llvm::TrailingObjects<TemplateParameterList, NamedDecl *,
7373
Expr *> {
74+
/// The template argument list of the template parameter list.
75+
TemplateArgument *InjectedArgs = nullptr;
76+
7477
/// The location of the 'template' keyword.
7578
SourceLocation TemplateLoc;
7679

@@ -196,6 +199,9 @@ class TemplateParameterList final
196199

197200
bool hasAssociatedConstraints() const;
198201

202+
/// Get the template argument list of the template parameter list.
203+
ArrayRef<TemplateArgument> getInjectedTemplateArgs(const ASTContext &Context);
204+
199205
SourceLocation getTemplateLoc() const { return TemplateLoc; }
200206
SourceLocation getLAngleLoc() const { return LAngleLoc; }
201207
SourceLocation getRAngleLoc() const { return RAngleLoc; }
@@ -793,15 +799,6 @@ class RedeclarableTemplateDecl : public TemplateDecl,
793799
/// The first value in the array is the number of specializations/partial
794800
/// specializations that follow.
795801
GlobalDeclID *LazySpecializations = nullptr;
796-
797-
/// The set of "injected" template arguments used within this
798-
/// template.
799-
///
800-
/// This pointer refers to the template arguments (there are as
801-
/// many template arguments as template parameters) for the
802-
/// template, and is allocated lazily, since most templates do not
803-
/// require the use of this information.
804-
TemplateArgument *InjectedArgs = nullptr;
805802
};
806803

807804
/// Pointer to the common data shared by all declarations of this
@@ -927,7 +924,10 @@ class RedeclarableTemplateDecl : public TemplateDecl,
927924
/// Although the C++ standard has no notion of the "injected" template
928925
/// arguments for a template, the notion is convenient when
929926
/// we need to perform substitutions inside the definition of a template.
930-
ArrayRef<TemplateArgument> getInjectedTemplateArgs();
927+
ArrayRef<TemplateArgument>
928+
getInjectedTemplateArgs(const ASTContext &Context) const {
929+
return getTemplateParameters()->getInjectedTemplateArgs(Context);
930+
}
931931

932932
using redecl_range = redeclarable_base::redecl_range;
933933
using redecl_iterator = redeclarable_base::redecl_iterator;
@@ -2087,10 +2087,6 @@ class ClassTemplatePartialSpecializationDecl
20872087
/// The list of template parameters
20882088
TemplateParameterList *TemplateParams = nullptr;
20892089

2090-
/// The set of "injected" template arguments used within this
2091-
/// partial specialization.
2092-
TemplateArgument *InjectedArgs = nullptr;
2093-
20942090
/// The class template partial specialization from which this
20952091
/// class template partial specialization was instantiated.
20962092
///
@@ -2136,9 +2132,11 @@ class ClassTemplatePartialSpecializationDecl
21362132
return TemplateParams;
21372133
}
21382134

2139-
/// Retrieve the template arguments list of the template parameter list
2140-
/// of this template.
2141-
ArrayRef<TemplateArgument> getInjectedTemplateArgs();
2135+
/// Get the template argument list of the template parameter list.
2136+
ArrayRef<TemplateArgument>
2137+
getInjectedTemplateArgs(const ASTContext &Context) const {
2138+
return getTemplateParameters()->getInjectedTemplateArgs(Context);
2139+
}
21422140

21432141
/// \brief All associated constraints of this partial specialization,
21442142
/// including the requires clause and any constraints derived from
@@ -2864,10 +2862,6 @@ class VarTemplatePartialSpecializationDecl
28642862
/// The list of template parameters
28652863
TemplateParameterList *TemplateParams = nullptr;
28662864

2867-
/// The set of "injected" template arguments used within this
2868-
/// partial specialization.
2869-
TemplateArgument *InjectedArgs = nullptr;
2870-
28712865
/// The variable template partial specialization from which this
28722866
/// variable template partial specialization was instantiated.
28732867
///
@@ -2914,9 +2908,11 @@ class VarTemplatePartialSpecializationDecl
29142908
return TemplateParams;
29152909
}
29162910

2917-
/// Retrieve the template arguments list of the template parameter list
2918-
/// of this template.
2919-
ArrayRef<TemplateArgument> getInjectedTemplateArgs();
2911+
/// Get the template argument list of the template parameter list.
2912+
ArrayRef<TemplateArgument>
2913+
getInjectedTemplateArgs(const ASTContext &Context) const {
2914+
return getTemplateParameters()->getInjectedTemplateArgs(Context);
2915+
}
29202916

29212917
/// \brief All associated constraints of this partial specialization,
29222918
/// including the requires clause and any constraints derived from

clang/lib/AST/ASTContext.cpp

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5634,7 +5634,7 @@ ASTContext::getDependentTemplateSpecializationType(
56345634
return QualType(T, 0);
56355635
}
56365636

5637-
TemplateArgument ASTContext::getInjectedTemplateArg(NamedDecl *Param) {
5637+
TemplateArgument ASTContext::getInjectedTemplateArg(NamedDecl *Param) const {
56385638
TemplateArgument Arg;
56395639
if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(Param)) {
56405640
QualType ArgType = getTypeDeclType(TTP);
@@ -5678,23 +5678,15 @@ TemplateArgument ASTContext::getInjectedTemplateArg(NamedDecl *Param) {
56785678
}
56795679

56805680
if (Param->isTemplateParameterPack())
5681-
Arg = TemplateArgument::CreatePackCopy(*this, Arg);
5681+
Arg =
5682+
TemplateArgument::CreatePackCopy(const_cast<ASTContext &>(*this), Arg);
56825683

56835684
return Arg;
56845685
}
56855686

5686-
void
5687-
ASTContext::getInjectedTemplateArgs(const TemplateParameterList *Params,
5688-
SmallVectorImpl<TemplateArgument> &Args) {
5689-
Args.reserve(Args.size() + Params->size());
5690-
5691-
for (NamedDecl *Param : *Params)
5692-
Args.push_back(getInjectedTemplateArg(Param));
5693-
}
5694-
56955687
QualType ASTContext::getPackExpansionType(QualType Pattern,
56965688
std::optional<unsigned> NumExpansions,
5697-
bool ExpectPackInType) {
5689+
bool ExpectPackInType) const {
56985690
assert((!ExpectPackInType || Pattern->containsUnexpandedParameterPack()) &&
56995691
"Pack expansions must expand one or more parameter packs");
57005692

clang/lib/AST/DeclTemplate.cpp

Lines changed: 14 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ DefaultTemplateArgumentContainsUnexpandedPack(const TemplateParam &P) {
5151
P.getDefaultArgument().getArgument().containsUnexpandedParameterPack();
5252
}
5353

54-
TemplateParameterList::TemplateParameterList(const ASTContext& C,
54+
TemplateParameterList::TemplateParameterList(const ASTContext &C,
5555
SourceLocation TemplateLoc,
5656
SourceLocation LAngleLoc,
5757
ArrayRef<NamedDecl *> Params,
@@ -244,6 +244,17 @@ bool TemplateParameterList::hasAssociatedConstraints() const {
244244
return HasRequiresClause || HasConstrainedParameters;
245245
}
246246

247+
ArrayRef<TemplateArgument>
248+
TemplateParameterList::getInjectedTemplateArgs(const ASTContext &Context) {
249+
if (!InjectedArgs) {
250+
InjectedArgs = new (Context) TemplateArgument[size()];
251+
llvm::transform(*this, InjectedArgs, [&](NamedDecl *ND) {
252+
return Context.getInjectedTemplateArg(ND);
253+
});
254+
}
255+
return {InjectedArgs, NumParams};
256+
}
257+
247258
bool TemplateParameterList::shouldIncludeTypeForArgument(
248259
const PrintingPolicy &Policy, const TemplateParameterList *TPL,
249260
unsigned Idx) {
@@ -396,22 +407,6 @@ void RedeclarableTemplateDecl::addSpecializationImpl(
396407
SETraits::getDecl(Entry));
397408
}
398409

399-
ArrayRef<TemplateArgument> RedeclarableTemplateDecl::getInjectedTemplateArgs() {
400-
TemplateParameterList *Params = getTemplateParameters();
401-
auto *CommonPtr = getCommonPtr();
402-
if (!CommonPtr->InjectedArgs) {
403-
auto &Context = getASTContext();
404-
SmallVector<TemplateArgument, 16> TemplateArgs;
405-
Context.getInjectedTemplateArgs(Params, TemplateArgs);
406-
CommonPtr->InjectedArgs =
407-
new (Context) TemplateArgument[TemplateArgs.size()];
408-
std::copy(TemplateArgs.begin(), TemplateArgs.end(),
409-
CommonPtr->InjectedArgs);
410-
}
411-
412-
return llvm::ArrayRef(CommonPtr->InjectedArgs, Params->size());
413-
}
414-
415410
//===----------------------------------------------------------------------===//
416411
// FunctionTemplateDecl Implementation
417412
//===----------------------------------------------------------------------===//
@@ -631,13 +626,10 @@ ClassTemplateDecl::getInjectedClassNameSpecialization() {
631626
// expansion (14.5.3) whose pattern is the name of the template parameter
632627
// pack.
633628
ASTContext &Context = getASTContext();
634-
TemplateParameterList *Params = getTemplateParameters();
635-
SmallVector<TemplateArgument, 16> TemplateArgs;
636-
Context.getInjectedTemplateArgs(Params, TemplateArgs);
637629
TemplateName Name = Context.getQualifiedTemplateName(
638630
/*NNS=*/nullptr, /*TemplateKeyword=*/false, TemplateName(this));
639-
CommonPtr->InjectedClassNameType =
640-
Context.getTemplateSpecializationType(Name, TemplateArgs);
631+
CommonPtr->InjectedClassNameType = Context.getTemplateSpecializationType(
632+
Name, getTemplateParameters()->getInjectedTemplateArgs(Context));
641633
return CommonPtr->InjectedClassNameType;
642634
}
643635

@@ -1184,20 +1176,6 @@ SourceRange ClassTemplatePartialSpecializationDecl::getSourceRange() const {
11841176
return Range;
11851177
}
11861178

1187-
ArrayRef<TemplateArgument>
1188-
ClassTemplatePartialSpecializationDecl::getInjectedTemplateArgs() {
1189-
TemplateParameterList *Params = getTemplateParameters();
1190-
auto *First = cast<ClassTemplatePartialSpecializationDecl>(getFirstDecl());
1191-
if (!First->InjectedArgs) {
1192-
auto &Context = getASTContext();
1193-
SmallVector<TemplateArgument, 16> TemplateArgs;
1194-
Context.getInjectedTemplateArgs(Params, TemplateArgs);
1195-
First->InjectedArgs = new (Context) TemplateArgument[TemplateArgs.size()];
1196-
std::copy(TemplateArgs.begin(), TemplateArgs.end(), First->InjectedArgs);
1197-
}
1198-
return llvm::ArrayRef(First->InjectedArgs, Params->size());
1199-
}
1200-
12011179
//===----------------------------------------------------------------------===//
12021180
// FriendTemplateDecl Implementation
12031181
//===----------------------------------------------------------------------===//
@@ -1548,20 +1526,6 @@ SourceRange VarTemplatePartialSpecializationDecl::getSourceRange() const {
15481526
return Range;
15491527
}
15501528

1551-
ArrayRef<TemplateArgument>
1552-
VarTemplatePartialSpecializationDecl::getInjectedTemplateArgs() {
1553-
TemplateParameterList *Params = getTemplateParameters();
1554-
auto *First = cast<VarTemplatePartialSpecializationDecl>(getFirstDecl());
1555-
if (!First->InjectedArgs) {
1556-
auto &Context = getASTContext();
1557-
SmallVector<TemplateArgument, 16> TemplateArgs;
1558-
Context.getInjectedTemplateArgs(Params, TemplateArgs);
1559-
First->InjectedArgs = new (Context) TemplateArgument[TemplateArgs.size()];
1560-
std::copy(TemplateArgs.begin(), TemplateArgs.end(), First->InjectedArgs);
1561-
}
1562-
return llvm::ArrayRef(First->InjectedArgs, Params->size());
1563-
}
1564-
15651529
static TemplateParameterList *
15661530
createMakeIntegerSeqParameterList(const ASTContext &C, DeclContext *DC) {
15671531
// typename T

clang/lib/Sema/SemaTemplateDeduction.cpp

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6163,7 +6163,7 @@ struct TemplateArgumentListAreEqual {
61636163
std::enable_if_t<!std::is_same_v<T1, T2>, bool> = true>
61646164
bool operator()(T1 *Spec, T2 *Primary) {
61656165
ArrayRef<TemplateArgument> Args1 = Spec->getTemplateArgs().asArray(),
6166-
Args2 = Primary->getInjectedTemplateArgs();
6166+
Args2 = Primary->getInjectedTemplateArgs(Ctx);
61676167

61686168
for (unsigned I = 0, E = Args1.size(); I < E; ++I) {
61696169
// We use profile, instead of structural comparison of the arguments,
@@ -6342,7 +6342,7 @@ bool Sema::isMoreSpecializedThanPrimary(
63426342
VarTemplateDecl *Primary = Spec->getSpecializedTemplate();
63436343
TemplateName Name(Primary);
63446344
QualType PrimaryT = Context.getTemplateSpecializationType(
6345-
Name, Primary->getInjectedTemplateArgs());
6345+
Name, Primary->getInjectedTemplateArgs(Context));
63466346
QualType PartialT = Context.getTemplateSpecializationType(
63476347
Name, Spec->getTemplateArgs().asArray());
63486348

@@ -6372,18 +6372,14 @@ bool Sema::isTemplateTemplateParameterAtLeastAsSpecializedAs(
63726372
// - Each function template has a single function parameter whose type is
63736373
// a specialization of X with template arguments corresponding to the
63746374
// template parameters from the respective function template
6375-
SmallVector<TemplateArgument, 8> AArgs;
6376-
Context.getInjectedTemplateArgs(A, AArgs);
6375+
SmallVector<TemplateArgument, 8> AArgs(A->getInjectedTemplateArgs(Context));
63776376

63786377
// Check P's arguments against A's parameter list. This will fill in default
63796378
// template arguments as needed. AArgs are already correct by construction.
63806379
// We can't just use CheckTemplateIdType because that will expand alias
63816380
// templates.
6382-
SmallVector<TemplateArgument, 4> PArgs;
6381+
SmallVector<TemplateArgument, 4> PArgs(P->getInjectedTemplateArgs(Context));
63836382
{
6384-
SFINAETrap Trap(*this);
6385-
6386-
Context.getInjectedTemplateArgs(P, PArgs);
63876383
TemplateArgumentListInfo PArgList(P->getLAngleLoc(),
63886384
P->getRAngleLoc());
63896385
for (unsigned I = 0, N = P->size(); I != N; ++I) {
@@ -6399,6 +6395,7 @@ bool Sema::isTemplateTemplateParameterAtLeastAsSpecializedAs(
63996395
}
64006396
PArgs.clear();
64016397

6398+
SFINAETrap Trap(*this);
64026399
// C++1z [temp.arg.template]p3:
64036400
// If the rewrite produces an invalid type, then P is not at least as
64046401
// specialized as A.

clang/lib/Sema/SemaTemplateInstantiate.cpp

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ struct TemplateInstantiationArgumentCollecter
200200
if (Innermost)
201201
AddInnermostTemplateArguments(FTD);
202202
else if (ForConstraintInstantiation)
203-
AddOuterTemplateArguments(FTD, FTD->getInjectedTemplateArgs(),
203+
AddOuterTemplateArguments(FTD, FTD->getInjectedTemplateArgs(S.Context),
204204
/*Final=*/false);
205205

206206
if (FTD->isMemberSpecialization())
@@ -219,7 +219,7 @@ struct TemplateInstantiationArgumentCollecter
219219
if (Innermost)
220220
AddInnermostTemplateArguments(VTD);
221221
else if (ForConstraintInstantiation)
222-
AddOuterTemplateArguments(VTD, VTD->getInjectedTemplateArgs(),
222+
AddOuterTemplateArguments(VTD, VTD->getInjectedTemplateArgs(S.Context),
223223
/*Final=*/false);
224224

225225
if (VTD->isMemberSpecialization())
@@ -237,7 +237,8 @@ struct TemplateInstantiationArgumentCollecter
237237
if (Innermost)
238238
AddInnermostTemplateArguments(VTPSD);
239239
else if (ForConstraintInstantiation)
240-
AddOuterTemplateArguments(VTPSD, VTPSD->getInjectedTemplateArgs(),
240+
AddOuterTemplateArguments(VTPSD,
241+
VTPSD->getInjectedTemplateArgs(S.Context),
241242
/*Final=*/false);
242243

243244
if (VTPSD->isMemberSpecialization())
@@ -254,7 +255,7 @@ struct TemplateInstantiationArgumentCollecter
254255
if (Innermost)
255256
AddInnermostTemplateArguments(CTD);
256257
else if (ForConstraintInstantiation)
257-
AddOuterTemplateArguments(CTD, CTD->getInjectedTemplateArgs(),
258+
AddOuterTemplateArguments(CTD, CTD->getInjectedTemplateArgs(S.Context),
258259
/*Final=*/false);
259260

260261
if (CTD->isMemberSpecialization())
@@ -274,7 +275,8 @@ struct TemplateInstantiationArgumentCollecter
274275
if (Innermost)
275276
AddInnermostTemplateArguments(CTPSD);
276277
else if (ForConstraintInstantiation)
277-
AddOuterTemplateArguments(CTPSD, CTPSD->getInjectedTemplateArgs(),
278+
AddOuterTemplateArguments(CTPSD,
279+
CTPSD->getInjectedTemplateArgs(S.Context),
278280
/*Final=*/false);
279281

280282
if (CTPSD->isMemberSpecialization())
@@ -290,7 +292,7 @@ struct TemplateInstantiationArgumentCollecter
290292
if (Innermost)
291293
AddInnermostTemplateArguments(TATD);
292294
else if (ForConstraintInstantiation)
293-
AddOuterTemplateArguments(TATD, TATD->getInjectedTemplateArgs(),
295+
AddOuterTemplateArguments(TATD, TATD->getInjectedTemplateArgs(S.Context),
294296
/*Final=*/false);
295297

296298
return UseNextDecl(TATD);

0 commit comments

Comments
 (0)