@@ -475,6 +475,21 @@ MultiLevelTemplateArgumentList Sema::getTemplateInstantiationArgs(
475475 assert ((ND || DC) && " Can't find arguments for a decl if one isn't provided" );
476476 // Accumulate the set of template argument lists in this structure.
477477 MultiLevelTemplateArgumentList Result;
478+ getTemplateInstantiationArgs (
479+ Result, ND, DC, Final, Innermost, RelativeToPrimary, Pattern,
480+ ForConstraintInstantiation, SkipForSpecialization,
481+ ForDefaultArgumentSubstitution);
482+ return Result;
483+ }
484+
485+ void Sema::getTemplateInstantiationArgs (
486+ MultiLevelTemplateArgumentList &Result, const NamedDecl *ND,
487+ const DeclContext *DC, bool Final,
488+ std::optional<ArrayRef<TemplateArgument>> Innermost, bool RelativeToPrimary,
489+ const FunctionDecl *Pattern, bool ForConstraintInstantiation,
490+ bool SkipForSpecialization, bool ForDefaultArgumentSubstitution) {
491+ assert ((ND || DC) && " Can't find arguments for a decl if one isn't provided" );
492+ // Accumulate the set of template argument lists in this structure.
478493
479494 using namespace TemplateInstArgsHelpers ;
480495 const Decl *CurDecl = ND;
@@ -535,14 +550,12 @@ MultiLevelTemplateArgumentList Sema::getTemplateInstantiationArgs(
535550 }
536551
537552 if (R.IsDone )
538- return Result ;
553+ return ;
539554 if (R.ClearRelativeToPrimary )
540555 RelativeToPrimary = false ;
541556 assert (R.NextDecl );
542557 CurDecl = R.NextDecl ;
543558 }
544-
545- return Result;
546559}
547560
548561bool Sema::CodeSynthesisContext::isInstantiationRecord () const {
@@ -1364,6 +1377,19 @@ namespace {
13641377 // Whether an incomplete substituion should be treated as an error.
13651378 bool BailOutOnIncomplete;
13661379
1380+ private:
1381+ bool isSubstitutingConstraints () const {
1382+ return llvm::any_of (SemaRef.CodeSynthesisContexts , [](auto &Context) {
1383+ return Context.Kind ==
1384+ Sema::CodeSynthesisContext::ConstraintSubstitution;
1385+ });
1386+ }
1387+
1388+ // CWG2770: Function parameters should be instantiated when they are
1389+ // needed by a satisfaction check of an atomic constraint or
1390+ // (recursively) by another function parameter.
1391+ bool maybeInstantiateFunctionParameterToScope (ParmVarDecl *OldParm);
1392+
13671393 public:
13681394 typedef TreeTransform<TemplateInstantiator> inherited;
13691395
@@ -1420,12 +1446,19 @@ namespace {
14201446 ArrayRef<UnexpandedParameterPack> Unexpanded,
14211447 bool &ShouldExpand, bool &RetainExpansion,
14221448 std::optional<unsigned > &NumExpansions) {
1423- return getSema ().CheckParameterPacksForExpansion (EllipsisLoc,
1424- PatternRange, Unexpanded,
1425- TemplateArgs,
1426- ShouldExpand,
1427- RetainExpansion,
1428- NumExpansions);
1449+ if (SemaRef.CurrentInstantiationScope && isSubstitutingConstraints ()) {
1450+ for (UnexpandedParameterPack ParmPack : Unexpanded) {
1451+ NamedDecl *VD = ParmPack.first .dyn_cast <NamedDecl *>();
1452+ if (!isa_and_present<ParmVarDecl>(VD))
1453+ continue ;
1454+ if (maybeInstantiateFunctionParameterToScope (cast<ParmVarDecl>(VD)))
1455+ return true ;
1456+ }
1457+ }
1458+
1459+ return getSema ().CheckParameterPacksForExpansion (
1460+ EllipsisLoc, PatternRange, Unexpanded, TemplateArgs, ShouldExpand,
1461+ RetainExpansion, NumExpansions);
14291462 }
14301463
14311464 void ExpandingFunctionParameterPack (ParmVarDecl *Pack) {
@@ -1900,9 +1933,62 @@ Decl *TemplateInstantiator::TransformDecl(SourceLocation Loc, Decl *D) {
19001933 // template parameter.
19011934 }
19021935
1936+ if (SemaRef.CurrentInstantiationScope ) {
1937+ if (isSubstitutingConstraints () && isa<ParmVarDecl>(D) &&
1938+ maybeInstantiateFunctionParameterToScope (cast<ParmVarDecl>(D)))
1939+ return nullptr ;
1940+ }
1941+
19031942 return SemaRef.FindInstantiatedDecl (Loc, cast<NamedDecl>(D), TemplateArgs);
19041943}
19051944
1945+ bool TemplateInstantiator::maybeInstantiateFunctionParameterToScope (
1946+ ParmVarDecl *OldParm) {
1947+ if (SemaRef.CurrentInstantiationScope ->findInstantiationUnsafe (OldParm))
1948+ return false ;
1949+ // We're instantiating a function parameter whose associated function template
1950+ // has not been instantiated at this point for constraint evaluation, so make
1951+ // sure the instantiated parameters are owned by a function declaration such
1952+ // that they can be correctly 'captured' in tryCaptureVariable().
1953+ Sema::ContextRAII Context (SemaRef, OldParm->getDeclContext ());
1954+
1955+ if (!OldParm->isParameterPack ())
1956+ return !TransformFunctionTypeParam (OldParm, /* indexAdjustment=*/ 0 ,
1957+ /* NumExpansions=*/ std::nullopt ,
1958+ /* ExpectParameterPack=*/ false );
1959+
1960+ SmallVector<UnexpandedParameterPack, 2 > Unexpanded;
1961+
1962+ // Find the parameter packs that could be expanded.
1963+ TypeLoc TL = OldParm->getTypeSourceInfo ()->getTypeLoc ();
1964+ PackExpansionTypeLoc ExpansionTL = TL.castAs <PackExpansionTypeLoc>();
1965+ TypeLoc Pattern = ExpansionTL.getPatternLoc ();
1966+ SemaRef.collectUnexpandedParameterPacks (Pattern, Unexpanded);
1967+ assert (!Unexpanded.empty () && " Pack expansion without parameter packs?" );
1968+
1969+ bool ShouldExpand = false ;
1970+ bool RetainExpansion = false ;
1971+ std::optional<unsigned > OrigNumExpansions =
1972+ ExpansionTL.getTypePtr ()->getNumExpansions ();
1973+ std::optional<unsigned > NumExpansions = OrigNumExpansions;
1974+ if (TryExpandParameterPacks (ExpansionTL.getEllipsisLoc (),
1975+ Pattern.getSourceRange (), Unexpanded,
1976+ ShouldExpand, RetainExpansion, NumExpansions))
1977+ return true ;
1978+
1979+ assert (ShouldExpand && !RetainExpansion &&
1980+ " Shouldn't preserve pack expansion when evaluating constraints" );
1981+ ExpandingFunctionParameterPack (OldParm);
1982+ for (unsigned I = 0 ; I != *NumExpansions; ++I) {
1983+ Sema::ArgumentPackSubstitutionIndexRAII SubstIndex (getSema (), I);
1984+ if (!TransformFunctionTypeParam (OldParm, /* indexAdjustment=*/ 0 ,
1985+ /* NumExpansions=*/ OrigNumExpansions,
1986+ /* ExpectParameterPack=*/ false ))
1987+ return true ;
1988+ }
1989+ return false ;
1990+ }
1991+
19061992Decl *TemplateInstantiator::TransformDefinition (SourceLocation Loc, Decl *D) {
19071993 Decl *Inst = getSema ().SubstDecl (D, getSema ().CurContext , TemplateArgs);
19081994 if (!Inst)
@@ -4584,9 +4670,8 @@ static const Decl *getCanonicalParmVarDecl(const Decl *D) {
45844670 return D;
45854671}
45864672
4587-
45884673llvm::PointerUnion<Decl *, LocalInstantiationScope::DeclArgumentPack *> *
4589- LocalInstantiationScope::findInstantiationOf (const Decl *D) {
4674+ LocalInstantiationScope::findInstantiationUnsafe (const Decl *D) {
45904675 D = getCanonicalParmVarDecl (D);
45914676 for (LocalInstantiationScope *Current = this ; Current;
45924677 Current = Current->Outer ) {
@@ -4611,6 +4696,14 @@ LocalInstantiationScope::findInstantiationOf(const Decl *D) {
46114696 break ;
46124697 }
46134698
4699+ return nullptr ;
4700+ }
4701+
4702+ llvm::PointerUnion<Decl *, LocalInstantiationScope::DeclArgumentPack *> *
4703+ LocalInstantiationScope::findInstantiationOf (const Decl *D) {
4704+ auto *Result = findInstantiationUnsafe (D);
4705+ if (Result)
4706+ return Result;
46144707 // If we're performing a partial substitution during template argument
46154708 // deduction, we may not have values for template parameters yet.
46164709 if (isa<NonTypeTemplateParmDecl>(D) || isa<TemplateTypeParmDecl>(D) ||
0 commit comments