@@ -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;
@@ -534,14 +549,12 @@ MultiLevelTemplateArgumentList Sema::getTemplateInstantiationArgs(
534549 }
535550
536551 if (R.IsDone )
537- return Result ;
552+ return ;
538553 if (R.ClearRelativeToPrimary )
539554 RelativeToPrimary = false ;
540555 assert (R.NextDecl );
541556 CurDecl = R.NextDecl ;
542557 }
543-
544- return Result;
545558}
546559
547560bool Sema::CodeSynthesisContext::isInstantiationRecord () const {
@@ -1374,6 +1387,19 @@ namespace {
13741387 // Whether an incomplete substituion should be treated as an error.
13751388 bool BailOutOnIncomplete;
13761389
1390+ private:
1391+ bool isSubstitutingConstraints () const {
1392+ return llvm::any_of (SemaRef.CodeSynthesisContexts , [](auto &Context) {
1393+ return Context.Kind ==
1394+ Sema::CodeSynthesisContext::ConstraintSubstitution;
1395+ });
1396+ }
1397+
1398+ // CWG2770: Function parameters should be instantiated when they are
1399+ // needed by a satisfaction check of an atomic constraint or
1400+ // (recursively) by another function parameter.
1401+ bool maybeInstantiateFunctionParameterToScope (ParmVarDecl *OldParm);
1402+
13771403 public:
13781404 typedef TreeTransform<TemplateInstantiator> inherited;
13791405
@@ -1430,12 +1456,19 @@ namespace {
14301456 ArrayRef<UnexpandedParameterPack> Unexpanded,
14311457 bool &ShouldExpand, bool &RetainExpansion,
14321458 UnsignedOrNone &NumExpansions) {
1433- return getSema ().CheckParameterPacksForExpansion (EllipsisLoc,
1434- PatternRange, Unexpanded,
1435- TemplateArgs,
1436- ShouldExpand,
1437- RetainExpansion,
1438- NumExpansions);
1459+ if (SemaRef.CurrentInstantiationScope && isSubstitutingConstraints ()) {
1460+ for (UnexpandedParameterPack ParmPack : Unexpanded) {
1461+ NamedDecl *VD = ParmPack.first .dyn_cast <NamedDecl *>();
1462+ if (!isa_and_present<ParmVarDecl>(VD))
1463+ continue ;
1464+ if (maybeInstantiateFunctionParameterToScope (cast<ParmVarDecl>(VD)))
1465+ return true ;
1466+ }
1467+ }
1468+
1469+ return getSema ().CheckParameterPacksForExpansion (
1470+ EllipsisLoc, PatternRange, Unexpanded, TemplateArgs, ShouldExpand,
1471+ RetainExpansion, NumExpansions);
14391472 }
14401473
14411474 void ExpandingFunctionParameterPack (ParmVarDecl *Pack) {
@@ -1919,9 +1952,62 @@ Decl *TemplateInstantiator::TransformDecl(SourceLocation Loc, Decl *D) {
19191952 // template parameter.
19201953 }
19211954
1955+ if (SemaRef.CurrentInstantiationScope ) {
1956+ if (isSubstitutingConstraints () && isa<ParmVarDecl>(D) &&
1957+ maybeInstantiateFunctionParameterToScope (cast<ParmVarDecl>(D)))
1958+ return nullptr ;
1959+ }
1960+
19221961 return SemaRef.FindInstantiatedDecl (Loc, cast<NamedDecl>(D), TemplateArgs);
19231962}
19241963
1964+ bool TemplateInstantiator::maybeInstantiateFunctionParameterToScope (
1965+ ParmVarDecl *OldParm) {
1966+ if (SemaRef.CurrentInstantiationScope ->findInstantiationUnsafe (OldParm))
1967+ return false ;
1968+ // We're instantiating a function parameter whose associated function template
1969+ // has not been instantiated at this point for constraint evaluation, so make
1970+ // sure the instantiated parameters are owned by a function declaration such
1971+ // that they can be correctly 'captured' in tryCaptureVariable().
1972+ Sema::ContextRAII Context (SemaRef, OldParm->getDeclContext ());
1973+
1974+ if (!OldParm->isParameterPack ())
1975+ return !TransformFunctionTypeParam (OldParm, /* indexAdjustment=*/ 0 ,
1976+ /* NumExpansions=*/ std::nullopt ,
1977+ /* ExpectParameterPack=*/ false );
1978+
1979+ SmallVector<UnexpandedParameterPack, 2 > Unexpanded;
1980+
1981+ // Find the parameter packs that could be expanded.
1982+ TypeLoc TL = OldParm->getTypeSourceInfo ()->getTypeLoc ();
1983+ PackExpansionTypeLoc ExpansionTL = TL.castAs <PackExpansionTypeLoc>();
1984+ TypeLoc Pattern = ExpansionTL.getPatternLoc ();
1985+ SemaRef.collectUnexpandedParameterPacks (Pattern, Unexpanded);
1986+ assert (!Unexpanded.empty () && " Pack expansion without parameter packs?" );
1987+
1988+ bool ShouldExpand = false ;
1989+ bool RetainExpansion = false ;
1990+ std::optional<unsigned > OrigNumExpansions =
1991+ ExpansionTL.getTypePtr ()->getNumExpansions ();
1992+ std::optional<unsigned > NumExpansions = OrigNumExpansions;
1993+ if (TryExpandParameterPacks (ExpansionTL.getEllipsisLoc (),
1994+ Pattern.getSourceRange (), Unexpanded,
1995+ ShouldExpand, RetainExpansion, NumExpansions))
1996+ return true ;
1997+
1998+ assert (ShouldExpand && !RetainExpansion &&
1999+ " Shouldn't preserve pack expansion when evaluating constraints" );
2000+ ExpandingFunctionParameterPack (OldParm);
2001+ for (unsigned I = 0 ; I != *NumExpansions; ++I) {
2002+ Sema::ArgumentPackSubstitutionIndexRAII SubstIndex (getSema (), I);
2003+ if (!TransformFunctionTypeParam (OldParm, /* indexAdjustment=*/ 0 ,
2004+ /* NumExpansions=*/ OrigNumExpansions,
2005+ /* ExpectParameterPack=*/ false ))
2006+ return true ;
2007+ }
2008+ return false ;
2009+ }
2010+
19252011Decl *TemplateInstantiator::TransformDefinition (SourceLocation Loc, Decl *D) {
19262012 Decl *Inst = getSema ().SubstDecl (D, getSema ().CurContext , TemplateArgs);
19272013 if (!Inst)
@@ -4485,9 +4571,8 @@ static const Decl *getCanonicalParmVarDecl(const Decl *D) {
44854571 return D;
44864572}
44874573
4488-
44894574llvm::PointerUnion<Decl *, LocalInstantiationScope::DeclArgumentPack *> *
4490- LocalInstantiationScope::findInstantiationOf (const Decl *D) {
4575+ LocalInstantiationScope::findInstantiationUnsafe (const Decl *D) {
44914576 D = getCanonicalParmVarDecl (D);
44924577 for (LocalInstantiationScope *Current = this ; Current;
44934578 Current = Current->Outer ) {
@@ -4512,6 +4597,14 @@ LocalInstantiationScope::findInstantiationOf(const Decl *D) {
45124597 break ;
45134598 }
45144599
4600+ return nullptr ;
4601+ }
4602+
4603+ llvm::PointerUnion<Decl *, LocalInstantiationScope::DeclArgumentPack *> *
4604+ LocalInstantiationScope::findInstantiationOf (const Decl *D) {
4605+ auto *Result = findInstantiationUnsafe (D);
4606+ if (Result)
4607+ return Result;
45154608 // If we're performing a partial substitution during template argument
45164609 // deduction, we may not have values for template parameters yet.
45174610 if (isa<NonTypeTemplateParmDecl>(D) || isa<TemplateTypeParmDecl>(D) ||
0 commit comments