This revision was automatically updated to reflect the committed changes.
Closed by commit rGc4c2a3c65684: [clang] Implement sugared substitution changes
to infrastructure (authored by mizvekov).
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D134604/new/
https://reviews.llvm.org/D134604
Files:
clang/include/clang/AST/ASTContext.h
clang/include/clang/AST/PropertiesBase.td
clang/include/clang/AST/TemplateName.h
clang/include/clang/AST/Type.h
clang/include/clang/AST/TypeProperties.td
clang/include/clang/Sema/Sema.h
clang/include/clang/Sema/Template.h
clang/lib/AST/ASTContext.cpp
clang/lib/AST/ASTImporter.cpp
clang/lib/AST/TemplateName.cpp
clang/lib/AST/Type.cpp
clang/lib/Sema/SemaConcept.cpp
clang/lib/Sema/SemaExprCXX.cpp
clang/lib/Sema/SemaTemplate.cpp
clang/lib/Sema/SemaTemplateDeduction.cpp
clang/lib/Sema/SemaTemplateInstantiate.cpp
clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
clang/lib/Sema/SemaType.cpp
clang/lib/Sema/TreeTransform.h
clang/lib/Sema/TypeLocBuilder.cpp
clang/lib/Sema/TypeLocBuilder.h
clang/test/SemaTemplate/nested-name-spec-template.cpp
Index: clang/test/SemaTemplate/nested-name-spec-template.cpp
===================================================================
--- clang/test/SemaTemplate/nested-name-spec-template.cpp
+++ clang/test/SemaTemplate/nested-name-spec-template.cpp
@@ -147,3 +147,10 @@
template void f<int>(); // expected-note{{in instantiation of}}
}
+
+namespace sugared_template_instantiation {
+ // Test that we ignore local qualifiers.
+ template <class A1, class = typename A1::type1> struct A {};
+ struct B { typedef int type1; };
+ typedef A<const B> type2;
+} // namespace sugated_template_instantiation
Index: clang/lib/Sema/TypeLocBuilder.h
===================================================================
--- clang/lib/Sema/TypeLocBuilder.h
+++ clang/lib/Sema/TypeLocBuilder.h
@@ -64,6 +64,10 @@
/// must be empty for this to work.
void pushFullCopy(TypeLoc L);
+ /// Pushes 'T' with all locations pointing to 'Loc'.
+ /// The builder must be empty for this to work.
+ void pushTrivial(ASTContext &Context, QualType T, SourceLocation Loc);
+
/// Pushes space for a typespec TypeLoc. Invalidates any TypeLocs
/// previously retrieved from this builder.
TypeSpecTypeLoc pushTypeSpec(QualType T) {
Index: clang/lib/Sema/TypeLocBuilder.cpp
===================================================================
--- clang/lib/Sema/TypeLocBuilder.cpp
+++ clang/lib/Sema/TypeLocBuilder.cpp
@@ -41,6 +41,29 @@
}
}
+void TypeLocBuilder::pushTrivial(ASTContext &Context, QualType T,
+ SourceLocation Loc) {
+ auto L = TypeLoc(T, nullptr);
+ reserve(L.getFullDataSize());
+
+ SmallVector<TypeLoc, 4> TypeLocs;
+ for (auto CurTL = L; CurTL; CurTL = CurTL.getNextTypeLoc())
+ TypeLocs.push_back(CurTL);
+
+ for (const auto &CurTL : llvm::reverse(TypeLocs)) {
+ switch (CurTL.getTypeLocClass()) {
+#define ABSTRACT_TYPELOC(CLASS, PARENT)
+#define TYPELOC(CLASS, PARENT) \
+ case TypeLoc::CLASS: { \
+ auto NewTL = push<class CLASS##TypeLoc>(CurTL.getType()); \
+ NewTL.initializeLocal(Context, Loc); \
+ break; \
+ }
+#include "clang/AST/TypeLocNodes.def"
+ }
+ }
+}
+
void TypeLocBuilder::grow(size_t NewCapacity) {
assert(NewCapacity > Capacity);
Index: clang/lib/Sema/TreeTransform.h
===================================================================
--- clang/lib/Sema/TreeTransform.h
+++ clang/lib/Sema/TreeTransform.h
@@ -636,6 +636,14 @@
QualType Transform##CLASS##Type(TypeLocBuilder &TLB, CLASS##TypeLoc T);
#include "clang/AST/TypeLocNodes.def"
+ QualType TransformTemplateTypeParmType(TypeLocBuilder &TLB,
+ TemplateTypeParmTypeLoc TL,
+ bool SuppressObjCLifetime);
+ QualType
+ TransformSubstTemplateTypeParmPackType(TypeLocBuilder &TLB,
+ SubstTemplateTypeParmPackTypeLoc TL,
+ bool SuppressObjCLifetime);
+
template<typename Fn>
QualType TransformFunctionProtoType(TypeLocBuilder &TLB,
FunctionProtoTypeLoc TL,
@@ -1285,9 +1293,10 @@
/// template name. Subclasses may override this routine to provide different
/// behavior.
TemplateName RebuildTemplateName(const TemplateArgument &ArgPack,
- Decl *AssociatedDecl, unsigned Index) {
+ Decl *AssociatedDecl, unsigned Index,
+ bool Final) {
return getSema().Context.getSubstTemplateTemplateParmPack(
- ArgPack, AssociatedDecl, Index);
+ ArgPack, AssociatedDecl, Index, Final);
}
/// Build a new compound statement.
@@ -4152,9 +4161,13 @@
NestedNameSpecifierLoc NNS, QualType ObjectType,
NamedDecl *FirstQualifierInScope) {
SmallVector<NestedNameSpecifierLoc, 4> Qualifiers;
- for (NestedNameSpecifierLoc Qualifier = NNS; Qualifier;
- Qualifier = Qualifier.getPrefix())
- Qualifiers.push_back(Qualifier);
+
+ auto insertNNS = [&Qualifiers](NestedNameSpecifierLoc NNS) {
+ for (NestedNameSpecifierLoc Qualifier = NNS; Qualifier;
+ Qualifier = Qualifier.getPrefix())
+ Qualifiers.push_back(Qualifier);
+ };
+ insertNNS(NNS);
CXXScopeSpec SS;
while (!Qualifiers.empty()) {
@@ -4211,14 +4224,17 @@
if (!TL)
return NestedNameSpecifierLoc();
- if (TL.getType()->isDependentType() || TL.getType()->isRecordType() ||
- (SemaRef.getLangOpts().CPlusPlus11 &&
- TL.getType()->isEnumeralType())) {
- assert(!TL.getType().hasLocalQualifiers() &&
- "Can't get cv-qualifiers here");
- if (TL.getType()->isEnumeralType())
+ QualType T = TL.getType();
+ if (T->isDependentType() || T->isRecordType() ||
+ (SemaRef.getLangOpts().CPlusPlus11 && T->isEnumeralType())) {
+ if (T->isEnumeralType())
SemaRef.Diag(TL.getBeginLoc(),
diag::warn_cxx98_compat_enum_nested_name_spec);
+
+ if (const auto ETL = TL.getAs<ElaboratedTypeLoc>()) {
+ SS.Adopt(ETL.getQualifierLoc());
+ TL = ETL.getNamedTypeLoc();
+ }
SS.Extend(SemaRef.Context, /*FIXME:*/ SourceLocation(), TL,
Q.getLocalEndLoc());
break;
@@ -4228,7 +4244,7 @@
TypedefTypeLoc TTL = TL.getAsAdjusted<TypedefTypeLoc>();
if (!TTL || !TTL.getTypedefNameDecl()->isInvalidDecl()) {
SemaRef.Diag(TL.getBeginLoc(), diag::err_nested_name_spec_non_tag)
- << TL.getType() << SS.getRange();
+ << T << SS.getRange();
}
return NestedNameSpecifierLoc();
}
@@ -4391,9 +4407,9 @@
if (SubstTemplateTemplateParmPackStorage *SubstPack
= Name.getAsSubstTemplateTemplateParmPack()) {
- return getDerived().RebuildTemplateName(SubstPack->getArgumentPack(),
- SubstPack->getAssociatedDecl(),
- SubstPack->getIndex());
+ return getDerived().RebuildTemplateName(
+ SubstPack->getArgumentPack(), SubstPack->getAssociatedDecl(),
+ SubstPack->getIndex(), SubstPack->getFinal());
}
// These should be getting filtered out before they reach the AST.
@@ -4807,7 +4823,20 @@
QualType
TreeTransform<Derived>::TransformQualifiedType(TypeLocBuilder &TLB,
QualifiedTypeLoc T) {
- QualType Result = getDerived().TransformType(TLB, T.getUnqualifiedLoc());
+ QualType Result;
+ TypeLoc UnqualTL = T.getUnqualifiedLoc();
+ auto SuppressObjCLifetime =
+ T.getType().getLocalQualifiers().hasObjCLifetime();
+ if (auto TTP = UnqualTL.getAs<TemplateTypeParmTypeLoc>()) {
+ Result = getDerived().TransformTemplateTypeParmType(TLB, TTP,
+ SuppressObjCLifetime);
+ } else if (auto STTP = UnqualTL.getAs<SubstTemplateTypeParmPackTypeLoc>()) {
+ Result = getDerived().TransformSubstTemplateTypeParmPackType(
+ TLB, STTP, SuppressObjCLifetime);
+ } else {
+ Result = getDerived().TransformType(TLB, UnqualTL);
+ }
+
if (Result.isNull())
return QualType();
@@ -4870,17 +4899,7 @@
// A lifetime qualifier applied to a substituted template parameter
// overrides the lifetime qualifier from the template argument.
const AutoType *AutoTy;
- if (const SubstTemplateTypeParmType *SubstTypeParam
- = dyn_cast<SubstTemplateTypeParmType>(T)) {
- QualType Replacement = SubstTypeParam->getReplacementType();
- Qualifiers Qs = Replacement.getQualifiers();
- Qs.removeObjCLifetime();
- Replacement = SemaRef.Context.getQualifiedType(
- Replacement.getUnqualifiedType(), Qs);
- T = SemaRef.Context.getSubstTemplateTypeParmType(
- Replacement, SubstTypeParam->getAssociatedDecl(),
- SubstTypeParam->getIndex(), SubstTypeParam->getPackIndex());
- } else if ((AutoTy = dyn_cast<AutoType>(T)) && AutoTy->isDeduced()) {
+ if ((AutoTy = dyn_cast<AutoType>(T)) && AutoTy->isDeduced()) {
// 'auto' types behave the same way as template parameters.
QualType Deduced = AutoTy->getDeducedType();
Qualifiers Qs = Deduced.getQualifiers();
@@ -6422,6 +6441,14 @@
QualType TreeTransform<Derived>::TransformTemplateTypeParmType(
TypeLocBuilder &TLB,
TemplateTypeParmTypeLoc TL) {
+ return getDerived().TransformTemplateTypeParmType(
+ TLB, TL,
+ /*SuppressObjCLifetime=*/false);
+}
+
+template <typename Derived>
+QualType TreeTransform<Derived>::TransformTemplateTypeParmType(
+ TypeLocBuilder &TLB, TemplateTypeParmTypeLoc TL, bool) {
return TransformTypeSpecType(TLB, TL);
}
@@ -6457,6 +6484,13 @@
QualType TreeTransform<Derived>::TransformSubstTemplateTypeParmPackType(
TypeLocBuilder &TLB,
SubstTemplateTypeParmPackTypeLoc TL) {
+ return getDerived().TransformSubstTemplateTypeParmPackType(
+ TLB, TL, /*SuppressObjCLifetime=*/false);
+}
+
+template <typename Derived>
+QualType TreeTransform<Derived>::TransformSubstTemplateTypeParmPackType(
+ TypeLocBuilder &TLB, SubstTemplateTypeParmPackTypeLoc TL, bool) {
return TransformTypeSpecType(TLB, TL);
}
@@ -7240,7 +7274,8 @@
TypeLocBuilder TypeArgBuilder;
TypeArgBuilder.reserve(TypeArgLoc.getFullDataSize());
- QualType NewTypeArg = getDerived().TransformType(TypeArgBuilder, TypeArgLoc);
+ QualType NewTypeArg =
+ getDerived().TransformType(TypeArgBuilder, TypeArgLoc);
if (NewTypeArg.isNull())
return QualType();
@@ -14530,11 +14565,11 @@
ArrayRef<ObjCProtocolDecl *> Protocols,
ArrayRef<SourceLocation> ProtocolLocs,
SourceLocation ProtocolRAngleLoc) {
- return SemaRef.BuildObjCObjectType(BaseType, Loc, TypeArgsLAngleLoc,
- TypeArgs, TypeArgsRAngleLoc,
- ProtocolLAngleLoc, Protocols, ProtocolLocs,
- ProtocolRAngleLoc,
- /*FailOnError=*/true);
+ return SemaRef.BuildObjCObjectType(BaseType, Loc, TypeArgsLAngleLoc, TypeArgs,
+ TypeArgsRAngleLoc, ProtocolLAngleLoc,
+ Protocols, ProtocolLocs, ProtocolRAngleLoc,
+ /*FailOnError=*/true,
+ /*Rebuilding=*/true);
}
template<typename Derived>
Index: clang/lib/Sema/SemaType.cpp
===================================================================
--- clang/lib/Sema/SemaType.cpp
+++ clang/lib/Sema/SemaType.cpp
@@ -829,8 +829,8 @@
/// Apply Objective-C type arguments to the given type.
static QualType applyObjCTypeArgs(Sema &S, SourceLocation loc, QualType type,
ArrayRef<TypeSourceInfo *> typeArgs,
- SourceRange typeArgsRange,
- bool failOnError = false) {
+ SourceRange typeArgsRange, bool failOnError,
+ bool rebuilding) {
// We can only apply type arguments to an Objective-C class type.
const auto *objcObjectType = type->getAs<ObjCObjectType>();
if (!objcObjectType || !objcObjectType->getInterface()) {
@@ -894,7 +894,9 @@
}
}
- if (!diagnosed) {
+ // When rebuilding, qualifiers might have gotten here through a
+ // final substitution.
+ if (!rebuilding && !diagnosed) {
S.Diag(qual.getBeginLoc(), diag::err_objc_type_arg_qualified)
<< typeArg << typeArg.getQualifiers().getAsString()
<< FixItHint::CreateRemoval(rangeToRemove);
@@ -1056,22 +1058,18 @@
return Result;
}
-QualType Sema::BuildObjCObjectType(QualType BaseType,
- SourceLocation Loc,
- SourceLocation TypeArgsLAngleLoc,
- ArrayRef<TypeSourceInfo *> TypeArgs,
- SourceLocation TypeArgsRAngleLoc,
- SourceLocation ProtocolLAngleLoc,
- ArrayRef<ObjCProtocolDecl *> Protocols,
- ArrayRef<SourceLocation> ProtocolLocs,
- SourceLocation ProtocolRAngleLoc,
- bool FailOnError) {
+QualType Sema::BuildObjCObjectType(
+ QualType BaseType, SourceLocation Loc, SourceLocation TypeArgsLAngleLoc,
+ ArrayRef<TypeSourceInfo *> TypeArgs, SourceLocation TypeArgsRAngleLoc,
+ SourceLocation ProtocolLAngleLoc, ArrayRef<ObjCProtocolDecl *> Protocols,
+ ArrayRef<SourceLocation> ProtocolLocs, SourceLocation ProtocolRAngleLoc,
+ bool FailOnError, bool Rebuilding) {
QualType Result = BaseType;
if (!TypeArgs.empty()) {
- Result = applyObjCTypeArgs(*this, Loc, Result, TypeArgs,
- SourceRange(TypeArgsLAngleLoc,
- TypeArgsRAngleLoc),
- FailOnError);
+ Result =
+ applyObjCTypeArgs(*this, Loc, Result, TypeArgs,
+ SourceRange(TypeArgsLAngleLoc, TypeArgsRAngleLoc),
+ FailOnError, Rebuilding);
if (FailOnError && Result.isNull())
return QualType();
}
@@ -1170,10 +1168,11 @@
T, BaseTypeInfo->getTypeLoc().getSourceRange().getBegin(),
TypeArgsLAngleLoc, ActualTypeArgInfos, TypeArgsRAngleLoc,
ProtocolLAngleLoc,
- llvm::makeArrayRef((ObjCProtocolDecl * const *)Protocols.data(),
+ llvm::makeArrayRef((ObjCProtocolDecl *const *)Protocols.data(),
Protocols.size()),
ProtocolLocs, ProtocolRAngleLoc,
- /*FailOnError=*/false);
+ /*FailOnError=*/false,
+ /*Rebuilding=*/false);
if (Result == T)
return BaseType;
Index: clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
===================================================================
--- clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -4552,8 +4552,8 @@
//
// template<typename T>
// A<T> Foo(int a = A<T>::FooImpl());
- MultiLevelTemplateArgumentList TemplateArgs
- = getTemplateInstantiationArgs(FD, nullptr, /*RelativeToPrimary=*/true);
+ MultiLevelTemplateArgumentList TemplateArgs = getTemplateInstantiationArgs(
+ FD, /*Final=*/false, nullptr, /*RelativeToPrimary=*/true);
if (SubstDefaultArgument(CallLoc, Param, TemplateArgs, /*ForCallExpr*/ true))
return true;
@@ -4591,8 +4591,8 @@
Sema::ContextRAII savedContext(*this, Decl);
LocalInstantiationScope Scope(*this);
- MultiLevelTemplateArgumentList TemplateArgs =
- getTemplateInstantiationArgs(Decl, nullptr, /*RelativeToPrimary*/true);
+ MultiLevelTemplateArgumentList TemplateArgs = getTemplateInstantiationArgs(
+ Decl, /*Final=*/false, nullptr, /*RelativeToPrimary*/ true);
// FIXME: We can't use getTemplateInstantiationPattern(false) in general
// here, because for a non-defining friend declaration in a class template,
@@ -4766,7 +4766,8 @@
return nullptr;
ContextRAII SavedContext(*this, FD);
- MultiLevelTemplateArgumentList MArgs(FTD, Args->asArray());
+ MultiLevelTemplateArgumentList MArgs(FTD, Args->asArray(),
+ /*Final=*/false);
return cast_or_null<FunctionDecl>(SubstDecl(FD, FD->getParent(), MArgs));
}
@@ -5032,8 +5033,8 @@
RebuildTypeSourceInfoForDefaultSpecialMembers();
SetDeclDefaulted(Function, PatternDecl->getLocation());
} else {
- MultiLevelTemplateArgumentList TemplateArgs =
- getTemplateInstantiationArgs(Function, nullptr, false, PatternDecl);
+ MultiLevelTemplateArgumentList TemplateArgs = getTemplateInstantiationArgs(
+ Function, /*Final=*/false, nullptr, false, PatternDecl);
// Substitute into the qualifier; we can get a substitution failure here
// through evil use of alias templates.
@@ -5125,13 +5126,13 @@
if (auto *PartialSpec =
dyn_cast<VarTemplatePartialSpecializationDecl>(FromVar)) {
IsMemberSpec = PartialSpec->isMemberSpecialization();
- MultiLevelList.addOuterTemplateArguments(PartialSpec,
- TemplateArgList.asArray());
+ MultiLevelList.addOuterTemplateArguments(
+ PartialSpec, TemplateArgList.asArray(), /*Final=*/false);
} else {
assert(VarTemplate == FromVar->getDescribedVarTemplate());
IsMemberSpec = VarTemplate->isMemberSpecialization();
- MultiLevelList.addOuterTemplateArguments(VarTemplate,
- TemplateArgList.asArray());
+ MultiLevelList.addOuterTemplateArguments(
+ VarTemplate, TemplateArgList.asArray(), /*Final=*/false);
}
if (!IsMemberSpec)
FromVar = FromVar->getFirstDecl();
Index: clang/lib/Sema/SemaTemplateInstantiate.cpp
===================================================================
--- clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -94,13 +94,15 @@
if (VarTemplatePartialSpecializationDecl *Partial =
Specialized.dyn_cast<VarTemplatePartialSpecializationDecl *>()) {
Result.addOuterTemplateArguments(
- Partial, VarTemplSpec->getTemplateInstantiationArgs().asArray());
+ Partial, VarTemplSpec->getTemplateInstantiationArgs().asArray(),
+ /*Final=*/false);
if (Partial->isMemberSpecialization())
return Response::Done();
} else {
VarTemplateDecl *Tmpl = Specialized.get<VarTemplateDecl *>();
Result.addOuterTemplateArguments(
- Tmpl, VarTemplSpec->getTemplateInstantiationArgs().asArray());
+ Tmpl, VarTemplSpec->getTemplateInstantiationArgs().asArray(),
+ /*Final=*/false);
if (Tmpl->isMemberSpecialization())
return Response::Done();
}
@@ -133,7 +135,8 @@
Result.addOuterTemplateArguments(
const_cast<ClassTemplateSpecializationDecl *>(ClassTemplSpec),
- ClassTemplSpec->getTemplateInstantiationArgs().asArray());
+ ClassTemplSpec->getTemplateInstantiationArgs().asArray(),
+ /*Final=*/false);
// If this class template specialization was instantiated from a
// specialized member that is a class template, we're done.
@@ -164,7 +167,8 @@
Function->getTemplateSpecializationArgs()) {
// Add the template arguments for this specialization.
Result.addOuterTemplateArguments(const_cast<FunctionDecl *>(Function),
- TemplateArgs->asArray());
+ TemplateArgs->asArray(),
+ /*Final=*/false);
// If this function was instantiated from a specialized member that is
// a function template, we're done.
@@ -210,7 +214,8 @@
->getInjectedSpecializationType();
const auto *InjectedType = cast<TemplateSpecializationType>(Injected);
Result.addOuterTemplateArguments(const_cast<CXXRecordDecl *>(Rec),
- InjectedType->template_arguments());
+ InjectedType->template_arguments(),
+ /*Final=*/false);
}
}
@@ -236,7 +241,8 @@
MultiLevelTemplateArgumentList &Result) {
Result.addOuterTemplateArguments(
const_cast<ImplicitConceptSpecializationDecl *>(CSD),
- CSD->getTemplateArguments());
+ CSD->getTemplateArguments(),
+ /*Final=*/false);
return Response::UseNextDecl(CSD);
}
@@ -271,7 +277,7 @@
/// arguments on an enclosing class template.
MultiLevelTemplateArgumentList Sema::getTemplateInstantiationArgs(
- const NamedDecl *ND, const TemplateArgumentList *Innermost,
+ const NamedDecl *ND, bool Final, const TemplateArgumentList *Innermost,
bool RelativeToPrimary, const FunctionDecl *Pattern,
bool ForConstraintInstantiation) {
assert(ND && "Can't find arguments for a decl if one isn't provided");
@@ -280,7 +286,7 @@
if (Innermost)
Result.addOuterTemplateArguments(const_cast<NamedDecl *>(ND),
- Innermost->asArray());
+ Innermost->asArray(), Final);
const Decl *CurDecl = ND;
@@ -1120,6 +1126,13 @@
return TemplateArgs.getNewDepth(Depth);
}
+ Optional<unsigned> getPackIndex(TemplateArgument Pack) {
+ int Index = getSema().ArgumentPackSubstitutionIndex;
+ if (Index == -1)
+ return None;
+ return Pack.pack_size() - 1 - Index;
+ }
+
bool TryExpandParameterPacks(SourceLocation EllipsisLoc,
SourceRange PatternRange,
ArrayRef<UnexpandedParameterPack> Unexpanded,
@@ -1288,16 +1301,26 @@
Optional<unsigned> NumExpansions,
bool ExpectParameterPack);
+ using inherited::TransformTemplateTypeParmType;
/// Transforms a template type parameter type by performing
/// substitution of the corresponding template type argument.
QualType TransformTemplateTypeParmType(TypeLocBuilder &TLB,
- TemplateTypeParmTypeLoc TL);
+ TemplateTypeParmTypeLoc TL,
+ bool SuppressObjCLifetime);
+
+ QualType BuildSubstTemplateTypeParmType(
+ TypeLocBuilder &TLB, bool SuppressObjCLifetime, bool Final,
+ Decl *AssociatedDecl, unsigned Index, Optional<unsigned> PackIndex,
+ TemplateArgument Arg, SourceLocation NameLoc);
/// Transforms an already-substituted template type parameter pack
/// into either itself (if we aren't substituting into its pack expansion)
/// or the appropriate substituted argument.
- QualType TransformSubstTemplateTypeParmPackType(TypeLocBuilder &TLB,
- SubstTemplateTypeParmPackTypeLoc TL);
+ using inherited::TransformSubstTemplateTypeParmPackType;
+ QualType
+ TransformSubstTemplateTypeParmPackType(TypeLocBuilder &TLB,
+ SubstTemplateTypeParmPackTypeLoc TL,
+ bool SuppressObjCLifetime);
ExprResult TransformLambdaExpr(LambdaExpr *E) {
LocalInstantiationScope Scope(SemaRef, /*CombineWithOuterScope=*/true);
@@ -1580,7 +1603,8 @@
return Arg.getAsTemplate();
}
- Decl *AssociatedDecl = TemplateArgs.getAssociatedDecl(TTP->getDepth());
+ auto [AssociatedDecl, Final] =
+ TemplateArgs.getAssociatedDecl(TTP->getDepth());
Optional<unsigned> PackIndex;
if (TTP->isParameterPack()) {
assert(Arg.getKind() == TemplateArgument::Pack &&
@@ -1591,11 +1615,11 @@
// actually expanding the enclosing pack expansion yet. So, just
// keep the entire argument pack.
return getSema().Context.getSubstTemplateTemplateParmPack(
- Arg, AssociatedDecl, TTP->getIndex());
+ Arg, AssociatedDecl, TTP->getIndex(), Final);
}
+ PackIndex = getPackIndex(Arg);
Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);
- PackIndex = getSema().ArgumentPackSubstitutionIndex;
}
TemplateName Template = Arg.getAsTemplate().getNameToSubstitute();
@@ -1603,9 +1627,10 @@
assert(!Template.getAsQualifiedTemplateName() &&
"template decl to substitute is qualified?");
- Template = getSema().Context.getSubstTemplateTemplateParm(
+ if (Final)
+ return Template;
+ return getSema().Context.getSubstTemplateTemplateParm(
Template, AssociatedDecl, TTP->getIndex(), PackIndex);
- return Template;
}
}
@@ -1614,9 +1639,14 @@
if (getSema().ArgumentPackSubstitutionIndex == -1)
return Name;
- TemplateArgument Arg = SubstPack->getArgumentPack();
- Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);
- return Arg.getAsTemplate().getNameToSubstitute();
+ TemplateArgument Pack = SubstPack->getArgumentPack();
+ TemplateName Template =
+ getPackSubstitutedTemplateArgument(getSema(), Pack).getAsTemplate();
+ if (SubstPack->getFinal())
+ return Template;
+ return getSema().Context.getSubstTemplateTemplateParm(
+ Template.getNameToSubstitute(), SubstPack->getAssociatedDecl(),
+ SubstPack->getIndex(), getPackIndex(Pack));
}
return inherited::TransformTemplateName(SS, Name, NameLoc, ObjectType,
@@ -1660,7 +1690,7 @@
return Arg.getAsExpr();
}
- Decl *AssociatedDecl = TemplateArgs.getAssociatedDecl(NTTP->getDepth());
+ auto [AssociatedDecl, _] = TemplateArgs.getAssociatedDecl(NTTP->getDepth());
Optional<unsigned> PackIndex;
if (NTTP->isParameterPack()) {
assert(Arg.getKind() == TemplateArgument::Pack &&
@@ -1679,15 +1709,15 @@
QualType ExprType = TargetType.getNonLValueExprType(SemaRef.Context);
if (TargetType->isRecordType())
ExprType.addConst();
-
+ // FIXME: Pass in Final.
return new (SemaRef.Context) SubstNonTypeTemplateParmPackExpr(
ExprType, TargetType->isReferenceType() ? VK_LValue : VK_PRValue,
E->getLocation(), Arg, AssociatedDecl, NTTP->getPosition());
}
- PackIndex = getSema().ArgumentPackSubstitutionIndex;
+ PackIndex = getPackIndex(Arg);
Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);
}
-
+ // FIXME: Don't put subst node on Final replacement.
return transformNonTypeTemplateParmRef(AssociatedDecl, NTTP, E->getLocation(),
Arg, PackIndex);
}
@@ -1779,6 +1809,7 @@
return ExprError();
Expr *resultExpr = result.get();
+ // FIXME: Don't put subst node on final replacement.
return new (SemaRef.Context) SubstNonTypeTemplateParmExpr(
resultExpr->getType(), resultExpr->getValueKind(), loc, resultExpr,
AssociatedDecl, parm->getIndex(), PackIndex, refParam);
@@ -1787,17 +1818,17 @@
ExprResult
TemplateInstantiator::TransformSubstNonTypeTemplateParmPackExpr(
SubstNonTypeTemplateParmPackExpr *E) {
- int PackIndex = getSema().ArgumentPackSubstitutionIndex;
- if (PackIndex == -1) {
+ if (getSema().ArgumentPackSubstitutionIndex == -1) {
// We aren't expanding the parameter pack, so just return ourselves.
return E;
}
- TemplateArgument Arg = E->getArgumentPack();
- Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);
+ TemplateArgument Pack = E->getArgumentPack();
+ TemplateArgument Arg = getPackSubstitutedTemplateArgument(getSema(), Pack);
+ // FIXME: Don't put subst node on final replacement.
return transformNonTypeTemplateParmRef(
E->getAssociatedDecl(), E->getParameterPack(),
- E->getParameterPackLocation(), Arg, PackIndex);
+ E->getParameterPackLocation(), Arg, getPackIndex(Pack));
}
ExprResult
@@ -1840,7 +1871,7 @@
return true;
return transformNonTypeTemplateParmRef(E->getAssociatedDecl(),
E->getParameter(), E->getExprLoc(),
- CanonicalConverted, E->getPackIndex());
+ SugaredConverted, E->getPackIndex());
}
ExprResult TemplateInstantiator::RebuildVarDeclRefExpr(VarDecl *PD,
@@ -1971,9 +2002,39 @@
return NewParm;
}
+QualType TemplateInstantiator::BuildSubstTemplateTypeParmType(
+ TypeLocBuilder &TLB, bool SuppressObjCLifetime, bool Final,
+ Decl *AssociatedDecl, unsigned Index, Optional<unsigned> PackIndex,
+ TemplateArgument Arg, SourceLocation NameLoc) {
+ QualType Replacement = Arg.getAsType();
+
+ // If the template parameter had ObjC lifetime qualifiers,
+ // then any such qualifiers on the replacement type are ignored.
+ if (SuppressObjCLifetime) {
+ Qualifiers RQs;
+ RQs = Replacement.getQualifiers();
+ RQs.removeObjCLifetime();
+ Replacement =
+ SemaRef.Context.getQualifiedType(Replacement.getUnqualifiedType(), RQs);
+ }
+
+ if (Final) {
+ TLB.pushTrivial(SemaRef.Context, Replacement, NameLoc);
+ return Replacement;
+ }
+ // TODO: only do this uniquing once, at the start of instantiation.
+ QualType Result = getSema().Context.getSubstTemplateTypeParmType(
+ Replacement, AssociatedDecl, Index, PackIndex);
+ SubstTemplateTypeParmTypeLoc NewTL =
+ TLB.push<SubstTemplateTypeParmTypeLoc>(Result);
+ NewTL.setNameLoc(NameLoc);
+ return Result;
+}
+
QualType
TemplateInstantiator::TransformTemplateTypeParmType(TypeLocBuilder &TLB,
- TemplateTypeParmTypeLoc TL) {
+ TemplateTypeParmTypeLoc TL,
+ bool SuppressObjCLifetime) {
const TemplateTypeParmType *T = TL.getTypePtr();
if (T->getDepth() < TemplateArgs.getNumLevels()) {
// Replace the template type parameter with its corresponding
@@ -2010,8 +2071,8 @@
return NewT;
}
- Decl *AssociatedDecl =
- const_cast<Decl *>(TemplateArgs.getAssociatedDecl(T->getDepth()));
+ auto [AssociatedDecl, Final] =
+ TemplateArgs.getAssociatedDecl(T->getDepth());
Optional<unsigned> PackIndex;
if (T->isParameterPack()) {
assert(Arg.getKind() == TemplateArgument::Pack &&
@@ -2022,7 +2083,7 @@
// enclosing pack expansion yet. Just save the template argument
// pack for later substitution.
QualType Result = getSema().Context.getSubstTemplateTypeParmPackType(
- AssociatedDecl, T->getIndex(), Arg);
+ AssociatedDecl, T->getIndex(), Final, Arg);
SubstTemplateTypeParmPackTypeLoc NewTL
= TLB.push<SubstTemplateTypeParmPackTypeLoc>(Result);
NewTL.setNameLoc(TL.getNameLoc());
@@ -2030,22 +2091,16 @@
}
// PackIndex starts from last element.
- PackIndex = Arg.pack_size() - 1 - getSema().ArgumentPackSubstitutionIndex;
+ PackIndex = getPackIndex(Arg);
Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);
}
assert(Arg.getKind() == TemplateArgument::Type &&
"Template argument kind mismatch");
- QualType Replacement = Arg.getAsType();
-
- // TODO: only do this uniquing once, at the start of instantiation.
- QualType Result = getSema().Context.getSubstTemplateTypeParmType(
- Replacement, AssociatedDecl, T->getIndex(), PackIndex);
- SubstTemplateTypeParmTypeLoc NewTL
- = TLB.push<SubstTemplateTypeParmTypeLoc>(Result);
- NewTL.setNameLoc(TL.getNameLoc());
- return Result;
+ return BuildSubstTemplateTypeParmType(TLB, SuppressObjCLifetime, Final,
+ AssociatedDecl, T->getIndex(),
+ PackIndex, Arg, TL.getNameLoc());
}
// The template type parameter comes from an inner template (e.g.,
@@ -2065,7 +2120,8 @@
}
QualType TemplateInstantiator::TransformSubstTemplateTypeParmPackType(
- TypeLocBuilder &TLB, SubstTemplateTypeParmPackTypeLoc TL) {
+ TypeLocBuilder &TLB, SubstTemplateTypeParmPackTypeLoc TL,
+ bool SuppressObjCLifetime) {
const SubstTemplateTypeParmPackType *T = TL.getTypePtr();
Decl *NewReplaced = TransformDecl(TL.getNameLoc(), T->getAssociatedDecl());
@@ -2075,7 +2131,7 @@
QualType Result = TL.getType();
if (NewReplaced != T->getAssociatedDecl())
Result = getSema().Context.getSubstTemplateTypeParmPackType(
- NewReplaced, T->getIndex(), T->getArgumentPack());
+ NewReplaced, T->getIndex(), T->getFinal(), T->getArgumentPack());
SubstTemplateTypeParmPackTypeLoc NewTL =
TLB.push<SubstTemplateTypeParmPackTypeLoc>(Result);
NewTL.setNameLoc(TL.getNameLoc());
@@ -2084,14 +2140,9 @@
TemplateArgument Pack = T->getArgumentPack();
TemplateArgument Arg = getPackSubstitutedTemplateArgument(getSema(), Pack);
- // PackIndex starts from last element.
- QualType Result = getSema().Context.getSubstTemplateTypeParmType(
- Arg.getAsType(), NewReplaced, T->getIndex(),
- Pack.pack_size() - 1 - getSema().ArgumentPackSubstitutionIndex);
- SubstTemplateTypeParmTypeLoc NewTL =
- TLB.push<SubstTemplateTypeParmTypeLoc>(Result);
- NewTL.setNameLoc(TL.getNameLoc());
- return Result;
+ return BuildSubstTemplateTypeParmType(
+ TLB, SuppressObjCLifetime, T->getFinal(), NewReplaced, T->getIndex(),
+ getPackIndex(Pack), Arg, TL.getNameLoc());
}
template<typename EntityPrinter>
Index: clang/lib/Sema/SemaTemplateDeduction.cpp
===================================================================
--- clang/lib/Sema/SemaTemplateDeduction.cpp
+++ clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -2687,9 +2687,8 @@
// itself, in case that substitution fails.
if (SugaredPackedArgsBuilder.empty()) {
LocalInstantiationScope Scope(S);
- TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack,
- CanonicalOutput);
- MultiLevelTemplateArgumentList Args(Template, TemplateArgs.asArray());
+ MultiLevelTemplateArgumentList Args(Template, CanonicalOutput,
+ /*Final=*/false);
if (auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(Param)) {
Sema::InstantiatingTemplate Inst(S, Template->getLocation(), Template,
@@ -2890,7 +2889,8 @@
CanonicalDeducedArgs};
MultiLevelTemplateArgumentList MLTAL = S.getTemplateInstantiationArgs(
- Template, /*InnerMost=*/NeedsReplacement ? nullptr : &DeducedTAL,
+ Template, /*Final=*/false,
+ /*InnerMost=*/NeedsReplacement ? nullptr : &DeducedTAL,
/*RelativeToPrimary=*/true, /*Pattern=*/
nullptr, /*ForConstraintInstantiation=*/true);
@@ -2959,11 +2959,12 @@
TemplateArgumentListInfo InstArgs(PartialTemplArgInfo->LAngleLoc,
PartialTemplArgInfo->RAngleLoc);
- if (S.SubstTemplateArguments(
- PartialTemplArgInfo->arguments(),
- MultiLevelTemplateArgumentList(
- Partial, CanonicalDeducedArgumentList->asArray()),
- InstArgs)) {
+ if (S.SubstTemplateArguments(PartialTemplArgInfo->arguments(),
+ MultiLevelTemplateArgumentList(
+ Partial,
+ CanonicalDeducedArgumentList->asArray(),
+ /*Final=*/false),
+ InstArgs)) {
unsigned ArgIdx = InstArgs.size(), ParamIdx = ArgIdx;
if (ParamIdx >= Partial->getTemplateParameters()->size())
ParamIdx = Partial->getTemplateParameters()->size() - 1;
@@ -3301,17 +3302,18 @@
ExtParameterInfoBuilder ExtParamInfos;
+ MultiLevelTemplateArgumentList MLTAL(FunctionTemplate,
+ CanonicalExplicitArgumentList->asArray(),
+ /*Final=*/false);
+
// Instantiate the types of each of the function parameters given the
// explicitly-specified template arguments. If the function has a trailing
// return type, substitute it after the arguments to ensure we substitute
// in lexical order.
if (Proto->hasTrailingReturn()) {
- if (SubstParmTypes(
- Function->getLocation(), Function->parameters(),
- Proto->getExtParameterInfosOrNull(),
- MultiLevelTemplateArgumentList(
- FunctionTemplate, CanonicalExplicitArgumentList->asArray()),
- ParamTypes, /*params=*/nullptr, ExtParamInfos))
+ if (SubstParmTypes(Function->getLocation(), Function->parameters(),
+ Proto->getExtParameterInfosOrNull(), MLTAL, ParamTypes,
+ /*params=*/nullptr, ExtParamInfos))
return TDK_SubstitutionFailure;
}
@@ -3334,11 +3336,9 @@
CXXThisScopeRAII ThisScope(*this, ThisContext, ThisTypeQuals,
getLangOpts().CPlusPlus11);
- ResultType = SubstType(
- Proto->getReturnType(),
- MultiLevelTemplateArgumentList(
- FunctionTemplate, CanonicalExplicitArgumentList->asArray()),
- Function->getTypeSpecStartLoc(), Function->getDeclName());
+ ResultType =
+ SubstType(Proto->getReturnType(), MLTAL,
+ Function->getTypeSpecStartLoc(), Function->getDeclName());
if (ResultType.isNull() || Trap.hasErrorOccurred())
return TDK_SubstitutionFailure;
// CUDA: Kernel function must have 'void' return type.
@@ -3353,12 +3353,9 @@
// Instantiate the types of each of the function parameters given the
// explicitly-specified template arguments if we didn't do so earlier.
if (!Proto->hasTrailingReturn() &&
- SubstParmTypes(
- Function->getLocation(), Function->parameters(),
- Proto->getExtParameterInfosOrNull(),
- MultiLevelTemplateArgumentList(
- FunctionTemplate, CanonicalExplicitArgumentList->asArray()),
- ParamTypes, /*params*/ nullptr, ExtParamInfos))
+ SubstParmTypes(Function->getLocation(), Function->parameters(),
+ Proto->getExtParameterInfosOrNull(), MLTAL, ParamTypes,
+ /*params*/ nullptr, ExtParamInfos))
return TDK_SubstitutionFailure;
if (FunctionType) {
@@ -3370,10 +3367,8 @@
// specification.
SmallVector<QualType, 4> ExceptionStorage;
if (getLangOpts().CPlusPlus17 &&
- SubstExceptionSpec(
- Function->getLocation(), EPI.ExceptionSpec, ExceptionStorage,
- MultiLevelTemplateArgumentList(
- FunctionTemplate, CanonicalExplicitArgumentList->asArray())))
+ SubstExceptionSpec(Function->getLocation(), EPI.ExceptionSpec,
+ ExceptionStorage, MLTAL))
return TDK_SubstitutionFailure;
*FunctionType = BuildFunctionType(ResultType, ParamTypes,
@@ -3616,7 +3611,8 @@
if (FunctionTemplate->getFriendObjectKind())
Owner = FunctionTemplate->getLexicalDeclContext();
MultiLevelTemplateArgumentList SubstArgs(
- FunctionTemplate, CanonicalDeducedArgumentList->asArray());
+ FunctionTemplate, CanonicalDeducedArgumentList->asArray(),
+ /*Final=*/false);
Specialization = cast_or_null<FunctionDecl>(
SubstDecl(FunctionTemplate->getTemplatedDecl(), Owner, SubstArgs));
if (!Specialization || Specialization->isInvalidDecl())
@@ -4677,7 +4673,8 @@
/*PartialTemplateArgs=*/false,
SugaredConverted, CanonicalConverted))
return true;
- MultiLevelTemplateArgumentList MLTAL(Concept, CanonicalConverted);
+ MultiLevelTemplateArgumentList MLTAL(Concept, CanonicalConverted,
+ /*Final=*/false);
if (S.CheckConstraintSatisfaction(Concept, {Concept->getConstraintExpr()},
MLTAL, TypeLoc.getLocalSourceRange(),
Satisfaction))
Index: clang/lib/Sema/SemaTemplate.cpp
===================================================================
--- clang/lib/Sema/SemaTemplate.cpp
+++ clang/lib/Sema/SemaTemplate.cpp
@@ -1720,14 +1720,17 @@
// SubstTempalteTypeParmPack, SubstNonTypeTemplateParmPack, and
// FunctionParmPackExpr are all partially substituted, which cannot happen
// with concepts at this point in translation.
+ using inherited::TransformTemplateTypeParmType;
QualType TransformTemplateTypeParmType(TypeLocBuilder &TLB,
- TemplateTypeParmTypeLoc TL) {
+ TemplateTypeParmTypeLoc TL, bool) {
assert(TL.getDecl()->getDepth() <= TemplateDepth &&
"Nothing should reference a value below the actual template depth, "
"depth is likely wrong");
if (TL.getDecl()->getDepth() != TemplateDepth)
Result = true;
- return inherited::TransformTemplateTypeParmType(TLB, TL);
+ return inherited::TransformTemplateTypeParmType(
+ TLB, TL,
+ /*SuppressObjCLifetime=*/false);
}
Decl *TransformDecl(SourceLocation Loc, Decl *D) {
@@ -3849,13 +3852,10 @@
if (Pattern->isInvalidDecl())
return QualType();
- TemplateArgumentList StackTemplateArgs(TemplateArgumentList::OnStack,
- CanonicalConverted);
-
// Only substitute for the innermost template argument list.
MultiLevelTemplateArgumentList TemplateArgLists;
- TemplateArgLists.addOuterTemplateArguments(Template,
- StackTemplateArgs.asArray());
+ TemplateArgLists.addOuterTemplateArguments(Template, CanonicalConverted,
+ /*Final=*/false);
TemplateArgLists.addOuterRetainedLevels(
AliasTemplate->getTemplateParameters()->getDepth());
@@ -3981,9 +3981,9 @@
ClassTemplate->getTemplatedDecl()->hasAttrs()) {
InstantiatingTemplate Inst(*this, TemplateLoc, Decl);
if (!Inst.isInvalid()) {
- MultiLevelTemplateArgumentList TemplateArgLists;
- TemplateArgLists.addOuterTemplateArguments(Template,
- CanonicalConverted);
+ MultiLevelTemplateArgumentList TemplateArgLists(Template,
+ CanonicalConverted,
+ /*Final=*/false);
InstantiateAttrsForDecl(TemplateArgLists,
ClassTemplate->getTemplatedDecl(), Decl);
}
@@ -4866,7 +4866,8 @@
bool AreArgsDependent =
TemplateSpecializationType::anyDependentTemplateArguments(
*TemplateArgs, CanonicalConverted);
- MultiLevelTemplateArgumentList MLTAL(NamedConcept, CanonicalConverted);
+ MultiLevelTemplateArgumentList MLTAL(NamedConcept, CanonicalConverted,
+ /*Final=*/false);
LocalInstantiationScope Scope(*this);
EnterExpressionEvaluationContext EECtx{
@@ -5278,11 +5279,9 @@
if (Inst.isInvalid())
return nullptr;
- TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack, Converted);
-
// Only substitute for the innermost template argument list.
- MultiLevelTemplateArgumentList TemplateArgLists(Template,
- TemplateArgs.asArray());
+ MultiLevelTemplateArgumentList TemplateArgLists(Template, Converted,
+ /*Final=*/false);
for (unsigned i = 0, e = Param->getDepth(); i != e; ++i)
TemplateArgLists.addOuterTemplateArguments(None);
@@ -5334,11 +5333,9 @@
if (Inst.isInvalid())
return ExprError();
- TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack, Converted);
-
// Only substitute for the innermost template argument list.
- MultiLevelTemplateArgumentList TemplateArgLists(Template,
- TemplateArgs.asArray());
+ MultiLevelTemplateArgumentList TemplateArgLists(Template, Converted,
+ /*Final=*/false);
for (unsigned i = 0, e = Param->getDepth(); i != e; ++i)
TemplateArgLists.addOuterTemplateArguments(None);
@@ -5387,11 +5384,9 @@
if (Inst.isInvalid())
return TemplateName();
- TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack, Converted);
-
// Only substitute for the innermost template argument list.
- MultiLevelTemplateArgumentList TemplateArgLists(Template,
- TemplateArgs.asArray());
+ MultiLevelTemplateArgumentList TemplateArgLists(Template, Converted,
+ /*Final=*/false);
for (unsigned i = 0, e = Param->getDepth(); i != e; ++i)
TemplateArgLists.addOuterTemplateArguments(None);
@@ -5572,10 +5567,8 @@
if (Inst.isInvalid())
return true;
- TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack,
- CanonicalConverted);
-
- MultiLevelTemplateArgumentList MLTAL(Template, TemplateArgs.asArray());
+ MultiLevelTemplateArgumentList MLTAL(Template, CanonicalConverted,
+ /*Final=*/false);
// If the parameter is a pack expansion, expand this slice of the pack.
if (auto *PET = NTTPType->getAs<PackExpansionType>()) {
Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(*this,
@@ -5737,9 +5730,10 @@
if (Inst.isInvalid())
return true;
- Params = SubstTemplateParams(
- Params, CurContext,
- MultiLevelTemplateArgumentList(Template, CanonicalConverted));
+ Params =
+ SubstTemplateParams(Params, CurContext,
+ MultiLevelTemplateArgumentList(
+ Template, CanonicalConverted, /*Final=*/false));
if (!Params)
return true;
}
@@ -6138,7 +6132,8 @@
CXXThisScopeRAII(*this, RD, ThisQuals, RD != nullptr);
MultiLevelTemplateArgumentList MLTAL = getTemplateInstantiationArgs(
- Template, &StackTemplateArgs, /*RelativeToPrimary=*/true,
+ Template, /*Final=*/false, &StackTemplateArgs,
+ /*RelativeToPrimary=*/true,
/*Pattern=*/nullptr,
/*ForConceptInstantiation=*/true);
if (EnsureTemplateArgumentListConstraints(
Index: clang/lib/Sema/SemaExprCXX.cpp
===================================================================
--- clang/lib/Sema/SemaExprCXX.cpp
+++ clang/lib/Sema/SemaExprCXX.cpp
@@ -8964,7 +8964,8 @@
auto *Param = cast<TemplateTypeParmDecl>(TPL->getParam(0));
TemplateArgumentList TAL(TemplateArgumentList::OnStack, Args);
- MultiLevelTemplateArgumentList MLTAL(Param, TAL.asArray());
+ MultiLevelTemplateArgumentList MLTAL(Param, TAL.asArray(),
+ /*Final=*/false);
MLTAL.addOuterRetainedLevels(TPL->getDepth());
Expr *IDC = Param->getTypeConstraint()->getImmediatelyDeclaredConstraint();
ExprResult Constraint = SubstExpr(IDC, MLTAL);
Index: clang/lib/Sema/SemaConcept.cpp
===================================================================
--- clang/lib/Sema/SemaConcept.cpp
+++ clang/lib/Sema/SemaConcept.cpp
@@ -454,7 +454,8 @@
// the list of current template arguments to the list so that they also can
// be picked out of the map.
if (auto *SpecArgs = FD->getTemplateSpecializationArgs()) {
- MultiLevelTemplateArgumentList JustTemplArgs(FD, SpecArgs->asArray());
+ MultiLevelTemplateArgumentList JustTemplArgs(FD, SpecArgs->asArray(),
+ /*Final=*/false);
if (addInstantiatedParametersToScope(
FD, PrimaryTemplate->getTemplatedDecl(), Scope, JustTemplArgs))
return true;
@@ -507,10 +508,11 @@
// Collect the list of template arguments relative to the 'primary' template.
// We need the entire list, since the constraint is completely uninstantiated
// at this point.
- MLTAL = getTemplateInstantiationArgs(FD, /*Innermost=*/nullptr,
- /*RelativeToPrimary=*/true,
- /*Pattern=*/nullptr,
- /*ForConstraintInstantiation=*/true);
+ MLTAL =
+ getTemplateInstantiationArgs(FD, /*Final=*/false, /*Innermost=*/nullptr,
+ /*RelativeToPrimary=*/true,
+ /*Pattern=*/nullptr,
+ /*ForConstraintInstantiation=*/true);
if (SetupConstraintScope(FD, TemplateArgs, MLTAL, Scope))
return llvm::None;
@@ -587,7 +589,7 @@
static unsigned CalculateTemplateDepthForConstraints(Sema &S,
const NamedDecl *ND) {
MultiLevelTemplateArgumentList MLTAL = S.getTemplateInstantiationArgs(
- ND, /*Innermost=*/nullptr, /*RelativeToPrimary=*/true,
+ ND, /*Final=*/false, /*Innermost=*/nullptr, /*RelativeToPrimary=*/true,
/*Pattern=*/nullptr,
/*ForConstraintInstantiation=*/true);
return MLTAL.getNumSubstitutedLevels();
@@ -600,8 +602,10 @@
using inherited = TreeTransform<AdjustConstraintDepth>;
AdjustConstraintDepth(Sema &SemaRef, unsigned TemplateDepth)
: inherited(SemaRef), TemplateDepth(TemplateDepth) {}
+
+ using inherited::TransformTemplateTypeParmType;
QualType TransformTemplateTypeParmType(TypeLocBuilder &TLB,
- TemplateTypeParmTypeLoc TL) {
+ TemplateTypeParmTypeLoc TL, bool) {
const TemplateTypeParmType *T = TL.getTypePtr();
TemplateTypeParmDecl *NewTTPDecl = nullptr;
@@ -1072,11 +1076,11 @@
const ConceptSpecializationExpr *CSE) {
TemplateArgumentList TAL{TemplateArgumentList::OnStack,
CSE->getTemplateArguments()};
- MultiLevelTemplateArgumentList MLTAL =
- S.getTemplateInstantiationArgs(CSE->getNamedConcept(), &TAL,
- /*RelativeToPrimary=*/true,
- /*Pattern=*/nullptr,
- /*ForConstraintInstantiation=*/true);
+ MultiLevelTemplateArgumentList MLTAL = S.getTemplateInstantiationArgs(
+ CSE->getNamedConcept(), /*Final=*/false, &TAL,
+ /*RelativeToPrimary=*/true,
+ /*Pattern=*/nullptr,
+ /*ForConstraintInstantiation=*/true);
return substituteParameterMappings(S, N, CSE->getNamedConcept(), MLTAL,
CSE->getTemplateArgsAsWritten());
Index: clang/lib/AST/Type.cpp
===================================================================
--- clang/lib/AST/Type.cpp
+++ clang/lib/AST/Type.cpp
@@ -3666,17 +3666,26 @@
}
SubstTemplateTypeParmPackType::SubstTemplateTypeParmPackType(
- QualType Canon, Decl *AssociatedDecl, unsigned Index,
+ QualType Canon, Decl *AssociatedDecl, unsigned Index, bool Final,
const TemplateArgument &ArgPack)
: Type(SubstTemplateTypeParmPack, Canon,
TypeDependence::DependentInstantiation |
TypeDependence::UnexpandedPack),
- Arguments(ArgPack.pack_begin()), AssociatedDecl(AssociatedDecl) {
+ Arguments(ArgPack.pack_begin()),
+ AssociatedDeclAndFinal(AssociatedDecl, Final) {
SubstTemplateTypeParmPackTypeBits.Index = Index;
SubstTemplateTypeParmPackTypeBits.NumArgs = ArgPack.pack_size();
assert(AssociatedDecl != nullptr);
}
+Decl *SubstTemplateTypeParmPackType::getAssociatedDecl() const {
+ return AssociatedDeclAndFinal.getPointer();
+}
+
+bool SubstTemplateTypeParmPackType::getFinal() const {
+ return AssociatedDeclAndFinal.getInt();
+}
+
const TemplateTypeParmDecl *
SubstTemplateTypeParmPackType::getReplacedParameter() const {
return ::getReplacedParameter(getAssociatedDecl(), getIndex());
@@ -3691,15 +3700,16 @@
}
void SubstTemplateTypeParmPackType::Profile(llvm::FoldingSetNodeID &ID) {
- Profile(ID, getAssociatedDecl(), getIndex(), getArgumentPack());
+ Profile(ID, getAssociatedDecl(), getIndex(), getFinal(), getArgumentPack());
}
void SubstTemplateTypeParmPackType::Profile(llvm::FoldingSetNodeID &ID,
const Decl *AssociatedDecl,
- unsigned Index,
+ unsigned Index, bool Final,
const TemplateArgument &ArgPack) {
ID.AddPointer(AssociatedDecl);
ID.AddInteger(Index);
+ ID.AddBoolean(Final);
ID.AddInteger(ArgPack.pack_size());
for (const auto &P : ArgPack.pack_elements())
ID.AddPointer(P.getAsType().getAsOpaquePtr());
Index: clang/lib/AST/TemplateName.cpp
===================================================================
--- clang/lib/AST/TemplateName.cpp
+++ clang/lib/AST/TemplateName.cpp
@@ -67,17 +67,37 @@
ID.AddInteger(PackIndex ? *PackIndex + 1 : 0);
}
+SubstTemplateTemplateParmPackStorage::SubstTemplateTemplateParmPackStorage(
+ ArrayRef<TemplateArgument> ArgPack, Decl *AssociatedDecl, unsigned Index,
+ bool Final)
+ : UncommonTemplateNameStorage(SubstTemplateTemplateParmPack, Index,
+ ArgPack.size()),
+ Arguments(ArgPack.data()), AssociatedDeclAndFinal(AssociatedDecl, Final) {
+ assert(AssociatedDecl != nullptr);
+}
+
void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID &ID,
ASTContext &Context) {
- Profile(ID, Context, getArgumentPack(), getAssociatedDecl(), getIndex());
+ Profile(ID, Context, getArgumentPack(), getAssociatedDecl(), getIndex(),
+ getFinal());
+}
+
+Decl *SubstTemplateTemplateParmPackStorage::getAssociatedDecl() const {
+ return AssociatedDeclAndFinal.getPointer();
+}
+
+bool SubstTemplateTemplateParmPackStorage::getFinal() const {
+ return AssociatedDeclAndFinal.getInt();
}
void SubstTemplateTemplateParmPackStorage::Profile(
llvm::FoldingSetNodeID &ID, ASTContext &Context,
- const TemplateArgument &ArgPack, Decl *AssociatedDecl, unsigned Index) {
+ const TemplateArgument &ArgPack, Decl *AssociatedDecl, unsigned Index,
+ bool Final) {
ArgPack.Profile(ID, Context);
ID.AddPointer(AssociatedDecl);
ID.AddInteger(Index);
+ ID.AddBoolean(Final);
}
TemplateName::TemplateName(void *Ptr) {
Index: clang/lib/AST/ASTImporter.cpp
===================================================================
--- clang/lib/AST/ASTImporter.cpp
+++ clang/lib/AST/ASTImporter.cpp
@@ -1542,7 +1542,7 @@
return ToArgumentPack.takeError();
return Importer.getToContext().getSubstTemplateTypeParmPackType(
- *ReplacedOrErr, T->getIndex(), *ToArgumentPack);
+ *ReplacedOrErr, T->getIndex(), T->getFinal(), *ToArgumentPack);
}
ExpectedType ASTNodeImporter::VisitTemplateSpecializationType(
@@ -9439,7 +9439,8 @@
return AssociatedDeclOrErr.takeError();
return ToContext.getSubstTemplateTemplateParmPack(
- *ArgPackOrErr, *AssociatedDeclOrErr, SubstPack->getIndex());
+ *ArgPackOrErr, *AssociatedDeclOrErr, SubstPack->getIndex(),
+ SubstPack->getFinal());
}
case TemplateName::UsingTemplate: {
auto UsingOrError = Import(From.getAsUsingShadowDecl());
Index: clang/lib/AST/ASTContext.cpp
===================================================================
--- clang/lib/AST/ASTContext.cpp
+++ clang/lib/AST/ASTContext.cpp
@@ -3045,6 +3045,18 @@
return getObjCLayout(D->getClassInterface(), D);
}
+static auto getCanonicalTemplateArguments(const ASTContext &C,
+ ArrayRef<TemplateArgument> Args,
+ bool &AnyNonCanonArgs) {
+ SmallVector<TemplateArgument, 16> CanonArgs(Args);
+ for (auto &Arg : CanonArgs) {
+ TemplateArgument OrigArg = Arg;
+ Arg = C.getCanonicalTemplateArgument(Arg);
+ AnyNonCanonArgs |= !Arg.structurallyEquals(OrigArg);
+ }
+ return CanonArgs;
+}
+
//===----------------------------------------------------------------------===//
// Type creation/memoization methods
//===----------------------------------------------------------------------===//
@@ -4852,31 +4864,38 @@
}
/// Retrieve a
-QualType ASTContext::getSubstTemplateTypeParmPackType(
- Decl *AssociatedDecl, unsigned Index, const TemplateArgument &ArgPack) {
+QualType
+ASTContext::getSubstTemplateTypeParmPackType(Decl *AssociatedDecl,
+ unsigned Index, bool Final,
+ const TemplateArgument &ArgPack) {
#ifndef NDEBUG
- for (const auto &P : ArgPack.pack_elements()) {
+ for (const auto &P : ArgPack.pack_elements())
assert(P.getKind() == TemplateArgument::Type && "Pack contains a non-type");
- assert(P.getAsType().isCanonical() && "Pack contains non-canonical type");
- }
#endif
llvm::FoldingSetNodeID ID;
- SubstTemplateTypeParmPackType::Profile(ID, AssociatedDecl, Index, ArgPack);
+ SubstTemplateTypeParmPackType::Profile(ID, AssociatedDecl, Index, Final,
+ ArgPack);
void *InsertPos = nullptr;
if (SubstTemplateTypeParmPackType *SubstParm =
SubstTemplateTypeParmPackTypes.FindNodeOrInsertPos(ID, InsertPos))
return QualType(SubstParm, 0);
QualType Canon;
- if (!AssociatedDecl->isCanonicalDecl()) {
- Canon = getSubstTemplateTypeParmPackType(AssociatedDecl->getCanonicalDecl(),
- Index, ArgPack);
- SubstTemplateTypeParmPackTypes.FindNodeOrInsertPos(ID, InsertPos);
+ {
+ TemplateArgument CanonArgPack = getCanonicalTemplateArgument(ArgPack);
+ if (!AssociatedDecl->isCanonicalDecl() ||
+ !CanonArgPack.structurallyEquals(ArgPack)) {
+ Canon = getSubstTemplateTypeParmPackType(
+ AssociatedDecl->getCanonicalDecl(), Index, Final, CanonArgPack);
+ [[maybe_unused]] const auto *Nothing =
+ SubstTemplateTypeParmPackTypes.FindNodeOrInsertPos(ID, InsertPos);
+ assert(!Nothing);
+ }
}
- auto *SubstParm = new (*this, TypeAlignment)
- SubstTemplateTypeParmPackType(Canon, AssociatedDecl, Index, ArgPack);
+ auto *SubstParm = new (*this, TypeAlignment) SubstTemplateTypeParmPackType(
+ Canon, AssociatedDecl, Index, Final, ArgPack);
Types.push_back(SubstParm);
SubstTemplateTypeParmPackTypes.InsertNode(SubstParm, InsertPos);
return QualType(SubstParm, 0);
@@ -5001,23 +5020,6 @@
return QualType(Spec, 0);
}
-static bool
-getCanonicalTemplateArguments(const ASTContext &C,
- ArrayRef<TemplateArgument> OrigArgs,
- SmallVectorImpl<TemplateArgument> &CanonArgs) {
- bool AnyNonCanonArgs = false;
- unsigned NumArgs = OrigArgs.size();
- CanonArgs.resize(NumArgs);
- for (unsigned I = 0; I != NumArgs; ++I) {
- const TemplateArgument &OrigArg = OrigArgs[I];
- TemplateArgument &CanonArg = CanonArgs[I];
- CanonArg = C.getCanonicalTemplateArgument(OrigArg);
- if (!CanonArg.structurallyEquals(OrigArg))
- AnyNonCanonArgs = true;
- }
- return AnyNonCanonArgs;
-}
-
QualType ASTContext::getCanonicalTemplateSpecializationType(
TemplateName Template, ArrayRef<TemplateArgument> Args) const {
assert(!Template.getAsDependentTemplateName() &&
@@ -5029,8 +5031,9 @@
// Build the canonical template specialization type.
TemplateName CanonTemplate = getCanonicalTemplateName(Template);
- SmallVector<TemplateArgument, 4> CanonArgs;
- ::getCanonicalTemplateArguments(*this, Args, CanonArgs);
+ bool AnyNonCanonArgs = false;
+ auto CanonArgs =
+ ::getCanonicalTemplateArguments(*this, Args, AnyNonCanonArgs);
// Determine whether this canonical template specialization type already
// exists.
@@ -5184,9 +5187,9 @@
ElaboratedTypeKeyword CanonKeyword = Keyword;
if (Keyword == ETK_None) CanonKeyword = ETK_Typename;
- SmallVector<TemplateArgument, 16> CanonArgs;
- bool AnyNonCanonArgs =
- ::getCanonicalTemplateArguments(*this, Args, CanonArgs);
+ bool AnyNonCanonArgs = false;
+ auto CanonArgs =
+ ::getCanonicalTemplateArguments(*this, Args, AnyNonCanonArgs);
QualType Canon;
if (AnyNonCanonArgs || CanonNNS != NNS || CanonKeyword != Keyword) {
@@ -6285,7 +6288,7 @@
getCanonicalTemplateArgument(subst->getArgumentPack());
return getSubstTemplateTemplateParmPack(
canonArgPack, subst->getAssociatedDecl()->getCanonicalDecl(),
- subst->getIndex());
+ subst->getFinal(), subst->getIndex());
}
}
@@ -6793,17 +6796,13 @@
return TemplateArgument(getCanonicalType(Arg.getAsType()));
case TemplateArgument::Pack: {
- if (Arg.pack_size() == 0)
+ bool AnyNonCanonArgs = false;
+ auto CanonArgs = ::getCanonicalTemplateArguments(
+ *this, Arg.pack_elements(), AnyNonCanonArgs);
+ if (!AnyNonCanonArgs)
return Arg;
-
- auto *CanonArgs = new (*this) TemplateArgument[Arg.pack_size()];
- unsigned Idx = 0;
- for (TemplateArgument::pack_iterator A = Arg.pack_begin(),
- AEnd = Arg.pack_end();
- A != AEnd; (void)++A, ++Idx)
- CanonArgs[Idx] = getCanonicalTemplateArgument(*A);
-
- return TemplateArgument(llvm::makeArrayRef(CanonArgs, Arg.pack_size()));
+ return TemplateArgument::CreatePackCopy(const_cast<ASTContext &>(*this),
+ CanonArgs);
}
}
@@ -9311,11 +9310,11 @@
TemplateName
ASTContext::getSubstTemplateTemplateParmPack(const TemplateArgument &ArgPack,
Decl *AssociatedDecl,
- unsigned Index) const {
+ unsigned Index, bool Final) const {
auto &Self = const_cast<ASTContext &>(*this);
llvm::FoldingSetNodeID ID;
SubstTemplateTemplateParmPackStorage::Profile(ID, Self, ArgPack,
- AssociatedDecl, Index);
+ AssociatedDecl, Index, Final);
void *InsertPos = nullptr;
SubstTemplateTemplateParmPackStorage *Subst
@@ -9323,7 +9322,7 @@
if (!Subst) {
Subst = new (*this) SubstTemplateTemplateParmPackStorage(
- ArgPack.pack_elements(), AssociatedDecl, Index);
+ ArgPack.pack_elements(), AssociatedDecl, Index, Final);
SubstTemplateTemplateParmPacks.InsertNode(Subst, InsertPos);
}
Index: clang/include/clang/Sema/Template.h
===================================================================
--- clang/include/clang/Sema/Template.h
+++ clang/include/clang/Sema/Template.h
@@ -77,7 +77,7 @@
using ArgList = ArrayRef<TemplateArgument>;
struct ArgumentListLevel {
- Decl *AssociatedDecl;
+ llvm::PointerIntPair<Decl *, 1, bool> AssociatedDeclAndFinal;
ArgList Args;
};
using ContainerType = SmallVector<ArgumentListLevel, 4>;
@@ -101,8 +101,8 @@
MultiLevelTemplateArgumentList() = default;
/// Construct a single-level template argument list.
- MultiLevelTemplateArgumentList(Decl *D, ArgList Args) {
- addOuterTemplateArguments(D, Args);
+ MultiLevelTemplateArgumentList(Decl *D, ArgList Args, bool Final) {
+ addOuterTemplateArguments(D, Args, Final);
}
void setKind(TemplateSubstitutionKind K) { Kind = K; }
@@ -160,9 +160,11 @@
/// A template-like entity which owns the whole pattern being substituted.
/// This will usually own a set of template parameters, or in some
/// cases might even be a template parameter itself.
- Decl *getAssociatedDecl(unsigned Depth) const {
+ std::pair<Decl *, bool> getAssociatedDecl(unsigned Depth) const {
assert(NumRetainedOuterLevels <= Depth && Depth < getNumLevels());
- return TemplateArgumentLists[getNumLevels() - Depth - 1].AssociatedDecl;
+ auto AD = TemplateArgumentLists[getNumLevels() - Depth - 1]
+ .AssociatedDeclAndFinal;
+ return {AD.getPointer(), AD.getInt()};
}
/// Determine whether there is a non-NULL template argument at the
@@ -202,21 +204,22 @@
/// Add a new outmost level to the multi-level template argument
/// list.
- void addOuterTemplateArguments(Decl *AssociatedDecl, ArgList Args) {
+ /// A 'Final' substitution means that Subst* nodes won't be built
+ /// for the replacements.
+ void addOuterTemplateArguments(Decl *AssociatedDecl, ArgList Args,
+ bool Final) {
assert(!NumRetainedOuterLevels &&
"substituted args outside retained args?");
assert(getKind() == TemplateSubstitutionKind::Specialization);
- assert(AssociatedDecl != nullptr || Args.size() == 0);
TemplateArgumentLists.push_back(
- {AssociatedDecl ? AssociatedDecl->getCanonicalDecl() : nullptr,
- Args});
+ {{AssociatedDecl->getCanonicalDecl(), Final}, Args});
}
void addOuterTemplateArguments(ArgList Args) {
assert(!NumRetainedOuterLevels &&
"substituted args outside retained args?");
assert(getKind() == TemplateSubstitutionKind::Rewrite);
- TemplateArgumentLists.push_back({nullptr, Args});
+ TemplateArgumentLists.push_back({{}, Args});
}
void addOuterTemplateArguments(llvm::NoneType) {
Index: clang/include/clang/Sema/Sema.h
===================================================================
--- clang/include/clang/Sema/Sema.h
+++ clang/include/clang/Sema/Sema.h
@@ -9074,10 +9074,12 @@
// C++ Template Instantiation
//
- MultiLevelTemplateArgumentList getTemplateInstantiationArgs(
- const NamedDecl *D, const TemplateArgumentList *Innermost = nullptr,
- bool RelativeToPrimary = false, const FunctionDecl *Pattern = nullptr,
- bool ForConstraintInstantiation = false);
+ MultiLevelTemplateArgumentList
+ getTemplateInstantiationArgs(const NamedDecl *D, bool Final = false,
+ const TemplateArgumentList *Innermost = nullptr,
+ bool RelativeToPrimary = false,
+ const FunctionDecl *Pattern = nullptr,
+ bool ForConstraintInstantiation = false);
/// A context in which code is being synthesized (where a source location
/// alone is not sufficient to identify the context). This covers template
@@ -10171,16 +10173,12 @@
bool FailOnError = false);
/// Build an Objective-C object pointer type.
- QualType BuildObjCObjectType(QualType BaseType,
- SourceLocation Loc,
- SourceLocation TypeArgsLAngleLoc,
- ArrayRef<TypeSourceInfo *> TypeArgs,
- SourceLocation TypeArgsRAngleLoc,
- SourceLocation ProtocolLAngleLoc,
- ArrayRef<ObjCProtocolDecl *> Protocols,
- ArrayRef<SourceLocation> ProtocolLocs,
- SourceLocation ProtocolRAngleLoc,
- bool FailOnError = false);
+ QualType BuildObjCObjectType(
+ QualType BaseType, SourceLocation Loc, SourceLocation TypeArgsLAngleLoc,
+ ArrayRef<TypeSourceInfo *> TypeArgs, SourceLocation TypeArgsRAngleLoc,
+ SourceLocation ProtocolLAngleLoc, ArrayRef<ObjCProtocolDecl *> Protocols,
+ ArrayRef<SourceLocation> ProtocolLocs, SourceLocation ProtocolRAngleLoc,
+ bool FailOnError, bool Rebuilding);
/// Ensure attributes are consistent with type.
/// \param [in, out] Attributes The attributes to check; they will
Index: clang/include/clang/AST/TypeProperties.td
===================================================================
--- clang/include/clang/AST/TypeProperties.td
+++ clang/include/clang/AST/TypeProperties.td
@@ -773,13 +773,16 @@
def : Property<"Index", UInt32> {
let Read = [{ node->getIndex() }];
}
+ def : Property<"Final", Bool> {
+ let Read = [{ node->getFinal() }];
+ }
def : Property<"replacementPack", TemplateArgument> {
let Read = [{ node->getArgumentPack() }];
}
def : Creator<[{
return ctx.getSubstTemplateTypeParmPackType(
- associatedDecl, Index, replacementPack);
+ associatedDecl, Index, Final, replacementPack);
}]>;
}
Index: clang/include/clang/AST/Type.h
===================================================================
--- clang/include/clang/AST/Type.h
+++ clang/include/clang/AST/Type.h
@@ -5158,10 +5158,10 @@
/// parameter pack is instantiated with.
const TemplateArgument *Arguments;
- Decl *AssociatedDecl;
+ llvm::PointerIntPair<Decl *, 1, bool> AssociatedDeclAndFinal;
SubstTemplateTypeParmPackType(QualType Canon, Decl *AssociatedDecl,
- unsigned Index,
+ unsigned Index, bool Final,
const TemplateArgument &ArgPack);
public:
@@ -5170,7 +5170,7 @@
/// A template-like entity which owns the whole pattern being substituted.
/// This will usually own a set of template parameters, or in some
/// cases might even be a template parameter itself.
- Decl *getAssociatedDecl() const { return AssociatedDecl; }
+ Decl *getAssociatedDecl() const;
/// Gets the template parameter declaration that was substituted for.
const TemplateTypeParmDecl *getReplacedParameter() const;
@@ -5179,6 +5179,9 @@
/// This should match the result of `getReplacedParameter()->getIndex()`.
unsigned getIndex() const { return SubstTemplateTypeParmPackTypeBits.Index; }
+ // When true the substitution will be 'Final' (subst node won't be placed).
+ bool getFinal() const;
+
unsigned getNumArgs() const {
return SubstTemplateTypeParmPackTypeBits.NumArgs;
}
@@ -5190,7 +5193,8 @@
void Profile(llvm::FoldingSetNodeID &ID);
static void Profile(llvm::FoldingSetNodeID &ID, const Decl *AssociatedDecl,
- unsigned Index, const TemplateArgument &ArgPack);
+ unsigned Index, bool Final,
+ const TemplateArgument &ArgPack);
static bool classof(const Type *T) {
return T->getTypeClass() == SubstTemplateTypeParmPack;
Index: clang/include/clang/AST/TemplateName.h
===================================================================
--- clang/include/clang/AST/TemplateName.h
+++ clang/include/clang/AST/TemplateName.h
@@ -139,25 +139,24 @@
class SubstTemplateTemplateParmPackStorage : public UncommonTemplateNameStorage,
public llvm::FoldingSetNode {
const TemplateArgument *Arguments;
- Decl *AssociatedDecl;
+ llvm::PointerIntPair<Decl *, 1, bool> AssociatedDeclAndFinal;
public:
SubstTemplateTemplateParmPackStorage(ArrayRef<TemplateArgument> ArgPack,
- Decl *AssociatedDecl, unsigned Index)
- : UncommonTemplateNameStorage(SubstTemplateTemplateParmPack, Index,
- ArgPack.size()),
- Arguments(ArgPack.data()), AssociatedDecl(AssociatedDecl) {
- assert(AssociatedDecl != nullptr);
- }
+ Decl *AssociatedDecl, unsigned Index,
+ bool Final);
/// A template-like entity which owns the whole pattern being substituted.
/// This will own a set of template parameters.
- Decl *getAssociatedDecl() const { return AssociatedDecl; }
+ Decl *getAssociatedDecl() const;
/// Returns the index of the replaced parameter in the associated declaration.
/// This should match the result of `getParameterPack()->getIndex()`.
unsigned getIndex() const { return Bits.Index; }
+ // When true the substitution will be 'Final' (subst node won't be placed).
+ bool getFinal() const;
+
/// Retrieve the template template parameter pack being substituted.
TemplateTemplateParmDecl *getParameterPack() const;
@@ -169,7 +168,7 @@
static void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context,
const TemplateArgument &ArgPack, Decl *AssociatedDecl,
- unsigned Index);
+ unsigned Index, bool Final);
};
/// Represents a C++ template name within the type system.
Index: clang/include/clang/AST/PropertiesBase.td
===================================================================
--- clang/include/clang/AST/PropertiesBase.td
+++ clang/include/clang/AST/PropertiesBase.td
@@ -730,8 +730,11 @@
def : Property<"index", UInt32> {
let Read = [{ parm->getIndex() }];
}
+ def : Property<"final", Bool> {
+ let Read = [{ parm->getFinal() }];
+ }
def : Creator<[{
- return ctx.getSubstTemplateTemplateParmPack(argumentPack, associatedDecl, index);
+ return ctx.getSubstTemplateTemplateParmPack(argumentPack, associatedDecl, index, final);
}]>;
}
Index: clang/include/clang/AST/ASTContext.h
===================================================================
--- clang/include/clang/AST/ASTContext.h
+++ clang/include/clang/AST/ASTContext.h
@@ -1621,7 +1621,7 @@
Decl *AssociatedDecl, unsigned Index,
Optional<unsigned> PackIndex) const;
QualType getSubstTemplateTypeParmPackType(Decl *AssociatedDecl,
- unsigned Index,
+ unsigned Index, bool Final,
const TemplateArgument &ArgPack);
QualType
@@ -2207,7 +2207,8 @@
Optional<unsigned> PackIndex) const;
TemplateName getSubstTemplateTemplateParmPack(const TemplateArgument &ArgPack,
Decl *AssociatedDecl,
- unsigned Index) const;
+ unsigned Index,
+ bool Final) const;
enum GetBuiltinTypeError {
/// No error
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits