Skip to content

[Clang][AST] Store injected template arguments in TemplateParameterList #113579

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 3 commits into from
Oct 29, 2024
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
12 changes: 3 additions & 9 deletions clang/include/clang/AST/ASTContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
mutable llvm::ContextualFoldingSet<DependentTemplateSpecializationType,
ASTContext&>
DependentTemplateSpecializationTypes;
llvm::FoldingSet<PackExpansionType> PackExpansionTypes;
mutable llvm::FoldingSet<PackExpansionType> PackExpansionTypes;
mutable llvm::FoldingSet<ObjCObjectTypeImpl> ObjCObjectTypes;
mutable llvm::FoldingSet<ObjCObjectPointerType> ObjCObjectPointerTypes;
mutable llvm::FoldingSet<DependentUnaryTransformType>
Expand Down Expand Up @@ -1778,13 +1778,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS,
const IdentifierInfo *Name, ArrayRef<TemplateArgument> Args) const;

TemplateArgument getInjectedTemplateArg(NamedDecl *ParamDecl);

/// Get a template argument list with one argument per template parameter
/// in a template parameter list, such as for the injected class name of
/// a class template.
void getInjectedTemplateArgs(const TemplateParameterList *Params,
SmallVectorImpl<TemplateArgument> &Args);
TemplateArgument getInjectedTemplateArg(NamedDecl *ParamDecl) const;

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

QualType getObjCInterfaceType(const ObjCInterfaceDecl *Decl,
ObjCInterfaceDecl *PrevDecl = nullptr) const;
Expand Down
44 changes: 20 additions & 24 deletions clang/include/clang/AST/DeclTemplate.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,9 @@ NamedDecl *getAsNamedDecl(TemplateParameter P);
class TemplateParameterList final
: private llvm::TrailingObjects<TemplateParameterList, NamedDecl *,
Expr *> {
/// The template argument list of the template parameter list.
TemplateArgument *InjectedArgs = nullptr;

/// The location of the 'template' keyword.
SourceLocation TemplateLoc;

Expand Down Expand Up @@ -196,6 +199,9 @@ class TemplateParameterList final

bool hasAssociatedConstraints() const;

/// Get the template argument list of the template parameter list.
ArrayRef<TemplateArgument> getInjectedTemplateArgs(const ASTContext &Context);

SourceLocation getTemplateLoc() const { return TemplateLoc; }
SourceLocation getLAngleLoc() const { return LAngleLoc; }
SourceLocation getRAngleLoc() const { return RAngleLoc; }
Expand Down Expand Up @@ -793,15 +799,6 @@ class RedeclarableTemplateDecl : public TemplateDecl,
/// The first value in the array is the number of specializations/partial
/// specializations that follow.
GlobalDeclID *LazySpecializations = nullptr;

/// The set of "injected" template arguments used within this
/// template.
///
/// This pointer refers to the template arguments (there are as
/// many template arguments as template parameters) for the
/// template, and is allocated lazily, since most templates do not
/// require the use of this information.
TemplateArgument *InjectedArgs = nullptr;
};

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

using redecl_range = redeclarable_base::redecl_range;
using redecl_iterator = redeclarable_base::redecl_iterator;
Expand Down Expand Up @@ -2087,10 +2087,6 @@ class ClassTemplatePartialSpecializationDecl
/// The list of template parameters
TemplateParameterList *TemplateParams = nullptr;

/// The set of "injected" template arguments used within this
/// partial specialization.
TemplateArgument *InjectedArgs = nullptr;

/// The class template partial specialization from which this
/// class template partial specialization was instantiated.
///
Expand Down Expand Up @@ -2136,9 +2132,11 @@ class ClassTemplatePartialSpecializationDecl
return TemplateParams;
}

/// Retrieve the template arguments list of the template parameter list
/// of this template.
ArrayRef<TemplateArgument> getInjectedTemplateArgs();
/// Get the template argument list of the template parameter list.
ArrayRef<TemplateArgument>
getInjectedTemplateArgs(const ASTContext &Context) const {
return getTemplateParameters()->getInjectedTemplateArgs(Context);
}

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

/// The set of "injected" template arguments used within this
/// partial specialization.
TemplateArgument *InjectedArgs = nullptr;

/// The variable template partial specialization from which this
/// variable template partial specialization was instantiated.
///
Expand Down Expand Up @@ -2914,9 +2908,11 @@ class VarTemplatePartialSpecializationDecl
return TemplateParams;
}

/// Retrieve the template arguments list of the template parameter list
/// of this template.
ArrayRef<TemplateArgument> getInjectedTemplateArgs();
/// Get the template argument list of the template parameter list.
ArrayRef<TemplateArgument>
getInjectedTemplateArgs(const ASTContext &Context) const {
return getTemplateParameters()->getInjectedTemplateArgs(Context);
}

/// \brief All associated constraints of this partial specialization,
/// including the requires clause and any constraints derived from
Expand Down
16 changes: 4 additions & 12 deletions clang/lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5622,7 +5622,7 @@ ASTContext::getDependentTemplateSpecializationType(
return QualType(T, 0);
}

TemplateArgument ASTContext::getInjectedTemplateArg(NamedDecl *Param) {
TemplateArgument ASTContext::getInjectedTemplateArg(NamedDecl *Param) const {
TemplateArgument Arg;
if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(Param)) {
QualType ArgType = getTypeDeclType(TTP);
Expand Down Expand Up @@ -5666,23 +5666,15 @@ TemplateArgument ASTContext::getInjectedTemplateArg(NamedDecl *Param) {
}

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

return Arg;
}

void
ASTContext::getInjectedTemplateArgs(const TemplateParameterList *Params,
SmallVectorImpl<TemplateArgument> &Args) {
Args.reserve(Args.size() + Params->size());

for (NamedDecl *Param : *Params)
Args.push_back(getInjectedTemplateArg(Param));
}

QualType ASTContext::getPackExpansionType(QualType Pattern,
std::optional<unsigned> NumExpansions,
bool ExpectPackInType) {
bool ExpectPackInType) const {
assert((!ExpectPackInType || Pattern->containsUnexpandedParameterPack()) &&
"Pack expansions must expand one or more parameter packs");

Expand Down
64 changes: 14 additions & 50 deletions clang/lib/AST/DeclTemplate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ DefaultTemplateArgumentContainsUnexpandedPack(const TemplateParam &P) {
P.getDefaultArgument().getArgument().containsUnexpandedParameterPack();
}

TemplateParameterList::TemplateParameterList(const ASTContext& C,
TemplateParameterList::TemplateParameterList(const ASTContext &C,
SourceLocation TemplateLoc,
SourceLocation LAngleLoc,
ArrayRef<NamedDecl *> Params,
Expand Down Expand Up @@ -244,6 +244,17 @@ bool TemplateParameterList::hasAssociatedConstraints() const {
return HasRequiresClause || HasConstrainedParameters;
}

ArrayRef<TemplateArgument>
TemplateParameterList::getInjectedTemplateArgs(const ASTContext &Context) {
if (!InjectedArgs) {
InjectedArgs = new (Context) TemplateArgument[size()];
llvm::transform(*this, InjectedArgs, [&](NamedDecl *ND) {
return Context.getInjectedTemplateArg(ND);
});
}
return {InjectedArgs, NumParams};
}

bool TemplateParameterList::shouldIncludeTypeForArgument(
const PrintingPolicy &Policy, const TemplateParameterList *TPL,
unsigned Idx) {
Expand Down Expand Up @@ -396,22 +407,6 @@ void RedeclarableTemplateDecl::addSpecializationImpl(
SETraits::getDecl(Entry));
}

ArrayRef<TemplateArgument> RedeclarableTemplateDecl::getInjectedTemplateArgs() {
TemplateParameterList *Params = getTemplateParameters();
auto *CommonPtr = getCommonPtr();
if (!CommonPtr->InjectedArgs) {
auto &Context = getASTContext();
SmallVector<TemplateArgument, 16> TemplateArgs;
Context.getInjectedTemplateArgs(Params, TemplateArgs);
CommonPtr->InjectedArgs =
new (Context) TemplateArgument[TemplateArgs.size()];
std::copy(TemplateArgs.begin(), TemplateArgs.end(),
CommonPtr->InjectedArgs);
}

return llvm::ArrayRef(CommonPtr->InjectedArgs, Params->size());
}

//===----------------------------------------------------------------------===//
// FunctionTemplateDecl Implementation
//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -631,13 +626,10 @@ ClassTemplateDecl::getInjectedClassNameSpecialization() {
// expansion (14.5.3) whose pattern is the name of the template parameter
// pack.
ASTContext &Context = getASTContext();
TemplateParameterList *Params = getTemplateParameters();
SmallVector<TemplateArgument, 16> TemplateArgs;
Context.getInjectedTemplateArgs(Params, TemplateArgs);
TemplateName Name = Context.getQualifiedTemplateName(
/*NNS=*/nullptr, /*TemplateKeyword=*/false, TemplateName(this));
CommonPtr->InjectedClassNameType =
Context.getTemplateSpecializationType(Name, TemplateArgs);
CommonPtr->InjectedClassNameType = Context.getTemplateSpecializationType(
Name, getTemplateParameters()->getInjectedTemplateArgs(Context));
return CommonPtr->InjectedClassNameType;
}

Expand Down Expand Up @@ -1185,20 +1177,6 @@ SourceRange ClassTemplatePartialSpecializationDecl::getSourceRange() const {
return Range;
}

ArrayRef<TemplateArgument>
ClassTemplatePartialSpecializationDecl::getInjectedTemplateArgs() {
TemplateParameterList *Params = getTemplateParameters();
auto *First = cast<ClassTemplatePartialSpecializationDecl>(getFirstDecl());
if (!First->InjectedArgs) {
auto &Context = getASTContext();
SmallVector<TemplateArgument, 16> TemplateArgs;
Context.getInjectedTemplateArgs(Params, TemplateArgs);
First->InjectedArgs = new (Context) TemplateArgument[TemplateArgs.size()];
std::copy(TemplateArgs.begin(), TemplateArgs.end(), First->InjectedArgs);
}
return llvm::ArrayRef(First->InjectedArgs, Params->size());
}

//===----------------------------------------------------------------------===//
// FriendTemplateDecl Implementation
//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -1549,20 +1527,6 @@ SourceRange VarTemplatePartialSpecializationDecl::getSourceRange() const {
return Range;
}

ArrayRef<TemplateArgument>
VarTemplatePartialSpecializationDecl::getInjectedTemplateArgs() {
TemplateParameterList *Params = getTemplateParameters();
auto *First = cast<VarTemplatePartialSpecializationDecl>(getFirstDecl());
if (!First->InjectedArgs) {
auto &Context = getASTContext();
SmallVector<TemplateArgument, 16> TemplateArgs;
Context.getInjectedTemplateArgs(Params, TemplateArgs);
First->InjectedArgs = new (Context) TemplateArgument[TemplateArgs.size()];
std::copy(TemplateArgs.begin(), TemplateArgs.end(), First->InjectedArgs);
}
return llvm::ArrayRef(First->InjectedArgs, Params->size());
}

static TemplateParameterList *
createMakeIntegerSeqParameterList(const ASTContext &C, DeclContext *DC) {
// typename T
Expand Down
13 changes: 5 additions & 8 deletions clang/lib/Sema/SemaTemplateDeduction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6163,7 +6163,7 @@ struct TemplateArgumentListAreEqual {
std::enable_if_t<!std::is_same_v<T1, T2>, bool> = true>
bool operator()(T1 *Spec, T2 *Primary) {
ArrayRef<TemplateArgument> Args1 = Spec->getTemplateArgs().asArray(),
Args2 = Primary->getInjectedTemplateArgs();
Args2 = Primary->getInjectedTemplateArgs(Ctx);

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

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

// Check P's arguments against A's parameter list. This will fill in default
// template arguments as needed. AArgs are already correct by construction.
// We can't just use CheckTemplateIdType because that will expand alias
// templates.
SmallVector<TemplateArgument, 4> PArgs;
SmallVector<TemplateArgument, 4> PArgs(P->getInjectedTemplateArgs(Context));
{
SFINAETrap Trap(*this);

Context.getInjectedTemplateArgs(P, PArgs);
TemplateArgumentListInfo PArgList(P->getLAngleLoc(),
P->getRAngleLoc());
for (unsigned I = 0, N = P->size(); I != N; ++I) {
Expand All @@ -6399,6 +6395,7 @@ bool Sema::isTemplateTemplateParameterAtLeastAsSpecializedAs(
}
PArgs.clear();

SFINAETrap Trap(*this);
// C++1z [temp.arg.template]p3:
// If the rewrite produces an invalid type, then P is not at least as
// specialized as A.
Expand Down
14 changes: 8 additions & 6 deletions clang/lib/Sema/SemaTemplateInstantiate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ struct TemplateInstantiationArgumentCollecter
if (Innermost)
AddInnermostTemplateArguments(FTD);
else if (ForConstraintInstantiation)
AddOuterTemplateArguments(FTD, FTD->getInjectedTemplateArgs(),
AddOuterTemplateArguments(FTD, FTD->getInjectedTemplateArgs(S.Context),
/*Final=*/false);

if (FTD->isMemberSpecialization())
Expand All @@ -219,7 +219,7 @@ struct TemplateInstantiationArgumentCollecter
if (Innermost)
AddInnermostTemplateArguments(VTD);
else if (ForConstraintInstantiation)
AddOuterTemplateArguments(VTD, VTD->getInjectedTemplateArgs(),
AddOuterTemplateArguments(VTD, VTD->getInjectedTemplateArgs(S.Context),
/*Final=*/false);

if (VTD->isMemberSpecialization())
Expand All @@ -237,7 +237,8 @@ struct TemplateInstantiationArgumentCollecter
if (Innermost)
AddInnermostTemplateArguments(VTPSD);
else if (ForConstraintInstantiation)
AddOuterTemplateArguments(VTPSD, VTPSD->getInjectedTemplateArgs(),
AddOuterTemplateArguments(VTPSD,
VTPSD->getInjectedTemplateArgs(S.Context),
/*Final=*/false);

if (VTPSD->isMemberSpecialization())
Expand All @@ -254,7 +255,7 @@ struct TemplateInstantiationArgumentCollecter
if (Innermost)
AddInnermostTemplateArguments(CTD);
else if (ForConstraintInstantiation)
AddOuterTemplateArguments(CTD, CTD->getInjectedTemplateArgs(),
AddOuterTemplateArguments(CTD, CTD->getInjectedTemplateArgs(S.Context),
/*Final=*/false);

if (CTD->isMemberSpecialization())
Expand All @@ -274,7 +275,8 @@ struct TemplateInstantiationArgumentCollecter
if (Innermost)
AddInnermostTemplateArguments(CTPSD);
else if (ForConstraintInstantiation)
AddOuterTemplateArguments(CTPSD, CTPSD->getInjectedTemplateArgs(),
AddOuterTemplateArguments(CTPSD,
CTPSD->getInjectedTemplateArgs(S.Context),
/*Final=*/false);

if (CTPSD->isMemberSpecialization())
Expand All @@ -290,7 +292,7 @@ struct TemplateInstantiationArgumentCollecter
if (Innermost)
AddInnermostTemplateArguments(TATD);
else if (ForConstraintInstantiation)
AddOuterTemplateArguments(TATD, TATD->getInjectedTemplateArgs(),
AddOuterTemplateArguments(TATD, TATD->getInjectedTemplateArgs(S.Context),
/*Final=*/false);

return UseNextDecl(TATD);
Expand Down
Loading