diff --git a/third_party/llvm/generated.patch b/third_party/llvm/generated.patch index ca1e4ff4d..509398da9 100644 --- a/third_party/llvm/generated.patch +++ b/third_party/llvm/generated.patch @@ -1,2926 +1 @@ Auto generated patch. Do not edit or delete it, even if empty. -diff -ruN --strip-trailing-cr a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst ---- a/clang/docs/ReleaseNotes.rst -+++ b/clang/docs/ReleaseNotes.rst -@@ -569,9 +569,6 @@ - in certain friend declarations. (#GH93099) - - Clang now instantiates the correct lambda call operator when a lambda's class type is - merged across modules. (#GH110401) --- Clang now uses the correct set of template argument lists when comparing the constraints of -- out-of-line definitions and member templates explicitly specialized for a given implicit instantiation of -- a class template. (#GH102320) - - Fix a crash when parsing a pseudo destructor involving an invalid type. (#GH111460) - - Fixed an assertion failure when invoking recovery call expressions with explicit attributes - and undeclared templates. (#GH107047), (#GH49093) -diff -ruN --strip-trailing-cr a/clang/include/clang/AST/DeclTemplate.h b/clang/include/clang/AST/DeclTemplate.h ---- a/clang/include/clang/AST/DeclTemplate.h -+++ b/clang/include/clang/AST/DeclTemplate.h -@@ -787,11 +787,15 @@ - EntryType *Entry, void *InsertPos); - - struct CommonBase { -- CommonBase() {} -+ CommonBase() : InstantiatedFromMember(nullptr, false) {} - - /// The template from which this was most - /// directly instantiated (or null). -- RedeclarableTemplateDecl *InstantiatedFromMember = nullptr; -+ /// -+ /// The boolean value indicates whether this template -+ /// was explicitly specialized. -+ llvm::PointerIntPair -+ InstantiatedFromMember; - - /// If non-null, points to an array of specializations (including - /// partial specializations) known only by their external declaration IDs. -@@ -802,19 +806,14 @@ - }; - - /// Pointer to the common data shared by all declarations of this -- /// template, and a flag indicating if the template is a member -- /// specialization. -- mutable llvm::PointerIntPair Common; -- -- CommonBase *getCommonPtrInternal() const { return Common.getPointer(); } -+ /// template. -+ mutable CommonBase *Common = nullptr; - - /// Retrieves the "common" pointer shared by all (re-)declarations of - /// the same template. Calling this routine may implicitly allocate memory - /// for the common pointer. - CommonBase *getCommonPtr() const; - -- void setCommonPtr(CommonBase *C) const { Common.setPointer(C); } -- - virtual CommonBase *newCommon(ASTContext &C) const = 0; - - // Construct a template decl with name, parameters, and templated element. -@@ -855,12 +854,15 @@ - /// template<> template - /// struct X::Inner { /* ... */ }; - /// \endcode -- bool isMemberSpecialization() const { return Common.getInt(); } -+ bool isMemberSpecialization() const { -+ return getCommonPtr()->InstantiatedFromMember.getInt(); -+ } - - /// Note that this member template is a specialization. - void setMemberSpecialization() { -- assert(!isMemberSpecialization() && "already a member specialization"); -- Common.setInt(true); -+ assert(getCommonPtr()->InstantiatedFromMember.getPointer() && -+ "Only member templates can be member template specializations"); -+ getCommonPtr()->InstantiatedFromMember.setInt(true); - } - - /// Retrieve the member template from which this template was -@@ -900,12 +902,12 @@ - /// void X::f(T, U); - /// \endcode - RedeclarableTemplateDecl *getInstantiatedFromMemberTemplate() const { -- return getCommonPtr()->InstantiatedFromMember; -+ return getCommonPtr()->InstantiatedFromMember.getPointer(); - } - - void setInstantiatedFromMemberTemplate(RedeclarableTemplateDecl *TD) { -- assert(!getCommonPtr()->InstantiatedFromMember); -- getCommonPtr()->InstantiatedFromMember = TD; -+ assert(!getCommonPtr()->InstantiatedFromMember.getPointer()); -+ getCommonPtr()->InstantiatedFromMember.setPointer(TD); - } - - /// Retrieve the "injected" template arguments that correspond to the -@@ -1955,7 +1957,13 @@ - /// specialization which was specialized by this. - llvm::PointerUnion -- getSpecializedTemplateOrPartial() const; -+ getSpecializedTemplateOrPartial() const { -+ if (const auto *PartialSpec = -+ SpecializedTemplate.dyn_cast()) -+ return PartialSpec->PartialSpecialization; -+ -+ return SpecializedTemplate.get(); -+ } - - /// Retrieve the set of template arguments that should be used - /// to instantiate members of the class template or class template partial -@@ -1981,8 +1989,6 @@ - /// template arguments have been deduced. - void setInstantiationOf(ClassTemplatePartialSpecializationDecl *PartialSpec, - const TemplateArgumentList *TemplateArgs) { -- assert(!isa(this) && -- "A partial specialization cannot be instantiated from a template"); - assert(!SpecializedTemplate.is() && - "Already set to a class template partial specialization!"); - auto *PS = new (getASTContext()) SpecializedPartialSpecialization(); -@@ -1994,8 +2000,6 @@ - /// Note that this class template specialization is an instantiation - /// of the given class template. - void setInstantiationOf(ClassTemplateDecl *TemplDecl) { -- assert(!isa(this) && -- "A partial specialization cannot be instantiated from a template"); - assert(!SpecializedTemplate.is() && - "Previously set to a class template partial specialization!"); - SpecializedTemplate = TemplDecl; -@@ -2189,11 +2193,18 @@ - /// struct X::Inner { /* ... */ }; - /// \endcode - bool isMemberSpecialization() const { -- return InstantiatedFromMember.getInt(); -+ const auto *First = -+ cast(getFirstDecl()); -+ return First->InstantiatedFromMember.getInt(); - } - - /// Note that this member template is a specialization. -- void setMemberSpecialization() { return InstantiatedFromMember.setInt(true); } -+ void setMemberSpecialization() { -+ auto *First = cast(getFirstDecl()); -+ assert(First->InstantiatedFromMember.getPointer() && -+ "Only member templates can be member template specializations"); -+ return First->InstantiatedFromMember.setInt(true); -+ } - - /// Retrieves the injected specialization type for this partial - /// specialization. This is not the same as the type-decl-type for -@@ -2263,6 +2274,8 @@ - return static_cast(RedeclarableTemplateDecl::getCommonPtr()); - } - -+ void setCommonPtr(Common *C) { RedeclarableTemplateDecl::Common = C; } -+ - public: - - friend class ASTDeclReader; -@@ -2713,7 +2726,13 @@ - /// Retrieve the variable template or variable template partial - /// specialization which was specialized by this. - llvm::PointerUnion -- getSpecializedTemplateOrPartial() const; -+ getSpecializedTemplateOrPartial() const { -+ if (const auto *PartialSpec = -+ SpecializedTemplate.dyn_cast()) -+ return PartialSpec->PartialSpecialization; -+ -+ return SpecializedTemplate.get(); -+ } - - /// Retrieve the set of template arguments that should be used - /// to instantiate the initializer of the variable template or variable -@@ -2739,8 +2758,6 @@ - /// template arguments have been deduced. - void setInstantiationOf(VarTemplatePartialSpecializationDecl *PartialSpec, - const TemplateArgumentList *TemplateArgs) { -- assert(!isa(this) && -- "A partial specialization cannot be instantiated from a template"); - assert(!SpecializedTemplate.is() && - "Already set to a variable template partial specialization!"); - auto *PS = new (getASTContext()) SpecializedPartialSpecialization(); -@@ -2752,8 +2769,6 @@ - /// Note that this variable template specialization is an instantiation - /// of the given variable template. - void setInstantiationOf(VarTemplateDecl *TemplDecl) { -- assert(!isa(this) && -- "A partial specialization cannot be instantiated from a template"); - assert(!SpecializedTemplate.is() && - "Previously set to a variable template partial specialization!"); - SpecializedTemplate = TemplDecl; -@@ -2944,11 +2959,18 @@ - /// U* X::Inner = (T*)(0) + 1; - /// \endcode - bool isMemberSpecialization() const { -- return InstantiatedFromMember.getInt(); -+ const auto *First = -+ cast(getFirstDecl()); -+ return First->InstantiatedFromMember.getInt(); - } - - /// Note that this member template is a specialization. -- void setMemberSpecialization() { return InstantiatedFromMember.setInt(true); } -+ void setMemberSpecialization() { -+ auto *First = cast(getFirstDecl()); -+ assert(First->InstantiatedFromMember.getPointer() && -+ "Only member templates can be member template specializations"); -+ return First->InstantiatedFromMember.setInt(true); -+ } - - SourceRange getSourceRange() const override LLVM_READONLY; - -@@ -3119,9 +3141,6 @@ - return makeSpecIterator(getSpecializations(), true); - } - -- /// Merge \p Prev with our RedeclarableTemplateDecl::Common. -- void mergePrevDecl(VarTemplateDecl *Prev); -- - // Implement isa/cast/dyncast support - static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classofKind(Kind K) { return K == VarTemplate; } -diff -ruN --strip-trailing-cr a/clang/include/clang/AST/SYCLKernelInfo.h b/clang/include/clang/AST/SYCLKernelInfo.h ---- a/clang/include/clang/AST/SYCLKernelInfo.h -+++ b/clang/include/clang/AST/SYCLKernelInfo.h -@@ -13,6 +13,7 @@ - #ifndef LLVM_CLANG_AST_SYCLKERNELINFO_H - #define LLVM_CLANG_AST_SYCLKERNELINFO_H - -+#include "clang/AST/CanonicalType.h" - #include "clang/AST/Decl.h" - #include "clang/AST/Type.h" - -diff -ruN --strip-trailing-cr a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h ---- a/clang/include/clang/Sema/Sema.h -+++ b/clang/include/clang/Sema/Sema.h -@@ -11328,9 +11328,9 @@ - CXXScopeSpec &SS, IdentifierInfo *Name, SourceLocation NameLoc, - const ParsedAttributesView &Attr, TemplateParameterList *TemplateParams, - AccessSpecifier AS, SourceLocation ModulePrivateLoc, -- SourceLocation FriendLoc, -- ArrayRef OuterTemplateParamLists, -- bool IsMemberSpecialization, SkipBodyInfo *SkipBody = nullptr); -+ SourceLocation FriendLoc, unsigned NumOuterTemplateParamLists, -+ TemplateParameterList **OuterTemplateParamLists, -+ SkipBodyInfo *SkipBody = nullptr); - - /// Translates template arguments as provided by the parser - /// into template arguments used by semantic analysis. -@@ -11369,8 +11369,7 @@ - DeclResult ActOnVarTemplateSpecialization( - Scope *S, Declarator &D, TypeSourceInfo *DI, LookupResult &Previous, - SourceLocation TemplateKWLoc, TemplateParameterList *TemplateParams, -- StorageClass SC, bool IsPartialSpecialization, -- bool IsMemberSpecialization); -+ StorageClass SC, bool IsPartialSpecialization); - - /// Get the specialization of the given variable template corresponding to - /// the specified argument list, or a null-but-valid result if the arguments -@@ -13012,14 +13011,28 @@ - /// dealing with a specialization. This is only relevant for function - /// template specializations. - /// -+ /// \param Pattern If non-NULL, indicates the pattern from which we will be -+ /// instantiating the definition of the given declaration, \p ND. This is -+ /// used to determine the proper set of template instantiation arguments for -+ /// friend function template specializations. -+ /// - /// \param ForConstraintInstantiation when collecting arguments, - /// ForConstraintInstantiation indicates we should continue looking when - /// encountering a lambda generic call operator, and continue looking for - /// arguments on an enclosing class template. -+ /// -+ /// \param SkipForSpecialization when specified, any template specializations -+ /// in a traversal would be ignored. -+ /// \param ForDefaultArgumentSubstitution indicates we should continue looking -+ /// when encountering a specialized member function template, rather than -+ /// returning immediately. - MultiLevelTemplateArgumentList getTemplateInstantiationArgs( - const NamedDecl *D, const DeclContext *DC = nullptr, bool Final = false, - std::optional> Innermost = std::nullopt, -- bool RelativeToPrimary = false, bool ForConstraintInstantiation = false); -+ bool RelativeToPrimary = false, const FunctionDecl *Pattern = nullptr, -+ bool ForConstraintInstantiation = false, -+ bool SkipForSpecialization = false, -+ bool ForDefaultArgumentSubstitution = false); - - /// RAII object to handle the state changes required to synthesize - /// a function body. -diff -ruN --strip-trailing-cr a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp ---- a/clang/lib/AST/ASTImporter.cpp -+++ b/clang/lib/AST/ASTImporter.cpp -@@ -6190,8 +6190,7 @@ - ExpectedDecl ASTNodeImporter::VisitClassTemplateSpecializationDecl( - ClassTemplateSpecializationDecl *D) { - ClassTemplateDecl *ClassTemplate; -- if (Error Err = importInto(ClassTemplate, -- D->getSpecializedTemplate()->getCanonicalDecl())) -+ if (Error Err = importInto(ClassTemplate, D->getSpecializedTemplate())) - return std::move(Err); - - // Import the context of this declaration. -diff -ruN --strip-trailing-cr a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp ---- a/clang/lib/AST/Decl.cpp -+++ b/clang/lib/AST/Decl.cpp -@@ -2709,20 +2709,20 @@ - auto From = VDTemplSpec->getInstantiatedFrom(); - if (auto *VTD = From.dyn_cast()) { - while (!VTD->isMemberSpecialization()) { -- if (auto *NewVTD = VTD->getInstantiatedFromMemberTemplate()) -- VTD = NewVTD; -- else -+ auto *NewVTD = VTD->getInstantiatedFromMemberTemplate(); -+ if (!NewVTD) - break; -+ VTD = NewVTD; - } - return getDefinitionOrSelf(VTD->getTemplatedDecl()); - } - if (auto *VTPSD = - From.dyn_cast()) { - while (!VTPSD->isMemberSpecialization()) { -- if (auto *NewVTPSD = VTPSD->getInstantiatedFromMember()) -- VTPSD = NewVTPSD; -- else -+ auto *NewVTPSD = VTPSD->getInstantiatedFromMember(); -+ if (!NewVTPSD) - break; -+ VTPSD = NewVTPSD; - } - return getDefinitionOrSelf(VTPSD); - } -@@ -2731,14 +2731,15 @@ - - // If this is the pattern of a variable template, find where it was - // instantiated from. FIXME: Is this necessary? -- if (VarTemplateDecl *VTD = VD->getDescribedVarTemplate()) { -- while (!VTD->isMemberSpecialization()) { -- if (auto *NewVTD = VTD->getInstantiatedFromMemberTemplate()) -- VTD = NewVTD; -- else -+ if (VarTemplateDecl *VarTemplate = VD->getDescribedVarTemplate()) { -+ while (!VarTemplate->isMemberSpecialization()) { -+ auto *NewVT = VarTemplate->getInstantiatedFromMemberTemplate(); -+ if (!NewVT) - break; -+ VarTemplate = NewVT; - } -- return getDefinitionOrSelf(VTD->getTemplatedDecl()); -+ -+ return getDefinitionOrSelf(VarTemplate->getTemplatedDecl()); - } - - if (VD == this) -@@ -4154,10 +4155,10 @@ - // If we hit a point where the user provided a specialization of this - // template, we're done looking. - while (!ForDefinition || !Primary->isMemberSpecialization()) { -- if (auto *NewPrimary = Primary->getInstantiatedFromMemberTemplate()) -- Primary = NewPrimary; -- else -+ auto *NewPrimary = Primary->getInstantiatedFromMemberTemplate(); -+ if (!NewPrimary) - break; -+ Primary = NewPrimary; - } - - return getDefinitionOrSelf(Primary->getTemplatedDecl()); -@@ -4170,7 +4171,7 @@ - if (FunctionTemplateSpecializationInfo *Info - = TemplateOrSpecialization - .dyn_cast()) { -- return Info->getTemplate()->getMostRecentDecl(); -+ return Info->getTemplate(); - } - return nullptr; - } -diff -ruN --strip-trailing-cr a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp ---- a/clang/lib/AST/DeclCXX.cpp -+++ b/clang/lib/AST/DeclCXX.cpp -@@ -2030,21 +2030,19 @@ - if (auto *TD = dyn_cast(this)) { - auto From = TD->getInstantiatedFrom(); - if (auto *CTD = From.dyn_cast()) { -- while (!CTD->isMemberSpecialization()) { -- if (auto *NewCTD = CTD->getInstantiatedFromMemberTemplate()) -- CTD = NewCTD; -- else -+ while (auto *NewCTD = CTD->getInstantiatedFromMemberTemplate()) { -+ if (NewCTD->isMemberSpecialization()) - break; -+ CTD = NewCTD; - } - return GetDefinitionOrSelf(CTD->getTemplatedDecl()); - } - if (auto *CTPSD = - From.dyn_cast()) { -- while (!CTPSD->isMemberSpecialization()) { -- if (auto *NewCTPSD = CTPSD->getInstantiatedFromMemberTemplate()) -- CTPSD = NewCTPSD; -- else -+ while (auto *NewCTPSD = CTPSD->getInstantiatedFromMember()) { -+ if (NewCTPSD->isMemberSpecialization()) - break; -+ CTPSD = NewCTPSD; - } - return GetDefinitionOrSelf(CTPSD); - } -diff -ruN --strip-trailing-cr a/clang/lib/AST/DeclTemplate.cpp b/clang/lib/AST/DeclTemplate.cpp ---- a/clang/lib/AST/DeclTemplate.cpp -+++ b/clang/lib/AST/DeclTemplate.cpp -@@ -320,16 +320,16 @@ - void RedeclarableTemplateDecl::anchor() {} - - RedeclarableTemplateDecl::CommonBase *RedeclarableTemplateDecl::getCommonPtr() const { -- if (CommonBase *C = getCommonPtrInternal()) -- return C; -+ if (Common) -+ return Common; - - // Walk the previous-declaration chain until we either find a declaration - // with a common pointer or we run out of previous declarations. - SmallVector PrevDecls; - for (const RedeclarableTemplateDecl *Prev = getPreviousDecl(); Prev; - Prev = Prev->getPreviousDecl()) { -- if (CommonBase *C = Prev->getCommonPtrInternal()) { -- setCommonPtr(C); -+ if (Prev->Common) { -+ Common = Prev->Common; - break; - } - -@@ -337,18 +337,18 @@ - } - - // If we never found a common pointer, allocate one now. -- if (!getCommonPtrInternal()) { -+ if (!Common) { - // FIXME: If any of the declarations is from an AST file, we probably - // need an update record to add the common data. - -- setCommonPtr(newCommon(getASTContext())); -+ Common = newCommon(getASTContext()); - } - - // Update any previous declarations we saw with the common pointer. - for (const RedeclarableTemplateDecl *Prev : PrevDecls) -- Prev->setCommonPtr(getCommonPtrInternal()); -+ Prev->Common = Common; - -- return getCommonPtrInternal(); -+ return Common; - } - - void RedeclarableTemplateDecl::loadLazySpecializationsImpl() const { -@@ -458,17 +458,19 @@ - } - - void FunctionTemplateDecl::mergePrevDecl(FunctionTemplateDecl *Prev) { -+ using Base = RedeclarableTemplateDecl; -+ - // If we haven't created a common pointer yet, then it can just be created - // with the usual method. -- if (!getCommonPtrInternal()) -+ if (!Base::Common) - return; - -- Common *ThisCommon = static_cast(getCommonPtrInternal()); -+ Common *ThisCommon = static_cast(Base::Common); - Common *PrevCommon = nullptr; - SmallVector PreviousDecls; - for (; Prev; Prev = Prev->getPreviousDecl()) { -- if (CommonBase *C = Prev->getCommonPtrInternal()) { -- PrevCommon = static_cast(C); -+ if (Prev->Base::Common) { -+ PrevCommon = static_cast(Prev->Base::Common); - break; - } - PreviousDecls.push_back(Prev); -@@ -478,7 +480,7 @@ - // use this common pointer. - if (!PrevCommon) { - for (auto *D : PreviousDecls) -- D->setCommonPtr(ThisCommon); -+ D->Base::Common = ThisCommon; - return; - } - -@@ -486,7 +488,7 @@ - assert(ThisCommon->Specializations.size() == 0 && - "Can't merge incompatible declarations!"); - -- setCommonPtr(PrevCommon); -+ Base::Common = PrevCommon; - } - - //===----------------------------------------------------------------------===// -@@ -993,17 +995,7 @@ - if (const auto *PartialSpec = - SpecializedTemplate.dyn_cast()) - return PartialSpec->PartialSpecialization->getSpecializedTemplate(); -- return SpecializedTemplate.get()->getMostRecentDecl(); --} -- --llvm::PointerUnion --ClassTemplateSpecializationDecl::getSpecializedTemplateOrPartial() const { -- if (const auto *PartialSpec = -- SpecializedTemplate.dyn_cast()) -- return PartialSpec->PartialSpecialization->getMostRecentDecl(); -- -- return SpecializedTemplate.get()->getMostRecentDecl(); -+ return SpecializedTemplate.get(); - } - - SourceRange -@@ -1293,39 +1285,6 @@ - return CommonPtr; - } - --void VarTemplateDecl::mergePrevDecl(VarTemplateDecl *Prev) { -- // If we haven't created a common pointer yet, then it can just be created -- // with the usual method. -- if (!getCommonPtrInternal()) -- return; -- -- Common *ThisCommon = static_cast(getCommonPtrInternal()); -- Common *PrevCommon = nullptr; -- SmallVector PreviousDecls; -- for (; Prev; Prev = Prev->getPreviousDecl()) { -- if (CommonBase *C = Prev->getCommonPtrInternal()) { -- PrevCommon = static_cast(C); -- break; -- } -- PreviousDecls.push_back(Prev); -- } -- -- // If the previous redecl chain hasn't created a common pointer yet, then just -- // use this common pointer. -- if (!PrevCommon) { -- for (auto *D : PreviousDecls) -- D->setCommonPtr(ThisCommon); -- return; -- } -- -- // Ensure we don't leak any important state. -- assert(ThisCommon->Specializations.empty() && -- ThisCommon->PartialSpecializations.empty() && -- "Can't merge incompatible declarations!"); -- -- setCommonPtr(PrevCommon); --} -- - VarTemplateSpecializationDecl * - VarTemplateDecl::findSpecialization(ArrayRef Args, - void *&InsertPos) { -@@ -1448,16 +1407,7 @@ - if (const auto *PartialSpec = - SpecializedTemplate.dyn_cast()) - return PartialSpec->PartialSpecialization->getSpecializedTemplate(); -- return SpecializedTemplate.get()->getMostRecentDecl(); --} -- --llvm::PointerUnion --VarTemplateSpecializationDecl::getSpecializedTemplateOrPartial() const { -- if (const auto *PartialSpec = -- SpecializedTemplate.dyn_cast()) -- return PartialSpec->PartialSpecialization->getMostRecentDecl(); -- -- return SpecializedTemplate.get()->getMostRecentDecl(); -+ return SpecializedTemplate.get(); - } - - SourceRange VarTemplateSpecializationDecl::getSourceRange() const { -diff -ruN --strip-trailing-cr a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp ---- a/clang/lib/Sema/SemaConcept.cpp -+++ b/clang/lib/Sema/SemaConcept.cpp -@@ -585,7 +585,7 @@ - - ArrayRef TemplateArgs = - TemplateArgsLists.getNumSubstitutedLevels() > 0 -- ? TemplateArgsLists.getInnermost() -+ ? TemplateArgsLists.getOutermost() - : ArrayRef{}; - Sema::InstantiatingTemplate Inst(S, TemplateIDRange.getBegin(), - Sema::InstantiatingTemplate::ConstraintsCheck{}, -@@ -834,6 +834,7 @@ - getTemplateInstantiationArgs(FD, FD->getLexicalDeclContext(), - /*Final=*/false, /*Innermost=*/std::nullopt, - /*RelativeToPrimary=*/true, -+ /*Pattern=*/nullptr, - /*ForConstraintInstantiation=*/true); - if (SetupConstraintScope(FD, TemplateArgs, MLTAL, Scope)) - return std::nullopt; -@@ -909,13 +910,15 @@ - // Figure out the to-translation-unit depth for this function declaration for - // the purpose of seeing if they differ by constraints. This isn't the same as - // getTemplateDepth, because it includes already instantiated parents. --static unsigned CalculateTemplateDepthForConstraints(Sema &S, -- const NamedDecl *ND) { -+static unsigned -+CalculateTemplateDepthForConstraints(Sema &S, const NamedDecl *ND, -+ bool SkipForSpecialization = false) { - MultiLevelTemplateArgumentList MLTAL = S.getTemplateInstantiationArgs( - ND, ND->getLexicalDeclContext(), /*Final=*/false, - /*Innermost=*/std::nullopt, - /*RelativeToPrimary=*/true, -- /*ForConstraintInstantiation=*/true); -+ /*Pattern=*/nullptr, -+ /*ForConstraintInstantiation=*/true, SkipForSpecialization); - return MLTAL.getNumLevels(); - } - -@@ -954,7 +957,8 @@ - DeclInfo.getDecl(), DeclInfo.getLexicalDeclContext(), /*Final=*/false, - /*Innermost=*/std::nullopt, - /*RelativeToPrimary=*/true, -- /*ForConstraintInstantiation=*/true); -+ /*Pattern=*/nullptr, /*ForConstraintInstantiation=*/true, -+ /*SkipForSpecialization*/ false); - - if (MLTAL.getNumSubstitutedLevels() == 0) - return ConstrExpr; -@@ -1064,16 +1068,16 @@ - bool Sema::FriendConstraintsDependOnEnclosingTemplate(const FunctionDecl *FD) { - assert(FD->getFriendObjectKind() && "Must be a friend!"); - -- FunctionTemplateDecl *FTD = FD->getDescribedFunctionTemplate(); - // The logic for non-templates is handled in ASTContext::isSameEntity, so we - // don't have to bother checking 'DependsOnEnclosingTemplate' for a - // non-function-template. -- assert(FTD && "Non-function templates don't need to be checked"); -+ assert(FD->getDescribedFunctionTemplate() && -+ "Non-function templates don't need to be checked"); - - SmallVector ACs; -- FTD->getAssociatedConstraints(ACs); -+ FD->getDescribedFunctionTemplate()->getAssociatedConstraints(ACs); - -- unsigned OldTemplateDepth = FTD->getTemplateParameters()->getDepth(); -+ unsigned OldTemplateDepth = CalculateTemplateDepthForConstraints(*this, FD); - for (const Expr *Constraint : ACs) - if (ConstraintExpressionDependsOnEnclosingTemplate(FD, OldTemplateDepth, - Constraint)) -@@ -1520,6 +1524,7 @@ - CSE->getNamedConcept(), CSE->getNamedConcept()->getLexicalDeclContext(), - /*Final=*/false, CSE->getTemplateArguments(), - /*RelativeToPrimary=*/true, -+ /*Pattern=*/nullptr, - /*ForConstraintInstantiation=*/true); - - return substituteParameterMappings(S, N, CSE->getNamedConcept(), MLTAL, -@@ -1800,8 +1805,8 @@ - return false; - } - -- unsigned Depth1 = CalculateTemplateDepthForConstraints(*this, D1); -- unsigned Depth2 = CalculateTemplateDepthForConstraints(*this, D2); -+ unsigned Depth1 = CalculateTemplateDepthForConstraints(*this, D1, true); -+ unsigned Depth2 = CalculateTemplateDepthForConstraints(*this, D2, true); - - for (size_t I = 0; I != AC1.size() && I != AC2.size(); ++I) { - if (Depth2 > Depth1) { -diff -ruN --strip-trailing-cr a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp ---- a/clang/lib/Sema/SemaDecl.cpp -+++ b/clang/lib/Sema/SemaDecl.cpp -@@ -4511,10 +4511,10 @@ - adjustDeclContextForDeclaratorDecl(New, Old); - - // Ensure the template parameters are compatible. -- if (NewTemplate && !TemplateParameterListsAreEqual( -- NewTemplate, NewTemplate->getTemplateParameters(), -- OldTemplate, OldTemplate->getTemplateParameters(), -- /*Complain=*/true, TPL_TemplateMatch)) -+ if (NewTemplate && -+ !TemplateParameterListsAreEqual(NewTemplate->getTemplateParameters(), -+ OldTemplate->getTemplateParameters(), -+ /*Complain=*/true, TPL_TemplateMatch)) - return New->setInvalidDecl(); - - // C++ [class.mem]p1: -@@ -4694,10 +4694,8 @@ - - // Keep a chain of previous declarations. - New->setPreviousDecl(Old); -- if (NewTemplate) { -- NewTemplate->mergePrevDecl(OldTemplate); -+ if (NewTemplate) - NewTemplate->setPreviousDecl(OldTemplate); -- } - - // Inherit access appropriately. - New->setAccess(Old->getAccess()); -@@ -7678,7 +7676,7 @@ - : SourceLocation(); - DeclResult Res = ActOnVarTemplateSpecialization( - S, D, TInfo, Previous, TemplateKWLoc, TemplateParams, SC, -- IsPartialSpecialization, IsMemberSpecialization); -+ IsPartialSpecialization); - if (Res.isInvalid()) - return nullptr; - NewVD = cast(Res.get()); -@@ -7697,10 +7695,6 @@ - VarTemplateDecl::Create(Context, DC, D.getIdentifierLoc(), Name, - TemplateParams, NewVD); - NewVD->setDescribedVarTemplate(NewTemplate); -- // If we are providing an explicit specialization of a static variable -- // template, make a note of that. -- if (IsMemberSpecialization) -- NewTemplate->setMemberSpecialization(); - } - - // If this decl has an auto type in need of deduction, make a note of the -@@ -8081,6 +8075,12 @@ - ? TPC_ClassTemplateMember - : TPC_VarTemplate)) - NewVD->setInvalidDecl(); -+ -+ // If we are providing an explicit specialization of a static variable -+ // template, make a note of that. -+ if (PrevVarTemplate && -+ PrevVarTemplate->getInstantiatedFromMemberTemplate()) -+ PrevVarTemplate->setMemberSpecialization(); - } - } - -@@ -9887,8 +9887,6 @@ - NewFD); - FunctionTemplate->setLexicalDeclContext(CurContext); - NewFD->setDescribedFunctionTemplate(FunctionTemplate); -- if (isMemberSpecialization) -- FunctionTemplate->setMemberSpecialization(); - - // For source fidelity, store the other template param lists. - if (TemplateParamLists.size() > 1) { -@@ -12046,7 +12044,10 @@ - - // If this is an explicit specialization of a member that is a function - // template, mark it as a member specialization. -- if (IsMemberSpecialization) { -+ if (IsMemberSpecialization && -+ NewTemplateDecl->getInstantiatedFromMemberTemplate()) { -+ NewTemplateDecl->setMemberSpecialization(); -+ assert(OldTemplateDecl->isMemberSpecialization()); - // Explicit specializations of a member template do not inherit deleted - // status from the parent member template that they are specializing. - if (OldFD->isDeleted()) { -@@ -17120,8 +17121,8 @@ - DeclResult Result = CheckClassTemplate( - S, TagSpec, TUK, KWLoc, SS, Name, NameLoc, Attrs, TemplateParams, - AS, ModulePrivateLoc, -- /*FriendLoc*/ SourceLocation(), TemplateParameterLists.drop_back(), -- isMemberSpecialization, SkipBody); -+ /*FriendLoc*/ SourceLocation(), TemplateParameterLists.size() - 1, -+ TemplateParameterLists.data(), SkipBody); - return Result.get(); - } else { - // The "template<>" header is extraneous. -diff -ruN --strip-trailing-cr a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp ---- a/clang/lib/Sema/SemaDeclCXX.cpp -+++ b/clang/lib/Sema/SemaDeclCXX.cpp -@@ -17410,8 +17410,8 @@ - return CheckClassTemplate(S, TagSpec, TagUseKind::Friend, TagLoc, SS, - Name, NameLoc, Attr, TemplateParams, AS_public, - /*ModulePrivateLoc=*/SourceLocation(), -- FriendLoc, TempParamLists.drop_back(), -- IsMemberSpecialization) -+ FriendLoc, TempParamLists.size() - 1, -+ TempParamLists.data()) - .get(); - } else { - // The "template<>" header is extraneous. -diff -ruN --strip-trailing-cr a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp ---- a/clang/lib/Sema/SemaTemplate.cpp -+++ b/clang/lib/Sema/SemaTemplate.cpp -@@ -1795,9 +1795,8 @@ - CXXScopeSpec &SS, IdentifierInfo *Name, SourceLocation NameLoc, - const ParsedAttributesView &Attr, TemplateParameterList *TemplateParams, - AccessSpecifier AS, SourceLocation ModulePrivateLoc, -- SourceLocation FriendLoc, -- ArrayRef OuterTemplateParamLists, -- bool IsMemberSpecialization, SkipBodyInfo *SkipBody) { -+ SourceLocation FriendLoc, unsigned NumOuterTemplateParamLists, -+ TemplateParameterList **OuterTemplateParamLists, SkipBodyInfo *SkipBody) { - assert(TemplateParams && TemplateParams->size() > 0 && - "No template parameters"); - assert(TUK != TagUseKind::Reference && -@@ -1985,6 +1984,19 @@ - } - - if (PrevClassTemplate) { -+ // Ensure that the template parameter lists are compatible. Skip this check -+ // for a friend in a dependent context: the template parameter list itself -+ // could be dependent. -+ if (!(TUK == TagUseKind::Friend && CurContext->isDependentContext()) && -+ !TemplateParameterListsAreEqual( -+ TemplateCompareNewDeclInfo(SemanticContext ? SemanticContext -+ : CurContext, -+ CurContext, KWLoc), -+ TemplateParams, PrevClassTemplate, -+ PrevClassTemplate->getTemplateParameters(), /*Complain=*/true, -+ TPL_TemplateMatch)) -+ return true; -+ - // C++ [temp.class]p4: - // In a redeclaration, partial specialization, explicit - // specialization or explicit instantiation of a class template, -@@ -1999,6 +2011,30 @@ - Diag(PrevRecordDecl->getLocation(), diag::note_previous_use); - Kind = PrevRecordDecl->getTagKind(); - } -+ -+ // Check for redefinition of this class template. -+ if (TUK == TagUseKind::Definition) { -+ if (TagDecl *Def = PrevRecordDecl->getDefinition()) { -+ // If we have a prior definition that is not visible, treat this as -+ // simply making that previous definition visible. -+ NamedDecl *Hidden = nullptr; -+ if (SkipBody && !hasVisibleDefinition(Def, &Hidden)) { -+ SkipBody->ShouldSkip = true; -+ SkipBody->Previous = Def; -+ auto *Tmpl = cast(Hidden)->getDescribedClassTemplate(); -+ assert(Tmpl && "original definition of a class template is not a " -+ "class template?"); -+ makeMergedDefinitionVisible(Hidden); -+ makeMergedDefinitionVisible(Tmpl); -+ } else { -+ Diag(NameLoc, diag::err_redefinition) << Name; -+ Diag(Def->getLocation(), diag::note_previous_definition); -+ // FIXME: Would it make sense to try to "forget" the previous -+ // definition, as part of error recovery? -+ return true; -+ } -+ } -+ } - } else if (PrevDecl) { - // C++ [temp]p5: - // A class template shall not have the same name as any other -@@ -2010,6 +2046,23 @@ - return true; - } - -+ // Check the template parameter list of this declaration, possibly -+ // merging in the template parameter list from the previous class -+ // template declaration. Skip this check for a friend in a dependent -+ // context, because the template parameter list might be dependent. -+ if (!(TUK == TagUseKind::Friend && CurContext->isDependentContext()) && -+ CheckTemplateParameterList( -+ TemplateParams, -+ PrevClassTemplate ? GetTemplateParameterList(PrevClassTemplate) -+ : nullptr, -+ (SS.isSet() && SemanticContext && SemanticContext->isRecord() && -+ SemanticContext->isDependentContext()) -+ ? TPC_ClassTemplateMember -+ : TUK == TagUseKind::Friend ? TPC_FriendClassTemplate -+ : TPC_ClassTemplate, -+ SkipBody)) -+ Invalid = true; -+ - if (SS.isSet()) { - // If the name of the template was qualified, we must be defining the - // template out-of-line. -@@ -2036,8 +2089,10 @@ - PrevClassTemplate->getTemplatedDecl() : nullptr, - /*DelayTypeCreation=*/true); - SetNestedNameSpecifier(*this, NewClass, SS); -- if (!OuterTemplateParamLists.empty()) -- NewClass->setTemplateParameterListsInfo(Context, OuterTemplateParamLists); -+ if (NumOuterTemplateParamLists > 0) -+ NewClass->setTemplateParameterListsInfo( -+ Context, -+ llvm::ArrayRef(OuterTemplateParamLists, NumOuterTemplateParamLists)); - - // Add alignment attributes if necessary; these attributes are checked when - // the ASTContext lays out the structure. -@@ -2050,10 +2105,7 @@ - = ClassTemplateDecl::Create(Context, SemanticContext, NameLoc, - DeclarationName(Name), TemplateParams, - NewClass); -- // If we are providing an explicit specialization of a member that is a -- // class template, make a note of that. -- if (IsMemberSpecialization) -- NewTemplate->setMemberSpecialization(); -+ - if (ShouldAddRedecl) - NewTemplate->setPreviousDecl(PrevClassTemplate); - -@@ -2068,6 +2120,12 @@ - assert(T->isDependentType() && "Class template type is not dependent?"); - (void)T; - -+ // If we are providing an explicit specialization of a member that is a -+ // class template, make a note of that. -+ if (PrevClassTemplate && -+ PrevClassTemplate->getInstantiatedFromMemberTemplate()) -+ PrevClassTemplate->setMemberSpecialization(); -+ - // Set the access specifier. - if (!Invalid && TUK != TagUseKind::Friend && - NewTemplate->getDeclContext()->isRecord()) -@@ -2077,62 +2135,8 @@ - NewClass->setLexicalDeclContext(CurContext); - NewTemplate->setLexicalDeclContext(CurContext); - -- // Ensure that the template parameter lists are compatible. Skip this check -- // for a friend in a dependent context: the template parameter list itself -- // could be dependent. -- if (ShouldAddRedecl && PrevClassTemplate && -- !TemplateParameterListsAreEqual( -- NewTemplate, TemplateParams, PrevClassTemplate, -- PrevClassTemplate->getTemplateParameters(), -- /*Complain=*/true, TPL_TemplateMatch)) -- return true; -- -- // Check the template parameter list of this declaration, possibly -- // merging in the template parameter list from the previous class -- // template declaration. Skip this check for a friend in a dependent -- // context, because the template parameter list might be dependent. -- if (ShouldAddRedecl && -- CheckTemplateParameterList( -- TemplateParams, -- PrevClassTemplate ? PrevClassTemplate->getTemplateParameters() -- : nullptr, -- (SS.isSet() && SemanticContext && SemanticContext->isRecord() && -- SemanticContext->isDependentContext()) -- ? TPC_ClassTemplateMember -- : TUK == TagUseKind::Friend ? TPC_FriendClassTemplate -- : TPC_ClassTemplate, -- SkipBody)) -- Invalid = true; -- -- if (TUK == TagUseKind::Definition) { -- if (PrevClassTemplate) { -- // Check for redefinition of this class template. -- if (TagDecl *Def = -- PrevClassTemplate->getTemplatedDecl()->getDefinition()) { -- // If we have a prior definition that is not visible, treat this as -- // simply making that previous definition visible. -- NamedDecl *Hidden = nullptr; -- if (SkipBody && !hasVisibleDefinition(Def, &Hidden)) { -- SkipBody->ShouldSkip = true; -- SkipBody->Previous = Def; -- auto *Tmpl = cast(Hidden)->getDescribedClassTemplate(); -- assert(Tmpl && "original definition of a class template is not a " -- "class template?"); -- makeMergedDefinitionVisible(Hidden); -- makeMergedDefinitionVisible(Tmpl); -- } else { -- Diag(NameLoc, diag::err_redefinition) << Name; -- Diag(Def->getLocation(), diag::note_previous_definition); -- // FIXME: Would it make sense to try to "forget" the previous -- // definition, as part of error recovery? -- return true; -- } -- } -- } -- -- if (!SkipBody || !SkipBody->ShouldSkip) -- NewClass->startDefinition(); -- } -+ if (TUK == TagUseKind::Definition && (!SkipBody || !SkipBody->ShouldSkip)) -+ NewClass->startDefinition(); - - ProcessDeclAttributeList(S, NewClass, Attr); - ProcessAPINotes(NewClass); -@@ -4129,8 +4133,7 @@ - DeclResult Sema::ActOnVarTemplateSpecialization( - Scope *S, Declarator &D, TypeSourceInfo *DI, LookupResult &Previous, - SourceLocation TemplateKWLoc, TemplateParameterList *TemplateParams, -- StorageClass SC, bool IsPartialSpecialization, -- bool IsMemberSpecialization) { -+ StorageClass SC, bool IsPartialSpecialization) { - // D must be variable template id. - assert(D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId && - "Variable template specialization is declared with a template id."); -@@ -4248,16 +4251,17 @@ - Context, VarTemplate->getDeclContext(), TemplateKWLoc, - TemplateNameLoc, TemplateParams, VarTemplate, DI->getType(), DI, SC, - CanonicalConverted); -- // If we are providing an explicit specialization of a member variable -- // template specialization, make a note of that. -- if (IsMemberSpecialization) -- Partial->setMemberSpecialization(); - Partial->setTemplateArgsAsWritten(TemplateArgs); - - if (!PrevPartial) - VarTemplate->AddPartialSpecialization(Partial, InsertPos); - Specialization = Partial; - -+ // If we are providing an explicit specialization of a member variable -+ // template specialization, make a note of that. -+ if (PrevPartial && PrevPartial->getInstantiatedFromMember()) -+ PrevPartial->setMemberSpecialization(); -+ - CheckTemplatePartialSpecialization(Partial); - } else { - // Create a new class template specialization declaration node for -@@ -5784,7 +5788,9 @@ - - MultiLevelTemplateArgumentList MLTAL = getTemplateInstantiationArgs( - Template, NewContext, /*Final=*/false, CanonicalConverted, -- /*RelativeToPrimary=*/true, /*ForConceptInstantiation=*/true); -+ /*RelativeToPrimary=*/true, -+ /*Pattern=*/nullptr, -+ /*ForConceptInstantiation=*/true); - if (EnsureTemplateArgumentListConstraints( - Template, MLTAL, - SourceRange(TemplateLoc, TemplateArgs.getRAngleLoc()))) { -@@ -8484,8 +8490,8 @@ - S, TagSpec, TUK, KWLoc, SS, ClassTemplate->getIdentifier(), - TemplateNameLoc, Attr, TemplateParams, AS_none, - /*ModulePrivateLoc=*/SourceLocation(), -- /*FriendLoc*/ SourceLocation(), TemplateParameterLists.drop_back(), -- isMemberSpecialization); -+ /*FriendLoc*/ SourceLocation(), TemplateParameterLists.size() - 1, -+ TemplateParameterLists.data()); - } - - // Create a new class template partial specialization declaration node. -@@ -8495,11 +8501,6 @@ - ClassTemplatePartialSpecializationDecl::Create( - Context, Kind, DC, KWLoc, TemplateNameLoc, TemplateParams, - ClassTemplate, CanonicalConverted, CanonType, PrevPartial); -- -- // If we are providing an explicit specialization of a member class -- // template specialization, make a note of that. -- if (isMemberSpecialization) -- Partial->setMemberSpecialization(); - Partial->setTemplateArgsAsWritten(TemplateArgs); - SetNestedNameSpecifier(*this, Partial, SS); - if (TemplateParameterLists.size() > 1 && SS.isSet()) { -@@ -8511,6 +8512,11 @@ - ClassTemplate->AddPartialSpecialization(Partial, InsertPos); - Specialization = Partial; - -+ // If we are providing an explicit specialization of a member class -+ // template specialization, make a note of that. -+ if (PrevPartial && PrevPartial->getInstantiatedFromMember()) -+ PrevPartial->setMemberSpecialization(); -+ - CheckTemplatePartialSpecialization(Partial); - } else { - // Create a new class template specialization declaration node for -@@ -9110,8 +9116,8 @@ - TemplateDeductionInfo Info(FailedCandidates.getLocation()); - FunctionDecl *Specialization = nullptr; - if (TemplateDeductionResult TDK = DeduceTemplateArguments( -- FunTmpl, ExplicitTemplateArgs ? &Args : nullptr, FT, -- Specialization, Info); -+ cast(FunTmpl->getFirstDecl()), -+ ExplicitTemplateArgs ? &Args : nullptr, FT, Specialization, Info); - TDK != TemplateDeductionResult::Success) { - // Template argument deduction failed; record why it failed, so - // that we can provide nifty diagnostics. -@@ -11309,8 +11315,8 @@ - - template - void checkTemplate(TemplDecl *TD) { -- if (TD->getMostRecentDecl()->isMemberSpecialization()) { -- if (!CheckMemberSpecialization(TD->getMostRecentDecl())) -+ if (TD->isMemberSpecialization()) { -+ if (!CheckMemberSpecialization(TD)) - diagnose(TD->getMostRecentDecl(), false); - } - } -diff -ruN --strip-trailing-cr a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp ---- a/clang/lib/Sema/SemaTemplateDeduction.cpp -+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp -@@ -3139,6 +3139,20 @@ - struct IsPartialSpecialization { - static constexpr bool value = true; - }; -+template -+static bool DeducedArgsNeedReplacement(TemplateDeclT *Template) { -+ return false; -+} -+template <> -+bool DeducedArgsNeedReplacement( -+ VarTemplatePartialSpecializationDecl *Spec) { -+ return !Spec->isClassScopeExplicitSpecialization(); -+} -+template <> -+bool DeducedArgsNeedReplacement( -+ ClassTemplatePartialSpecializationDecl *Spec) { -+ return !Spec->isClassScopeExplicitSpecialization(); -+} - - template - static TemplateDeductionResult -@@ -3149,10 +3163,23 @@ - llvm::SmallVector AssociatedConstraints; - Template->getAssociatedConstraints(AssociatedConstraints); - -+ 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=*/CanonicalDeducedArgs, /*RelativeToPrimary=*/true, -- /*ForConstraintInstantiation=*/true); -+ Template, Template->getDeclContext(), /*Final=*/false, Innermost, -+ /*RelativeToPrimary=*/true, /*Pattern=*/ -+ nullptr, /*ForConstraintInstantiation=*/true); -+ -+ // getTemplateInstantiationArgs picks up the non-deduced version of the -+ // 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 (!Innermost) -+ MLTAL.replaceInnermostTemplateArguments(Template, CanonicalDeducedArgs); - - if (S.CheckConstraintSatisfaction(Template, AssociatedConstraints, MLTAL, - Info.getLocation(), -diff -ruN --strip-trailing-cr a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp ---- a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp -+++ b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp -@@ -765,7 +765,7 @@ - } - // Template arguments used to transform the template arguments in - // DeducedResults. -- SmallVector InnerArgsForBuildingRC( -+ SmallVector TemplateArgsForBuildingRC( - F->getTemplateParameters()->size()); - // Transform the transformed template args - MultiLevelTemplateArgumentList Args; -@@ -778,30 +778,33 @@ - NamedDecl *TP = F->getTemplateParameters()->getParam(Index); - MultiLevelTemplateArgumentList Args; - Args.setKind(TemplateSubstitutionKind::Rewrite); -- Args.addOuterTemplateArguments(InnerArgsForBuildingRC); -+ Args.addOuterTemplateArguments(TemplateArgsForBuildingRC); - // Rebuild the template parameter with updated depth and index. - NamedDecl *NewParam = - transformTemplateParameter(SemaRef, F->getDeclContext(), TP, Args, - /*NewIndex=*/FirstUndeducedParamIdx, - getDepthAndIndex(TP).first + AdjustDepth); - FirstUndeducedParamIdx += 1; -- assert(InnerArgsForBuildingRC[Index].isNull()); -- InnerArgsForBuildingRC[Index] = Context.getInjectedTemplateArg(NewParam); -+ assert(TemplateArgsForBuildingRC[Index].isNull()); -+ TemplateArgsForBuildingRC[Index] = -+ Context.getInjectedTemplateArg(NewParam); - continue; - } - TemplateArgumentLoc Input = - SemaRef.getTrivialTemplateArgumentLoc(D, QualType(), SourceLocation{}); - TemplateArgumentLoc Output; - if (!SemaRef.SubstTemplateArgument(Input, Args, Output)) { -- assert(InnerArgsForBuildingRC[Index].isNull() && -+ assert(TemplateArgsForBuildingRC[Index].isNull() && - "InstantiatedArgs must be null before setting"); -- InnerArgsForBuildingRC[Index] = Output.getArgument(); -+ TemplateArgsForBuildingRC[Index] = Output.getArgument(); - } - } - -- // A list of template arguments for transforming the require-clause using -- // the transformed template arguments as the template argument list of F. -- // -+ // A list of template arguments for transforming the require-clause of F. -+ // It must contain the entire set of template argument lists. -+ MultiLevelTemplateArgumentList ArgsForBuildingRC; -+ ArgsForBuildingRC.setKind(clang::TemplateSubstitutionKind::Rewrite); -+ ArgsForBuildingRC.addOuterTemplateArguments(TemplateArgsForBuildingRC); - // For 2), if the underlying deduction guide F is nested in a class template, - // we need the entire template argument list, as the constraint AST in the - // require-clause of F remains completely uninstantiated. -@@ -824,15 +827,25 @@ - // - The occurrence of U in the function parameter is [depth:0, index:0] - // - The template parameter of U is [depth:0, index:0] - // -+ // We add the outer template arguments which is [int] to the multi-level arg -+ // list to ensure that the occurrence U in `C` will be replaced with int -+ // during the substitution. -+ // - // NOTE: The underlying deduction guide F is instantiated -- either from an - // explicitly-written deduction guide member, or from a constructor. -- MultiLevelTemplateArgumentList ArgsForBuildingRC = -- SemaRef.getTemplateInstantiationArgs(F, F->getLexicalDeclContext(), -- /*Final=*/false, -- /*Innermost=*/InnerArgsForBuildingRC, -- /*RelativeToPrimary=*/true, -- /*ForConstraintInstantiation=*/true); -- ArgsForBuildingRC.setKind(clang::TemplateSubstitutionKind::Rewrite); -+ // getInstantiatedFromMemberTemplate() can only handle the former case, so we -+ // check the DeclContext kind. -+ if (F->getLexicalDeclContext()->getDeclKind() == -+ clang::Decl::ClassTemplateSpecialization) { -+ auto OuterLevelArgs = SemaRef.getTemplateInstantiationArgs( -+ F, F->getLexicalDeclContext(), -+ /*Final=*/false, /*Innermost=*/std::nullopt, -+ /*RelativeToPrimary=*/true, -+ /*Pattern=*/nullptr, -+ /*ForConstraintInstantiation=*/true); -+ for (auto It : OuterLevelArgs) -+ ArgsForBuildingRC.addOuterTemplateArguments(It.Args); -+ } - - ExprResult E = SemaRef.SubstExpr(RC, ArgsForBuildingRC); - if (E.isInvalid()) -diff -ruN --strip-trailing-cr a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp ---- a/clang/lib/Sema/SemaTemplateInstantiate.cpp -+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp -@@ -52,6 +52,38 @@ - //===----------------------------------------------------------------------===/ - - namespace { -+namespace TemplateInstArgsHelpers { -+struct Response { -+ const Decl *NextDecl = nullptr; -+ bool IsDone = false; -+ bool ClearRelativeToPrimary = true; -+ static Response Done() { -+ Response R; -+ R.IsDone = true; -+ return R; -+ } -+ static Response ChangeDecl(const Decl *ND) { -+ Response R; -+ R.NextDecl = ND; -+ return R; -+ } -+ static Response ChangeDecl(const DeclContext *Ctx) { -+ Response R; -+ R.NextDecl = Decl::castFromDeclContext(Ctx); -+ return R; -+ } -+ -+ static Response UseNextDecl(const Decl *CurDecl) { -+ return ChangeDecl(CurDecl->getDeclContext()); -+ } -+ -+ static Response DontClearRelativeToPrimaryNextDecl(const Decl *CurDecl) { -+ Response R = Response::UseNextDecl(CurDecl); -+ R.ClearRelativeToPrimary = false; -+ return R; -+ } -+}; -+ - // Retrieve the primary template for a lambda call operator. It's - // unfortunate that we only have the mappings of call operators rather - // than lambda classes. -@@ -139,398 +171,379 @@ - .TraverseType(Underlying); - } - --struct TemplateInstantiationArgumentCollecter -- : DeclVisitor { -- Sema &S; -- MultiLevelTemplateArgumentList &Result; -- std::optional> Innermost; -- bool RelativeToPrimary; -- bool ForConstraintInstantiation; -- -- TemplateInstantiationArgumentCollecter( -- Sema &S, MultiLevelTemplateArgumentList &Result, -- std::optional> Innermost, -- bool RelativeToPrimary, bool ForConstraintInstantiation) -- : S(S), Result(Result), Innermost(Innermost), -- RelativeToPrimary(RelativeToPrimary), -- ForConstraintInstantiation(ForConstraintInstantiation) {} -- -- Decl *Done() { return nullptr; } -- -- Decl *ChangeDecl(const Decl *D) { -- RelativeToPrimary = false; -- return const_cast(D); -- } -- -- Decl *ChangeDecl(const DeclContext *DC) { -- return ChangeDecl(Decl::castFromDeclContext(DC)); -- } -- -- Decl *UseNextDecl(const Decl *D) { return ChangeDecl(D->getDeclContext()); } -- -- void AddInnermostTemplateArguments(const Decl *D) { -- assert(Innermost); -- Result.addOuterTemplateArguments(const_cast(D), *Innermost, -- /*Final=*/false); -- Innermost.reset(); -- } -- -- void AddOuterTemplateArguments(const Decl *D, ArrayRef Args, -- bool Final) { -- Result.addOuterTemplateArguments(const_cast(D), Args, Final); -- } -- -- Decl *VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *TTPD) { -- if (Innermost) -- AddInnermostTemplateArguments(TTPD); -- else if (ForConstraintInstantiation) -- AddOuterTemplateArguments(nullptr, std::nullopt, /*Final=*/false); -- -- for (unsigned Depth = TTPD->getDepth() + 1; Depth--;) -- AddOuterTemplateArguments(nullptr, std::nullopt, /*Final=*/false); -- -- return Done(); -- } -- -- Decl *VisitFunctionTemplateDecl(FunctionTemplateDecl *FTD) { -- assert( -- (ForConstraintInstantiation || Result.getNumSubstitutedLevels() == 0) && -- "outer template not instantiated?"); -- -- if (Innermost) -- AddInnermostTemplateArguments(FTD); -- else if (ForConstraintInstantiation) -- AddOuterTemplateArguments(FTD, FTD->getInjectedTemplateArgs(S.Context), -- /*Final=*/false); -- -- if (FTD->isMemberSpecialization()) -- return Done(); -- -- if (FTD->getFriendObjectKind()) -- return ChangeDecl(FTD->getLexicalDeclContext()); -- return UseNextDecl(FTD); -- } -- -- Decl *VisitVarTemplateDecl(VarTemplateDecl *VTD) { -- assert( -- (ForConstraintInstantiation || Result.getNumSubstitutedLevels() == 0) && -- "outer template not instantiated?"); -- -- if (Innermost) -- AddInnermostTemplateArguments(VTD); -- else if (ForConstraintInstantiation) -- AddOuterTemplateArguments(VTD, VTD->getInjectedTemplateArgs(S.Context), -- /*Final=*/false); -- -- if (VTD->isMemberSpecialization()) -- return Done(); -- -- return UseNextDecl(VTD); -- } -- -- Decl *VisitVarTemplatePartialSpecializationDecl( -- VarTemplatePartialSpecializationDecl *VTPSD) { -- assert( -- (ForConstraintInstantiation || Result.getNumSubstitutedLevels() == 0) && -- "outer template not instantiated?"); -- -- if (Innermost) -- AddInnermostTemplateArguments(VTPSD); -- else if (ForConstraintInstantiation) -- AddOuterTemplateArguments(VTPSD, -- VTPSD->getInjectedTemplateArgs(S.Context), -- /*Final=*/false); -- -- if (VTPSD->isMemberSpecialization()) -- return Done(); -- -- return UseNextDecl(VTPSD); -- } -- -- Decl *VisitClassTemplateDecl(ClassTemplateDecl *CTD) { -- assert( -- (ForConstraintInstantiation || Result.getNumSubstitutedLevels() == 0) && -- "outer template not instantiated?"); -- -- if (Innermost) -- AddInnermostTemplateArguments(CTD); -- else if (ForConstraintInstantiation) -- AddOuterTemplateArguments(CTD, CTD->getInjectedTemplateArgs(S.Context), -- /*Final=*/false); -- -- if (CTD->isMemberSpecialization()) -- return Done(); -- -- if (CTD->getFriendObjectKind()) -- return ChangeDecl(CTD->getLexicalDeclContext()); -- return UseNextDecl(CTD); -- } -- -- Decl *VisitClassTemplatePartialSpecializationDecl( -- ClassTemplatePartialSpecializationDecl *CTPSD) { -- assert( -- (ForConstraintInstantiation || Result.getNumSubstitutedLevels() == 0) && -- "outer template not instantiated?"); -- -- if (Innermost) -- AddInnermostTemplateArguments(CTPSD); -- else if (ForConstraintInstantiation) -- AddOuterTemplateArguments(CTPSD, -- CTPSD->getInjectedTemplateArgs(S.Context), -- /*Final=*/false); -+// Add template arguments from a variable template instantiation. -+Response -+HandleVarTemplateSpec(const VarTemplateSpecializationDecl *VarTemplSpec, -+ MultiLevelTemplateArgumentList &Result, -+ bool SkipForSpecialization) { -+ // For a class-scope explicit specialization, there are no template arguments -+ // at this level, but there may be enclosing template arguments. -+ if (VarTemplSpec->isClassScopeExplicitSpecialization()) -+ return Response::DontClearRelativeToPrimaryNextDecl(VarTemplSpec); -+ -+ // We're done when we hit an explicit specialization. -+ if (VarTemplSpec->getSpecializationKind() == TSK_ExplicitSpecialization && -+ !isa(VarTemplSpec)) -+ return Response::Done(); -+ -+ // If this variable template specialization was instantiated from a -+ // specialized member that is a variable template, we're done. -+ assert(VarTemplSpec->getSpecializedTemplate() && "No variable template?"); -+ llvm::PointerUnion -+ Specialized = VarTemplSpec->getSpecializedTemplateOrPartial(); -+ if (VarTemplatePartialSpecializationDecl *Partial = -+ Specialized.dyn_cast()) { -+ if (!SkipForSpecialization) -+ Result.addOuterTemplateArguments( -+ Partial, VarTemplSpec->getTemplateInstantiationArgs().asArray(), -+ /*Final=*/false); -+ if (Partial->isMemberSpecialization()) -+ return Response::Done(); -+ } else { -+ VarTemplateDecl *Tmpl = Specialized.get(); -+ if (!SkipForSpecialization) -+ Result.addOuterTemplateArguments( -+ Tmpl, VarTemplSpec->getTemplateInstantiationArgs().asArray(), -+ /*Final=*/false); -+ if (Tmpl->isMemberSpecialization()) -+ return Response::Done(); -+ } -+ return Response::DontClearRelativeToPrimaryNextDecl(VarTemplSpec); -+} -+ -+// If we have a template template parameter with translation unit context, -+// then we're performing substitution into a default template argument of -+// this template template parameter before we've constructed the template -+// that will own this template template parameter. In this case, we -+// use empty template parameter lists for all of the outer templates -+// to avoid performing any substitutions. -+Response -+HandleDefaultTempArgIntoTempTempParam(const TemplateTemplateParmDecl *TTP, -+ MultiLevelTemplateArgumentList &Result) { -+ for (unsigned I = 0, N = TTP->getDepth() + 1; I != N; ++I) -+ Result.addOuterTemplateArguments(std::nullopt); -+ return Response::Done(); -+} -+ -+Response HandlePartialClassTemplateSpec( -+ const ClassTemplatePartialSpecializationDecl *PartialClassTemplSpec, -+ MultiLevelTemplateArgumentList &Result, bool SkipForSpecialization) { -+ if (!SkipForSpecialization) -+ Result.addOuterRetainedLevels(PartialClassTemplSpec->getTemplateDepth()); -+ return Response::Done(); -+} -+ -+// Add template arguments from a class template instantiation. -+Response -+HandleClassTemplateSpec(const ClassTemplateSpecializationDecl *ClassTemplSpec, -+ MultiLevelTemplateArgumentList &Result, -+ bool SkipForSpecialization) { -+ if (!ClassTemplSpec->isClassScopeExplicitSpecialization()) { -+ // We're done when we hit an explicit specialization. -+ if (ClassTemplSpec->getSpecializationKind() == TSK_ExplicitSpecialization && -+ !isa(ClassTemplSpec)) -+ return Response::Done(); -+ -+ if (!SkipForSpecialization) -+ Result.addOuterTemplateArguments( -+ const_cast(ClassTemplSpec), -+ ClassTemplSpec->getTemplateInstantiationArgs().asArray(), -+ /*Final=*/false); - -- if (CTPSD->isMemberSpecialization()) -- return Done(); -+ // If this class template specialization was instantiated from a -+ // specialized member that is a class template, we're done. -+ assert(ClassTemplSpec->getSpecializedTemplate() && "No class template?"); -+ if (ClassTemplSpec->getSpecializedTemplate()->isMemberSpecialization()) -+ return Response::Done(); -+ -+ // If this was instantiated from a partial template specialization, we need -+ // to get the next level of declaration context from the partial -+ // specialization, as the ClassTemplateSpecializationDecl's -+ // DeclContext/LexicalDeclContext will be for the primary template. -+ if (auto *InstFromPartialTempl = -+ ClassTemplSpec->getSpecializedTemplateOrPartial() -+ .dyn_cast()) -+ return Response::ChangeDecl( -+ InstFromPartialTempl->getLexicalDeclContext()); -+ } -+ return Response::UseNextDecl(ClassTemplSpec); -+} -+ -+Response HandleFunction(Sema &SemaRef, const FunctionDecl *Function, -+ MultiLevelTemplateArgumentList &Result, -+ const FunctionDecl *Pattern, bool RelativeToPrimary, -+ bool ForConstraintInstantiation, -+ bool ForDefaultArgumentSubstitution) { -+ // Add template arguments from a function template specialization. -+ if (!RelativeToPrimary && -+ Function->getTemplateSpecializationKindForInstantiation() == -+ TSK_ExplicitSpecialization) -+ return Response::Done(); -+ -+ if (!RelativeToPrimary && -+ Function->getTemplateSpecializationKind() == TSK_ExplicitSpecialization) { -+ // This is an implicit instantiation of an explicit specialization. We -+ // don't get any template arguments from this function but might get -+ // some from an enclosing template. -+ return Response::UseNextDecl(Function); -+ } else if (const TemplateArgumentList *TemplateArgs = -+ Function->getTemplateSpecializationArgs()) { -+ // Add the template arguments for this specialization. -+ Result.addOuterTemplateArguments(const_cast(Function), -+ TemplateArgs->asArray(), -+ /*Final=*/false); - -- return UseNextDecl(CTPSD); -- } -+ if (RelativeToPrimary && -+ (Function->getTemplateSpecializationKind() == -+ TSK_ExplicitSpecialization || -+ (Function->getFriendObjectKind() && -+ !Function->getPrimaryTemplate()->getFriendObjectKind()))) -+ return Response::UseNextDecl(Function); -+ -+ // If this function was instantiated from a specialized member that is -+ // a function template, we're done. -+ assert(Function->getPrimaryTemplate() && "No function template?"); -+ if (!ForDefaultArgumentSubstitution && -+ Function->getPrimaryTemplate()->isMemberSpecialization()) -+ return Response::Done(); -+ -+ // If this function is a generic lambda specialization, we are done. -+ if (!ForConstraintInstantiation && -+ isGenericLambdaCallOperatorOrStaticInvokerSpecialization(Function)) -+ return Response::Done(); - -- Decl *VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *TATD) { -+ } else if (Function->getDescribedFunctionTemplate()) { - assert( - (ForConstraintInstantiation || Result.getNumSubstitutedLevels() == 0) && -- "outer template not instantiated?"); -- if (Innermost) -- AddInnermostTemplateArguments(TATD); -- else if (ForConstraintInstantiation) -- AddOuterTemplateArguments(TATD, TATD->getInjectedTemplateArgs(S.Context), -- /*Final=*/false); -- -- return UseNextDecl(TATD); -+ "Outer template not instantiated?"); - } -- -- Decl *VisitConceptDecl(ConceptDecl *CD) { -- assert( -- (ForConstraintInstantiation || Result.getNumSubstitutedLevels() == 0) && -- "outer template not instantiated?"); -- if (Innermost) -- AddInnermostTemplateArguments(CD); -- -- return UseNextDecl(CD); -- } -- -- Decl *VisitFunctionDecl(FunctionDecl *FD) { -- assert(!FD->getDescribedFunctionTemplate() && -- "not for templated declarations"); -- -- if (!RelativeToPrimary) { -- // Add template arguments from a function template specialization. -- if (const MemberSpecializationInfo *MSI = -- FD->getMemberSpecializationInfo(); -- MSI && -- MSI->getTemplateSpecializationKind() == TSK_ExplicitSpecialization) -- return Done(); -- -- // This is an implicit instantiation of an explicit specialization. We -- // don't get any template arguments from this function but might get -- // some from an enclosing template. -- if (FD->getTemplateSpecializationKind() == TSK_ExplicitSpecialization) -- return UseNextDecl(FD); -- } -- -- if (const TemplateArgumentList *TemplateArgs = -- FD->getTemplateSpecializationArgs()) { -- // Add the template arguments for this specialization. -- if (Innermost) -- AddInnermostTemplateArguments(FD); -- else -- AddOuterTemplateArguments(FD, TemplateArgs->asArray(), /*Final=*/false); -- -- if (FD->getTemplateSpecializationKind() == TSK_ExplicitSpecialization || -- (FD->getFriendObjectKind() && -- !FD->getPrimaryTemplate()->getFriendObjectKind())) -- return UseNextDecl(FD); -- -- // If this function was instantiated from a specialized member that is -- // a function template, we're done. -- assert(FD->getPrimaryTemplate() && "No function template?"); -- if (FD->getPrimaryTemplate()->isMemberSpecialization()) -- return Done(); -- -- // If this function is a generic lambda specialization, we are done. -- if (!ForConstraintInstantiation && -- isGenericLambdaCallOperatorOrStaticInvokerSpecialization(FD)) -- return Done(); -- } -- -- // If this is a friend or local declaration and it declares an entity at -- // namespace scope, take arguments from its lexical parent -- // instead of its semantic parent, unless of course the pattern we're -- // instantiating actually comes from the file's context! -- if ((FD->getFriendObjectKind() || FD->isLocalExternDecl()) && -- FD->getNonTransparentDeclContext()->isFileContext()) { -- return ChangeDecl(FD->getLexicalDeclContext()); -- } -- -- if (ForConstraintInstantiation && FD->getFriendObjectKind()) -- return ChangeDecl(FD->getLexicalDeclContext()); -- return UseNextDecl(FD); -- } -- -- Decl *VisitCXXRecordDecl(CXXRecordDecl *RD) { -- assert(!RD->getDescribedClassTemplate() && -- "not for templated declarations"); -- -- if (const MemberSpecializationInfo *MSI = RD->getMemberSpecializationInfo(); -- MSI && -- MSI->getTemplateSpecializationKind() == TSK_ExplicitSpecialization) -- return Done(); -- -- if (ForConstraintInstantiation && RD->getFriendObjectKind() && -- RD->getNonTransparentDeclContext()->isFileContext()) { -- return ChangeDecl(RD->getLexicalDeclContext()); -- } -- -- // This is to make sure we pick up the VarTemplateSpecializationDecl or the -- // TypeAliasTemplateDecl that this lambda is defined inside of. -- if (RD->isLambda()) { -- if (Decl *LCD = RD->getLambdaContextDecl()) -- return ChangeDecl(LCD); -- // Retrieve the template arguments for a using alias declaration. -- // This is necessary for constraint checking, since we always keep -- // constraints relative to the primary template. -- if (auto TypeAlias = getEnclosingTypeAliasTemplateDecl(S); -- ForConstraintInstantiation && TypeAlias) { -- if (isLambdaEnclosedByTypeAliasDecl(RD->getLambdaCallOperator(), -- TypeAlias.PrimaryTypeAliasDecl)) { -- AddOuterTemplateArguments(TypeAlias.Template, -- TypeAlias.AssociatedTemplateArguments, -- /*Final=*/false); -- // Visit the parent of the current type alias declaration rather than -- // the lambda thereof. -- // E.g., in the following example: -- // struct S { -- // template using T = decltype([] {} ()); -+ // If this is a friend or local declaration and it declares an entity at -+ // namespace scope, take arguments from its lexical parent -+ // instead of its semantic parent, unless of course the pattern we're -+ // instantiating actually comes from the file's context! -+ if ((Function->getFriendObjectKind() || Function->isLocalExternDecl()) && -+ Function->getNonTransparentDeclContext()->isFileContext() && -+ (!Pattern || !Pattern->getLexicalDeclContext()->isFileContext())) { -+ return Response::ChangeDecl(Function->getLexicalDeclContext()); -+ } -+ -+ if (ForConstraintInstantiation && Function->getFriendObjectKind()) -+ return Response::ChangeDecl(Function->getLexicalDeclContext()); -+ return Response::UseNextDecl(Function); -+} -+ -+Response HandleFunctionTemplateDecl(Sema &SemaRef, -+ const FunctionTemplateDecl *FTD, -+ MultiLevelTemplateArgumentList &Result) { -+ if (!isa(FTD->getDeclContext())) { -+ Result.addOuterTemplateArguments( -+ const_cast(FTD), -+ const_cast(FTD)->getInjectedTemplateArgs( -+ SemaRef.Context), -+ /*Final=*/false); -+ -+ NestedNameSpecifier *NNS = FTD->getTemplatedDecl()->getQualifier(); -+ -+ while (const Type *Ty = NNS ? NNS->getAsType() : nullptr) { -+ if (NNS->isInstantiationDependent()) { -+ if (const auto *TSTy = Ty->getAs()) { -+ ArrayRef Arguments = TSTy->template_arguments(); -+ // Prefer template arguments from the injected-class-type if possible. -+ // For example, -+ // ```cpp -+ // template struct S { -+ // template void foo(); - // }; -- // void foo() { -- // S::T var; -- // } -- // The instantiated lambda expression (which we're visiting at 'var') -- // has a function DeclContext 'foo' rather than the Record DeclContext -- // S. This seems to be an oversight to me that we may want to set a -- // Sema Context from the CXXScopeSpec before substituting into T. -- return ChangeDecl(TypeAlias.Template->getDeclContext()); -+ // template template -+ // ^^^^^^^^^^^^^ InjectedTemplateArgs -+ // They're of kind TemplateArgument::Pack, not of -+ // TemplateArgument::Type. -+ // void S::foo() {} -+ // ^^^^^^^ -+ // TSTy->template_arguments() (which are of PackExpansionType) -+ // ``` -+ // This meets the contract in -+ // TreeTransform::TryExpandParameterPacks that the template arguments -+ // for unexpanded parameters should be of a Pack kind. -+ if (TSTy->isCurrentInstantiation()) { -+ auto *RD = TSTy->getCanonicalTypeInternal()->getAsCXXRecordDecl(); -+ if (ClassTemplateDecl *CTD = RD->getDescribedClassTemplate()) -+ Arguments = CTD->getInjectedTemplateArgs(SemaRef.Context); -+ else if (auto *Specialization = -+ dyn_cast(RD)) -+ Arguments = -+ Specialization->getTemplateInstantiationArgs().asArray(); -+ } -+ Result.addOuterTemplateArguments( -+ TSTy->getTemplateName().getAsTemplateDecl(), Arguments, -+ /*Final=*/false); - } - } -- } -- -- return UseNextDecl(RD); -- } -- -- Decl * -- VisitClassTemplateSpecializationDecl(ClassTemplateSpecializationDecl *CTSD) { -- // For a class-scope explicit specialization, there are no template -- // arguments at this level, but there may be enclosing template arguments. -- if (CTSD->isClassScopeExplicitSpecialization()) -- return UseNextDecl(CTSD); - -- // We're done when we hit an explicit specialization. -- if (CTSD->getSpecializationKind() == TSK_ExplicitSpecialization) -- return Done(); -- -- if (Innermost) -- AddInnermostTemplateArguments(CTSD); -- else -- AddOuterTemplateArguments(CTSD, -- CTSD->getTemplateInstantiationArgs().asArray(), -- /*Final=*/false); -- -- // If this class template specialization was instantiated from a -- // specialized member that is a class template, we're done. -- assert(CTSD->getSpecializedTemplate() && "No class template?"); -- llvm::PointerUnion -- Specialized = CTSD->getSpecializedTemplateOrPartial(); -- if (auto *CTPSD = -- Specialized.dyn_cast()) { -- if (CTPSD->isMemberSpecialization()) -- return Done(); -- } else { -- auto *CTD = Specialized.get(); -- if (CTD->isMemberSpecialization()) -- return Done(); -- } -- return UseNextDecl(CTSD); -+ NNS = NNS->getPrefix(); -+ } - } - -- Decl * -- VisitVarTemplateSpecializationDecl(VarTemplateSpecializationDecl *VTSD) { -- // For a class-scope explicit specialization, there are no template -- // arguments at this level, but there may be enclosing template arguments. -- if (VTSD->isClassScopeExplicitSpecialization()) -- return UseNextDecl(VTSD); -- -- // We're done when we hit an explicit specialization. -- if (VTSD->getSpecializationKind() == TSK_ExplicitSpecialization) -- return Done(); -+ return Response::ChangeDecl(FTD->getLexicalDeclContext()); -+} - -- if (Innermost) -- AddInnermostTemplateArguments(VTSD); -- else -- AddOuterTemplateArguments(VTSD, -- VTSD->getTemplateInstantiationArgs().asArray(), -- /*Final=*/false); -- -- // If this variable template specialization was instantiated from a -- // specialized member that is a variable template, we're done. -- assert(VTSD->getSpecializedTemplate() && "No variable template?"); -- llvm::PointerUnion -- Specialized = VTSD->getSpecializedTemplateOrPartial(); -- if (auto *VTPSD = -- Specialized.dyn_cast()) { -- if (VTPSD->isMemberSpecialization()) -- return Done(); -- } else { -- auto *VTD = Specialized.get(); -- if (VTD->isMemberSpecialization()) -- return Done(); -+Response HandleRecordDecl(Sema &SemaRef, const CXXRecordDecl *Rec, -+ MultiLevelTemplateArgumentList &Result, -+ ASTContext &Context, -+ bool ForConstraintInstantiation) { -+ if (ClassTemplateDecl *ClassTemplate = Rec->getDescribedClassTemplate()) { -+ assert( -+ (ForConstraintInstantiation || Result.getNumSubstitutedLevels() == 0) && -+ "Outer template not instantiated?"); -+ if (ClassTemplate->isMemberSpecialization()) -+ return Response::Done(); -+ if (ForConstraintInstantiation) -+ Result.addOuterTemplateArguments( -+ const_cast(Rec), -+ ClassTemplate->getInjectedTemplateArgs(SemaRef.Context), -+ /*Final=*/false); -+ } -+ -+ if (const MemberSpecializationInfo *MSInfo = -+ Rec->getMemberSpecializationInfo()) -+ if (MSInfo->getTemplateSpecializationKind() == TSK_ExplicitSpecialization) -+ return Response::Done(); -+ -+ bool IsFriend = Rec->getFriendObjectKind() || -+ (Rec->getDescribedClassTemplate() && -+ Rec->getDescribedClassTemplate()->getFriendObjectKind()); -+ if (ForConstraintInstantiation && IsFriend && -+ Rec->getNonTransparentDeclContext()->isFileContext()) { -+ return Response::ChangeDecl(Rec->getLexicalDeclContext()); -+ } -+ -+ // This is to make sure we pick up the VarTemplateSpecializationDecl or the -+ // TypeAliasTemplateDecl that this lambda is defined inside of. -+ if (Rec->isLambda()) { -+ if (const Decl *LCD = Rec->getLambdaContextDecl()) -+ return Response::ChangeDecl(LCD); -+ // Retrieve the template arguments for a using alias declaration. -+ // This is necessary for constraint checking, since we always keep -+ // constraints relative to the primary template. -+ if (auto TypeAlias = getEnclosingTypeAliasTemplateDecl(SemaRef); -+ ForConstraintInstantiation && TypeAlias) { -+ if (isLambdaEnclosedByTypeAliasDecl(Rec->getLambdaCallOperator(), -+ TypeAlias.PrimaryTypeAliasDecl)) { -+ Result.addOuterTemplateArguments(TypeAlias.Template, -+ TypeAlias.AssociatedTemplateArguments, -+ /*Final=*/false); -+ // Visit the parent of the current type alias declaration rather than -+ // the lambda thereof. -+ // E.g., in the following example: -+ // struct S { -+ // template using T = decltype([] {} ()); -+ // }; -+ // void foo() { -+ // S::T var; -+ // } -+ // The instantiated lambda expression (which we're visiting at 'var') -+ // has a function DeclContext 'foo' rather than the Record DeclContext -+ // S. This seems to be an oversight to me that we may want to set a -+ // Sema Context from the CXXScopeSpec before substituting into T. -+ return Response::ChangeDecl(TypeAlias.Template->getDeclContext()); -+ } - } -- return UseNextDecl(VTSD); - } - -- Decl *VisitImplicitConceptSpecializationDecl( -- ImplicitConceptSpecializationDecl *ICSD) { -- AddOuterTemplateArguments(ICSD, ICSD->getTemplateArguments(), -- /*Final=*/false); -- return UseNextDecl(ICSD); -- } -- -- Decl *VisitDecl(Decl *D) { -- if (D->isFileContextDecl()) -- return Done(); -- -- if (isa(D)) -- RelativeToPrimary = false; -- -- return UseNextDecl(D); -- } -+ return Response::UseNextDecl(Rec); -+} - -- Decl *Visit(Decl *D) { -- if (TemplateDecl *TD = D->getDescribedTemplate()) -- D = TD; -- return DeclVisitor::Visit(D); -- } --}; -+Response HandleImplicitConceptSpecializationDecl( -+ const ImplicitConceptSpecializationDecl *CSD, -+ MultiLevelTemplateArgumentList &Result) { -+ Result.addOuterTemplateArguments( -+ const_cast(CSD), -+ CSD->getTemplateArguments(), -+ /*Final=*/false); -+ return Response::UseNextDecl(CSD); -+} - -+Response HandleGenericDeclContext(const Decl *CurDecl) { -+ return Response::UseNextDecl(CurDecl); -+} -+} // namespace TemplateInstArgsHelpers - } // namespace - - MultiLevelTemplateArgumentList Sema::getTemplateInstantiationArgs( - const NamedDecl *ND, const DeclContext *DC, bool Final, - std::optional> Innermost, bool RelativeToPrimary, -- bool ForConstraintInstantiation) { -+ const FunctionDecl *Pattern, bool ForConstraintInstantiation, -+ bool SkipForSpecialization, bool ForDefaultArgumentSubstitution) { - assert((ND || DC) && "Can't find arguments for a decl if one isn't provided"); - // Accumulate the set of template argument lists in this structure. - MultiLevelTemplateArgumentList Result; -+ -+ using namespace TemplateInstArgsHelpers; - const Decl *CurDecl = ND; - - if (!CurDecl) - CurDecl = Decl::castFromDeclContext(DC); - -- TemplateInstantiationArgumentCollecter Collecter( -- *this, Result, Innermost, RelativeToPrimary, ForConstraintInstantiation); -- do { -- CurDecl = Collecter.Visit(const_cast(CurDecl)); -- } while (CurDecl); -+ if (Innermost) { -+ Result.addOuterTemplateArguments(const_cast(ND), *Innermost, -+ Final); -+ // Populate placeholder template arguments for TemplateTemplateParmDecls. -+ // This is essential for the case e.g. -+ // -+ // template concept Concept = false; -+ // template