@@ -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 {
@@ -1349,6 +1362,19 @@ namespace {
13491362 // Whether an incomplete substituion should be treated as an error.
13501363 bool BailOutOnIncomplete;
13511364
1365+ private:
1366+ bool isSubstitutingConstraints () const {
1367+ return llvm::any_of (SemaRef.CodeSynthesisContexts , [](auto &Context) {
1368+ return Context.Kind ==
1369+ Sema::CodeSynthesisContext::ConstraintSubstitution;
1370+ });
1371+ }
1372+
1373+ // CWG2770: Function parameters should be instantiated when they are
1374+ // needed by a satisfaction check of an atomic constraint or
1375+ // (recursively) by another function parameter.
1376+ bool maybeInstantiateFunctionParameterToScope (ParmVarDecl *OldParm);
1377+
13521378 public:
13531379 typedef TreeTransform<TemplateInstantiator> inherited;
13541380
@@ -1405,12 +1431,19 @@ namespace {
14051431 ArrayRef<UnexpandedParameterPack> Unexpanded,
14061432 bool &ShouldExpand, bool &RetainExpansion,
14071433 std::optional<unsigned > &NumExpansions) {
1408- return getSema ().CheckParameterPacksForExpansion (EllipsisLoc,
1409- PatternRange, Unexpanded,
1410- TemplateArgs,
1411- ShouldExpand,
1412- RetainExpansion,
1413- NumExpansions);
1434+ if (SemaRef.CurrentInstantiationScope && isSubstitutingConstraints ()) {
1435+ for (UnexpandedParameterPack ParmPack : Unexpanded) {
1436+ NamedDecl *VD = ParmPack.first .dyn_cast <NamedDecl *>();
1437+ if (!isa_and_present<ParmVarDecl>(VD))
1438+ continue ;
1439+ if (maybeInstantiateFunctionParameterToScope (cast<ParmVarDecl>(VD)))
1440+ return true ;
1441+ }
1442+ }
1443+
1444+ return getSema ().CheckParameterPacksForExpansion (
1445+ EllipsisLoc, PatternRange, Unexpanded, TemplateArgs, ShouldExpand,
1446+ RetainExpansion, NumExpansions);
14141447 }
14151448
14161449 void ExpandingFunctionParameterPack (ParmVarDecl *Pack) {
@@ -1911,9 +1944,62 @@ Decl *TemplateInstantiator::TransformDecl(SourceLocation Loc, Decl *D) {
19111944 // template parameter.
19121945 }
19131946
1947+ if (SemaRef.CurrentInstantiationScope ) {
1948+ if (isSubstitutingConstraints () && isa<ParmVarDecl>(D) &&
1949+ maybeInstantiateFunctionParameterToScope (cast<ParmVarDecl>(D)))
1950+ return nullptr ;
1951+ }
1952+
19141953 return SemaRef.FindInstantiatedDecl (Loc, cast<NamedDecl>(D), TemplateArgs);
19151954}
19161955
1956+ bool TemplateInstantiator::maybeInstantiateFunctionParameterToScope (
1957+ ParmVarDecl *OldParm) {
1958+ if (SemaRef.CurrentInstantiationScope ->findInstantiationUnsafe (OldParm))
1959+ return false ;
1960+ // We're instantiating a function parameter whose associated function template
1961+ // has not been instantiated at this point for constraint evaluation, so make
1962+ // sure the instantiated parameters are owned by a function declaration such
1963+ // that they can be correctly 'captured' in tryCaptureVariable().
1964+ Sema::ContextRAII Context (SemaRef, OldParm->getDeclContext ());
1965+
1966+ if (!OldParm->isParameterPack ())
1967+ return !TransformFunctionTypeParam (OldParm, /* indexAdjustment=*/ 0 ,
1968+ /* NumExpansions=*/ std::nullopt ,
1969+ /* ExpectParameterPack=*/ false );
1970+
1971+ SmallVector<UnexpandedParameterPack, 2 > Unexpanded;
1972+
1973+ // Find the parameter packs that could be expanded.
1974+ TypeLoc TL = OldParm->getTypeSourceInfo ()->getTypeLoc ();
1975+ PackExpansionTypeLoc ExpansionTL = TL.castAs <PackExpansionTypeLoc>();
1976+ TypeLoc Pattern = ExpansionTL.getPatternLoc ();
1977+ SemaRef.collectUnexpandedParameterPacks (Pattern, Unexpanded);
1978+ assert (!Unexpanded.empty () && " Pack expansion without parameter packs?" );
1979+
1980+ bool ShouldExpand = false ;
1981+ bool RetainExpansion = false ;
1982+ std::optional<unsigned > OrigNumExpansions =
1983+ ExpansionTL.getTypePtr ()->getNumExpansions ();
1984+ std::optional<unsigned > NumExpansions = OrigNumExpansions;
1985+ if (TryExpandParameterPacks (ExpansionTL.getEllipsisLoc (),
1986+ Pattern.getSourceRange (), Unexpanded,
1987+ ShouldExpand, RetainExpansion, NumExpansions))
1988+ return true ;
1989+
1990+ assert (ShouldExpand && !RetainExpansion &&
1991+ " Shouldn't preserve pack expansion when evaluating constraints" );
1992+ ExpandingFunctionParameterPack (OldParm);
1993+ for (unsigned I = 0 ; I != *NumExpansions; ++I) {
1994+ Sema::ArgumentPackSubstitutionIndexRAII SubstIndex (getSema (), I);
1995+ if (!TransformFunctionTypeParam (OldParm, /* indexAdjustment=*/ 0 ,
1996+ /* NumExpansions=*/ OrigNumExpansions,
1997+ /* ExpectParameterPack=*/ false ))
1998+ return true ;
1999+ }
2000+ return false ;
2001+ }
2002+
19172003Decl *TemplateInstantiator::TransformDefinition (SourceLocation Loc, Decl *D) {
19182004 Decl *Inst = getSema ().SubstDecl (D, getSema ().CurContext , TemplateArgs);
19192005 if (!Inst)
@@ -4591,9 +4677,8 @@ static const Decl *getCanonicalParmVarDecl(const Decl *D) {
45914677 return D;
45924678}
45934679
4594-
45954680llvm::PointerUnion<Decl *, LocalInstantiationScope::DeclArgumentPack *> *
4596- LocalInstantiationScope::findInstantiationOf (const Decl *D) {
4681+ LocalInstantiationScope::findInstantiationUnsafe (const Decl *D) {
45974682 D = getCanonicalParmVarDecl (D);
45984683 for (LocalInstantiationScope *Current = this ; Current;
45994684 Current = Current->Outer ) {
@@ -4618,6 +4703,14 @@ LocalInstantiationScope::findInstantiationOf(const Decl *D) {
46184703 break ;
46194704 }
46204705
4706+ return nullptr ;
4707+ }
4708+
4709+ llvm::PointerUnion<Decl *, LocalInstantiationScope::DeclArgumentPack *> *
4710+ LocalInstantiationScope::findInstantiationOf (const Decl *D) {
4711+ auto *Result = findInstantiationUnsafe (D);
4712+ if (Result)
4713+ return Result;
46214714 // If we're performing a partial substitution during template argument
46224715 // deduction, we may not have values for template parameters yet.
46234716 if (isa<NonTypeTemplateParmDecl>(D) || isa<TemplateTypeParmDecl>(D) ||
0 commit comments