diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index efd925e990f43..53040aa0f9074 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -51,6 +51,10 @@ AST Dumping Potentially Breaking Changes Clang Frontend Potentially Breaking Changes ------------------------------------------- +- Removed support for constructing on-stack ``TemplateArgumentList``s; interfaces should instead + use ``ArrayRef`` to pass template arguments. Transitioning internal uses to + ``ArrayRef`` reduces AST memory usage by 0.4% when compiling clang, and is + expected to show similar improvements on other workloads. Target OS macros extension ^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/include/clang/AST/DeclTemplate.h b/clang/include/clang/AST/DeclTemplate.h index 832ad2de6b08a..baf71145d99dc 100644 --- a/clang/include/clang/AST/DeclTemplate.h +++ b/clang/include/clang/AST/DeclTemplate.h @@ -241,9 +241,6 @@ class FixedSizeTemplateParameterListStorage /// A template argument list. class TemplateArgumentList final : private llvm::TrailingObjects { - /// The template argument list. - const TemplateArgument *Arguments; - /// The number of template arguments in this template /// argument list. unsigned NumArguments; @@ -258,30 +255,11 @@ class TemplateArgumentList final TemplateArgumentList(const TemplateArgumentList &) = delete; TemplateArgumentList &operator=(const TemplateArgumentList &) = delete; - /// Type used to indicate that the template argument list itself is a - /// stack object. It does not own its template arguments. - enum OnStackType { OnStack }; - /// Create a new template argument list that copies the given set of /// template arguments. static TemplateArgumentList *CreateCopy(ASTContext &Context, ArrayRef Args); - /// Construct a new, temporary template argument list on the stack. - /// - /// The template argument list does not own the template arguments - /// provided. - explicit TemplateArgumentList(OnStackType, ArrayRef Args) - : Arguments(Args.data()), NumArguments(Args.size()) {} - - /// Produces a shallow copy of the given template argument list. - /// - /// This operation assumes that the input argument list outlives it. - /// This takes the list as a pointer to avoid looking like a copy - /// constructor, since this really isn't safe to use that way. - explicit TemplateArgumentList(const TemplateArgumentList *Other) - : Arguments(Other->data()), NumArguments(Other->size()) {} - /// Retrieve the template argument at a given index. const TemplateArgument &get(unsigned Idx) const { assert(Idx < NumArguments && "Invalid template argument index"); @@ -301,7 +279,9 @@ class TemplateArgumentList final unsigned size() const { return NumArguments; } /// Retrieve a pointer to the template argument list. - const TemplateArgument *data() const { return Arguments; } + const TemplateArgument *data() const { + return getTrailingObjects(); + } }; void *allocateDefaultArgStorageChain(const ASTContext &C); diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index b780cee86c3c3..780a2f2d8ce27 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -9329,12 +9329,12 @@ class Sema final { TemplateDeductionResult DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial, - const TemplateArgumentList &TemplateArgs, + ArrayRef TemplateArgs, sema::TemplateDeductionInfo &Info); TemplateDeductionResult DeduceTemplateArguments(VarTemplatePartialSpecializationDecl *Partial, - const TemplateArgumentList &TemplateArgs, + ArrayRef TemplateArgs, sema::TemplateDeductionInfo &Info); TemplateDeductionResult SubstituteExplicitTemplateArguments( @@ -9507,7 +9507,7 @@ class Sema final { MultiLevelTemplateArgumentList getTemplateInstantiationArgs( const NamedDecl *D, const DeclContext *DC = nullptr, bool Final = false, - const TemplateArgumentList *Innermost = nullptr, + std::optional> Innermost = std::nullopt, bool RelativeToPrimary = false, const FunctionDecl *Pattern = nullptr, bool ForConstraintInstantiation = false, bool SkipForSpecialization = false); @@ -10537,7 +10537,7 @@ class Sema final { bool AtEndOfTU = false); VarTemplateSpecializationDecl *BuildVarTemplateInstantiation( VarTemplateDecl *VarTemplate, VarDecl *FromVar, - const TemplateArgumentList &TemplateArgList, + const TemplateArgumentList *PartialSpecArgs, const TemplateArgumentListInfo &TemplateArgsInfo, SmallVectorImpl &Converted, SourceLocation PointOfInstantiation, diff --git a/clang/lib/AST/DeclTemplate.cpp b/clang/lib/AST/DeclTemplate.cpp index 946a34ea8830e..3c217d6a6a5ae 100644 --- a/clang/lib/AST/DeclTemplate.cpp +++ b/clang/lib/AST/DeclTemplate.cpp @@ -871,8 +871,7 @@ void TemplateTemplateParmDecl::setDefaultArgument( // TemplateArgumentList Implementation //===----------------------------------------------------------------------===// TemplateArgumentList::TemplateArgumentList(ArrayRef Args) - : Arguments(getTrailingObjects()), - NumArguments(Args.size()) { + : NumArguments(Args.size()) { std::uninitialized_copy(Args.begin(), Args.end(), getTrailingObjects()); } diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp index 5028879eda22f..2878e4d31ee8f 100644 --- a/clang/lib/Sema/SemaConcept.cpp +++ b/clang/lib/Sema/SemaConcept.cpp @@ -661,11 +661,12 @@ Sema::SetupConstraintCheckingTemplateArgumentsAndScope( // 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, FD->getLexicalDeclContext(), - /*Final=*/false, /*Innermost=*/nullptr, - /*RelativeToPrimary=*/true, - /*Pattern=*/nullptr, - /*ForConstraintInstantiation=*/true); + MLTAL = + getTemplateInstantiationArgs(FD, FD->getLexicalDeclContext(), + /*Final=*/false, /*Innermost=*/std::nullopt, + /*RelativeToPrimary=*/true, + /*Pattern=*/nullptr, + /*ForConstraintInstantiation=*/true); if (SetupConstraintScope(FD, TemplateArgs, MLTAL, Scope)) return std::nullopt; @@ -740,7 +741,8 @@ static unsigned CalculateTemplateDepthForConstraints(Sema &S, const NamedDecl *ND, bool SkipForSpecialization = false) { MultiLevelTemplateArgumentList MLTAL = S.getTemplateInstantiationArgs( - ND, ND->getLexicalDeclContext(), /*Final=*/false, /*Innermost=*/nullptr, + ND, ND->getLexicalDeclContext(), /*Final=*/false, + /*Innermost=*/std::nullopt, /*RelativeToPrimary=*/true, /*Pattern=*/nullptr, /*ForConstraintInstantiation=*/true, SkipForSpecialization); @@ -780,7 +782,7 @@ static const Expr *SubstituteConstraintExpressionWithoutSatisfaction( const Expr *ConstrExpr) { MultiLevelTemplateArgumentList MLTAL = S.getTemplateInstantiationArgs( DeclInfo.getDecl(), DeclInfo.getLexicalDeclContext(), /*Final=*/false, - /*Innermost=*/nullptr, + /*Innermost=*/std::nullopt, /*RelativeToPrimary=*/true, /*Pattern=*/nullptr, /*ForConstraintInstantiation=*/true, /*SkipForSpecialization*/ false); @@ -1279,11 +1281,9 @@ substituteParameterMappings(Sema &S, NormalizedConstraint &N, static bool substituteParameterMappings(Sema &S, NormalizedConstraint &N, const ConceptSpecializationExpr *CSE) { - TemplateArgumentList TAL{TemplateArgumentList::OnStack, - CSE->getTemplateArguments()}; MultiLevelTemplateArgumentList MLTAL = S.getTemplateInstantiationArgs( CSE->getNamedConcept(), CSE->getNamedConcept()->getLexicalDeclContext(), - /*Final=*/false, &TAL, + /*Final=*/false, CSE->getTemplateArguments(), /*RelativeToPrimary=*/true, /*Pattern=*/nullptr, /*ForConstraintInstantiation=*/true); diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 2b695fd43eac0..3a32754e5376e 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -9113,9 +9113,7 @@ Sema::BuildExprRequirement( auto *Param = cast(TPL->getParam(0)); - TemplateArgumentList TAL(TemplateArgumentList::OnStack, Args); - MultiLevelTemplateArgumentList MLTAL(Param, TAL.asArray(), - /*Final=*/false); + MultiLevelTemplateArgumentList MLTAL(Param, Args, /*Final=*/false); MLTAL.addOuterRetainedLevels(TPL->getDepth()); const TypeConstraint *TC = Param->getTypeConstraint(); assert(TC && "Type Constraint cannot be null here"); diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 9e8d058041f04..5616682e909aa 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -4843,9 +4843,7 @@ Sema::CheckVarTemplateId(VarTemplateDecl *Template, SourceLocation TemplateLoc, // the set of specializations, based on the closest partial specialization // that it represents. That is, VarDecl *InstantiationPattern = Template->getTemplatedDecl(); - TemplateArgumentList TemplateArgList(TemplateArgumentList::OnStack, - CanonicalConverted); - TemplateArgumentList *InstantiationArgs = &TemplateArgList; + const TemplateArgumentList *PartialSpecArgs = nullptr; bool AmbiguousPartialSpec = false; typedef PartialSpecMatchResult MatchResult; SmallVector Matched; @@ -4866,7 +4864,7 @@ Sema::CheckVarTemplateId(VarTemplateDecl *Template, SourceLocation TemplateLoc, TemplateDeductionInfo Info(FailedCandidates.getLocation()); if (TemplateDeductionResult Result = - DeduceTemplateArguments(Partial, TemplateArgList, Info)) { + DeduceTemplateArguments(Partial, CanonicalConverted, Info)) { // Store the failed-deduction information for use in diagnostics, later. // TODO: Actually use the failed-deduction info? FailedCandidates.addCandidate().set( @@ -4919,7 +4917,7 @@ Sema::CheckVarTemplateId(VarTemplateDecl *Template, SourceLocation TemplateLoc, // Instantiate using the best variable template partial specialization. InstantiationPattern = Best->Partial; - InstantiationArgs = Best->Args; + PartialSpecArgs = Best->Args; } else { // -- If no match is found, the instantiation is generated // from the primary template. @@ -4931,7 +4929,7 @@ Sema::CheckVarTemplateId(VarTemplateDecl *Template, SourceLocation TemplateLoc, // in DoMarkVarDeclReferenced(). // FIXME: LateAttrs et al.? VarTemplateSpecializationDecl *Decl = BuildVarTemplateInstantiation( - Template, InstantiationPattern, *InstantiationArgs, TemplateArgs, + Template, InstantiationPattern, PartialSpecArgs, TemplateArgs, CanonicalConverted, TemplateNameLoc /*, LateAttrs, StartingScope*/); if (!Decl) return true; @@ -4952,7 +4950,7 @@ Sema::CheckVarTemplateId(VarTemplateDecl *Template, SourceLocation TemplateLoc, if (VarTemplatePartialSpecializationDecl *D = dyn_cast(InstantiationPattern)) - Decl->setInstantiationOf(D, InstantiationArgs); + Decl->setInstantiationOf(D, PartialSpecArgs); checkSpecializationReachability(TemplateNameLoc, Decl); @@ -6257,8 +6255,6 @@ bool Sema::CheckTemplateArgumentList( TemplateArgs = std::move(NewArgs); if (!PartialTemplateArgs) { - TemplateArgumentList StackTemplateArgs(TemplateArgumentList::OnStack, - CanonicalConverted); // Setup the context/ThisScope for the case where we are needing to // re-instantiate constraints outside of normal instantiation. DeclContext *NewContext = Template->getDeclContext(); @@ -6278,7 +6274,7 @@ bool Sema::CheckTemplateArgumentList( CXXThisScopeRAII(*this, RD, ThisQuals, RD != nullptr); MultiLevelTemplateArgumentList MLTAL = getTemplateInstantiationArgs( - Template, NewContext, /*Final=*/false, &StackTemplateArgs, + Template, NewContext, /*Final=*/false, CanonicalConverted, /*RelativeToPrimary=*/true, /*Pattern=*/nullptr, /*ForConceptInstantiation=*/true); @@ -9782,8 +9778,8 @@ bool Sema::CheckFunctionTemplateSpecialization( // specialization, with the template arguments from the previous // specialization. // Take copies of (semantic and syntactic) template argument lists. - const TemplateArgumentList* TemplArgs = new (Context) - TemplateArgumentList(Specialization->getTemplateSpecializationArgs()); + const TemplateArgumentList *TemplArgs = TemplateArgumentList::CreateCopy( + Context, Specialization->getTemplateSpecializationArgs()->asArray()); FD->setFunctionTemplateSpecialization( Specialization->getPrimaryTemplate(), TemplArgs, /*InsertPos=*/nullptr, SpecInfo->getTemplateSpecializationKind(), diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index f08577febcd3e..a54ad27975890 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -2514,17 +2514,6 @@ DeduceTemplateArguments(Sema &S, TemplateParameterList *TemplateParams, return Sema::TDK_Success; } -static Sema::TemplateDeductionResult -DeduceTemplateArguments(Sema &S, TemplateParameterList *TemplateParams, - const TemplateArgumentList &ParamList, - const TemplateArgumentList &ArgList, - TemplateDeductionInfo &Info, - SmallVectorImpl &Deduced) { - return DeduceTemplateArguments(S, TemplateParams, ParamList.asArray(), - ArgList.asArray(), Info, Deduced, - /*NumberOfArgumentsMustMatch=*/false); -} - /// Determine whether two template arguments are the same. static bool isSameTemplateArg(ASTContext &Context, TemplateArgument X, @@ -2945,13 +2934,14 @@ CheckDeducedArgumentConstraints(Sema &S, TemplateDeclT *Template, llvm::SmallVector AssociatedConstraints; Template->getAssociatedConstraints(AssociatedConstraints); - bool NeedsReplacement = DeducedArgsNeedReplacement(Template); - TemplateArgumentList DeducedTAL{TemplateArgumentList::OnStack, - CanonicalDeducedArgs}; + std::optional> Innermost; + // If we don't need to replace the deduced template arguments, + // we can add them immediately as the inner-most argument list. + if (!DeducedArgsNeedReplacement(Template)) + Innermost = CanonicalDeducedArgs; MultiLevelTemplateArgumentList MLTAL = S.getTemplateInstantiationArgs( - Template, Template->getDeclContext(), /*Final=*/false, - /*InnerMost=*/NeedsReplacement ? nullptr : &DeducedTAL, + Template, Template->getDeclContext(), /*Final=*/false, Innermost, /*RelativeToPrimary=*/true, /*Pattern=*/ nullptr, /*ForConstraintInstantiation=*/true); @@ -2959,7 +2949,7 @@ CheckDeducedArgumentConstraints(Sema &S, TemplateDeclT *Template, // template args when this is a variable template partial specialization and // not class-scope explicit specialization, so replace with Deduced Args // instead of adding to inner-most. - if (NeedsReplacement) + if (!Innermost) MLTAL.replaceInnermostTemplateArguments(Template, CanonicalDeducedArgs); if (S.CheckConstraintSatisfaction(Template, AssociatedConstraints, MLTAL, @@ -2980,7 +2970,7 @@ static std::enable_if_t::value, Sema::TemplateDeductionResult> FinishTemplateArgumentDeduction( Sema &S, T *Partial, bool IsPartialOrdering, - const TemplateArgumentList &TemplateArgs, + ArrayRef TemplateArgs, SmallVectorImpl &Deduced, TemplateDeductionInfo &Info) { // Unevaluated SFINAE context. @@ -3073,7 +3063,7 @@ FinishTemplateArgumentDeduction( // FIXME: Factor out duplication with partial specialization version above. static Sema::TemplateDeductionResult FinishTemplateArgumentDeduction( Sema &S, TemplateDecl *Template, bool PartialOrdering, - const TemplateArgumentList &TemplateArgs, + ArrayRef TemplateArgs, SmallVectorImpl &Deduced, TemplateDeductionInfo &Info) { // Unevaluated SFINAE context. @@ -3122,7 +3112,7 @@ static Sema::TemplateDeductionResult FinishTemplateArgumentDeduction( /// partial specialization per C++ [temp.class.spec.match]. Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial, - const TemplateArgumentList &TemplateArgs, + ArrayRef TemplateArgs, TemplateDeductionInfo &Info) { if (Partial->isInvalidDecl()) return TDK_Invalid; @@ -3144,11 +3134,10 @@ Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial, SmallVector Deduced; Deduced.resize(Partial->getTemplateParameters()->size()); - if (TemplateDeductionResult Result - = ::DeduceTemplateArguments(*this, - Partial->getTemplateParameters(), - Partial->getTemplateArgs(), - TemplateArgs, Info, Deduced)) + if (TemplateDeductionResult Result = ::DeduceTemplateArguments( + *this, Partial->getTemplateParameters(), + Partial->getTemplateArgs().asArray(), TemplateArgs, Info, Deduced, + /*NumberOfArgumentsMustMatch=*/false)) return Result; SmallVector DeducedArgs(Deduced.begin(), Deduced.end()); @@ -3174,7 +3163,7 @@ Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial, /// partial specialization per C++ [temp.class.spec.match]. Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(VarTemplatePartialSpecializationDecl *Partial, - const TemplateArgumentList &TemplateArgs, + ArrayRef TemplateArgs, TemplateDeductionInfo &Info) { if (Partial->isInvalidDecl()) return TDK_Invalid; @@ -3197,8 +3186,9 @@ Sema::DeduceTemplateArguments(VarTemplatePartialSpecializationDecl *Partial, SmallVector Deduced; Deduced.resize(Partial->getTemplateParameters()->size()); if (TemplateDeductionResult Result = ::DeduceTemplateArguments( - *this, Partial->getTemplateParameters(), Partial->getTemplateArgs(), - TemplateArgs, Info, Deduced)) + *this, Partial->getTemplateParameters(), + Partial->getTemplateArgs().asArray(), TemplateArgs, Info, Deduced, + /*NumberOfArgumentsMustMatch=*/false)) return Result; SmallVector DeducedArgs(Deduced.begin(), Deduced.end()); @@ -3427,15 +3417,15 @@ Sema::TemplateDeductionResult Sema::SubstituteExplicitTemplateArguments( // specification. SmallVector ExceptionStorage; if (getLangOpts().CPlusPlus17 && - SubstExceptionSpec(Function->getLocation(), EPI.ExceptionSpec, - ExceptionStorage, - getTemplateInstantiationArgs( - FunctionTemplate, nullptr, /*Final=*/true, - /*Innermost=*/SugaredExplicitArgumentList, - /*RelativeToPrimary=*/false, - /*Pattern=*/nullptr, - /*ForConstraintInstantiation=*/false, - /*SkipForSpecialization=*/true))) + SubstExceptionSpec( + Function->getLocation(), EPI.ExceptionSpec, ExceptionStorage, + getTemplateInstantiationArgs( + FunctionTemplate, nullptr, /*Final=*/true, + /*Innermost=*/SugaredExplicitArgumentList->asArray(), + /*RelativeToPrimary=*/false, + /*Pattern=*/nullptr, + /*ForConstraintInstantiation=*/false, + /*SkipForSpecialization=*/true))) return TDK_SubstitutionFailure; *FunctionType = BuildFunctionType(ResultType, ParamTypes, @@ -5802,10 +5792,8 @@ static bool isAtLeastAsSpecializedAs(Sema &S, QualType T1, QualType T2, bool AtLeastAsSpecialized; S.runWithSufficientStackSpace(Info.getLocation(), [&] { AtLeastAsSpecialized = !FinishTemplateArgumentDeduction( - S, P2, /*IsPartialOrdering=*/true, - TemplateArgumentList(TemplateArgumentList::OnStack, - TST1->template_arguments()), - Deduced, Info); + S, P2, /*IsPartialOrdering=*/true, TST1->template_arguments(), Deduced, + Info); }); return AtLeastAsSpecialized; } diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index e12186d7d82f8..01b78e4424fb5 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -338,7 +338,7 @@ Response HandleGenericDeclContext(const Decl *CurDecl) { MultiLevelTemplateArgumentList Sema::getTemplateInstantiationArgs( const NamedDecl *ND, const DeclContext *DC, bool Final, - const TemplateArgumentList *Innermost, bool RelativeToPrimary, + std::optional> Innermost, bool RelativeToPrimary, const FunctionDecl *Pattern, bool ForConstraintInstantiation, bool SkipForSpecialization) { assert((ND || DC) && "Can't find arguments for a decl if one isn't provided"); @@ -352,8 +352,8 @@ MultiLevelTemplateArgumentList Sema::getTemplateInstantiationArgs( CurDecl = Decl::castFromDeclContext(DC); if (Innermost) { - Result.addOuterTemplateArguments(const_cast(ND), - Innermost->asArray(), Final); + Result.addOuterTemplateArguments(const_cast(ND), *Innermost, + Final); // Populate placeholder template arguments for TemplateTemplateParmDecls. // This is essential for the case e.g. // @@ -3656,7 +3656,8 @@ bool Sema::usesPartialOrExplicitSpecialization( for (unsigned I = 0, N = PartialSpecs.size(); I != N; ++I) { TemplateDeductionInfo Info(Loc); if (!DeduceTemplateArguments(PartialSpecs[I], - ClassTemplateSpec->getTemplateArgs(), Info)) + ClassTemplateSpec->getTemplateArgs().asArray(), + Info)) return true; } @@ -3701,7 +3702,7 @@ getPatternForClassTemplateSpecialization( ClassTemplatePartialSpecializationDecl *Partial = PartialSpecs[I]; TemplateDeductionInfo Info(FailedCandidates.getLocation()); if (Sema::TemplateDeductionResult Result = S.DeduceTemplateArguments( - Partial, ClassTemplateSpec->getTemplateArgs(), Info)) { + Partial, ClassTemplateSpec->getTemplateArgs().asArray(), Info)) { // Store the failed-deduction information for use in diagnostics, later. // TODO: Actually use the failed-deduction info? FailedCandidates.addCandidate().set( diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index fcb27a880290b..d67b21b4449e0 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -4656,9 +4656,10 @@ bool Sema::InstantiateDefaultArgument(SourceLocation CallLoc, FunctionDecl *FD, // // template // A Foo(int a = A::FooImpl()); - MultiLevelTemplateArgumentList TemplateArgs = getTemplateInstantiationArgs( - FD, FD->getLexicalDeclContext(), /*Final=*/false, nullptr, - /*RelativeToPrimary=*/true); + MultiLevelTemplateArgumentList TemplateArgs = + getTemplateInstantiationArgs(FD, FD->getLexicalDeclContext(), + /*Final=*/false, /*Innermost=*/std::nullopt, + /*RelativeToPrimary=*/true); if (SubstDefaultArgument(CallLoc, Param, TemplateArgs, /*ForCallExpr*/ true)) return true; @@ -4696,9 +4697,10 @@ void Sema::InstantiateExceptionSpec(SourceLocation PointOfInstantiation, Sema::ContextRAII savedContext(*this, Decl); LocalInstantiationScope Scope(*this); - MultiLevelTemplateArgumentList TemplateArgs = getTemplateInstantiationArgs( - Decl, Decl->getLexicalDeclContext(), /*Final=*/false, nullptr, - /*RelativeToPrimary*/ true); + MultiLevelTemplateArgumentList TemplateArgs = + getTemplateInstantiationArgs(Decl, Decl->getLexicalDeclContext(), + /*Final=*/false, /*Innermost=*/std::nullopt, + /*RelativeToPrimary*/ true); // FIXME: We can't use getTemplateInstantiationPattern(false) in general // here, because for a non-defining friend declaration in a class template, @@ -5140,8 +5142,8 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, SetDeclDefaulted(Function, PatternDecl->getLocation()); } else { MultiLevelTemplateArgumentList TemplateArgs = getTemplateInstantiationArgs( - Function, Function->getLexicalDeclContext(), /*Final=*/false, nullptr, - false, PatternDecl); + Function, Function->getLexicalDeclContext(), /*Final=*/false, + /*Innermost=*/std::nullopt, false, PatternDecl); // Substitute into the qualifier; we can get a substitution failure here // through evil use of alias templates. @@ -5211,7 +5213,7 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, VarTemplateSpecializationDecl *Sema::BuildVarTemplateInstantiation( VarTemplateDecl *VarTemplate, VarDecl *FromVar, - const TemplateArgumentList &TemplateArgList, + const TemplateArgumentList *PartialSpecArgs, const TemplateArgumentListInfo &TemplateArgsInfo, SmallVectorImpl &Converted, SourceLocation PointOfInstantiation, LateInstantiatedAttrVec *LateAttrs, @@ -5236,14 +5238,15 @@ VarTemplateSpecializationDecl *Sema::BuildVarTemplateInstantiation( MultiLevelTemplateArgumentList MultiLevelList; if (auto *PartialSpec = dyn_cast(FromVar)) { + assert(PartialSpecArgs); IsMemberSpec = PartialSpec->isMemberSpecialization(); MultiLevelList.addOuterTemplateArguments( - PartialSpec, TemplateArgList.asArray(), /*Final=*/false); + PartialSpec, PartialSpecArgs->asArray(), /*Final=*/false); } else { assert(VarTemplate == FromVar->getDescribedVarTemplate()); IsMemberSpec = VarTemplate->isMemberSpecialization(); - MultiLevelList.addOuterTemplateArguments( - VarTemplate, TemplateArgList.asArray(), /*Final=*/false); + MultiLevelList.addOuterTemplateArguments(VarTemplate, Converted, + /*Final=*/false); } if (!IsMemberSpec) FromVar = FromVar->getFirstDecl();