[c++20] P0780R2: Support pack-expansion of init-captures.

This permits an init-capture to introduce a new pack:

  template<typename ...T> auto x = [...a = T()] { /* a is a pack */ };

To support this, the mechanism for allowing ParmVarDecls to be packs has
been extended to support arbitrary local VarDecls.

llvm-svn: 361300
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index 55d1d94..ba54d50 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -819,7 +819,19 @@
       SemaRef.InstantiateAttrs(TemplateArgs, Old, New);
     }
 
-    void transformedLocalDecl(Decl *Old, Decl *New) {
+    void transformedLocalDecl(Decl *Old, ArrayRef<Decl *> NewDecls) {
+      if (Old->isParameterPack()) {
+        SemaRef.CurrentInstantiationScope->MakeInstantiatedLocalArgPack(Old);
+        for (auto *New : NewDecls)
+          SemaRef.CurrentInstantiationScope->InstantiatedLocalPackArg(
+              Old, cast<VarDecl>(New));
+        return;
+      }
+
+      assert(NewDecls.size() == 1 &&
+             "should only have multiple expansions for a pack");
+      Decl *New = NewDecls.front();
+
       // If we've instantiated the call operator of a lambda or the call
       // operator template of a generic lambda, update the "instantiation of"
       // information.
@@ -888,12 +900,11 @@
     ExprResult TransformSubstNonTypeTemplateParmPackExpr(
                                            SubstNonTypeTemplateParmPackExpr *E);
 
-    /// Rebuild a DeclRefExpr for a ParmVarDecl reference.
-    ExprResult RebuildParmVarDeclRefExpr(ParmVarDecl *PD, SourceLocation Loc);
+    /// Rebuild a DeclRefExpr for a VarDecl reference.
+    ExprResult RebuildVarDeclRefExpr(VarDecl *PD, SourceLocation Loc);
 
-    /// Transform a reference to a function parameter pack.
-    ExprResult TransformFunctionParmPackRefExpr(DeclRefExpr *E,
-                                                ParmVarDecl *PD);
+    /// Transform a reference to a function or init-capture parameter pack.
+    ExprResult TransformFunctionParmPackRefExpr(DeclRefExpr *E, VarDecl *PD);
 
     /// Transform a FunctionParmPackExpr which was built when we couldn't
     /// expand a function parameter pack reference which refers to an expanded
@@ -1324,9 +1335,8 @@
                                          Arg);
 }
 
-ExprResult
-TemplateInstantiator::RebuildParmVarDeclRefExpr(ParmVarDecl *PD,
-                                                SourceLocation Loc) {
+ExprResult TemplateInstantiator::RebuildVarDeclRefExpr(VarDecl *PD,
+                                                       SourceLocation Loc) {
   DeclarationNameInfo NameInfo(PD->getDeclName(), Loc);
   return getSema().BuildDeclarationNameExpr(CXXScopeSpec(), NameInfo, PD);
 }
@@ -1335,11 +1345,11 @@
 TemplateInstantiator::TransformFunctionParmPackExpr(FunctionParmPackExpr *E) {
   if (getSema().ArgumentPackSubstitutionIndex != -1) {
     // We can expand this parameter pack now.
-    ParmVarDecl *D = E->getExpansion(getSema().ArgumentPackSubstitutionIndex);
-    ValueDecl *VD = cast_or_null<ValueDecl>(TransformDecl(E->getExprLoc(), D));
+    VarDecl *D = E->getExpansion(getSema().ArgumentPackSubstitutionIndex);
+    VarDecl *VD = cast_or_null<VarDecl>(TransformDecl(E->getExprLoc(), D));
     if (!VD)
       return ExprError();
-    return RebuildParmVarDeclRefExpr(cast<ParmVarDecl>(VD), E->getExprLoc());
+    return RebuildVarDeclRefExpr(VD, E->getExprLoc());
   }
 
   QualType T = TransformType(E->getType());
@@ -1348,25 +1358,24 @@
 
   // Transform each of the parameter expansions into the corresponding
   // parameters in the instantiation of the function decl.
-  SmallVector<ParmVarDecl *, 8> Parms;
-  Parms.reserve(E->getNumExpansions());
+  SmallVector<VarDecl *, 8> Vars;
+  Vars.reserve(E->getNumExpansions());
   for (FunctionParmPackExpr::iterator I = E->begin(), End = E->end();
        I != End; ++I) {
-    ParmVarDecl *D =
-        cast_or_null<ParmVarDecl>(TransformDecl(E->getExprLoc(), *I));
+    VarDecl *D = cast_or_null<VarDecl>(TransformDecl(E->getExprLoc(), *I));
     if (!D)
       return ExprError();
-    Parms.push_back(D);
+    Vars.push_back(D);
   }
 
   return FunctionParmPackExpr::Create(getSema().Context, T,
                                       E->getParameterPack(),
-                                      E->getParameterPackLocation(), Parms);
+                                      E->getParameterPackLocation(), Vars);
 }
 
 ExprResult
 TemplateInstantiator::TransformFunctionParmPackRefExpr(DeclRefExpr *E,
-                                                       ParmVarDecl *PD) {
+                                                       VarDecl *PD) {
   typedef LocalInstantiationScope::DeclArgumentPack DeclArgumentPack;
   llvm::PointerUnion<Decl *, DeclArgumentPack *> *Found
     = getSema().CurrentInstantiationScope->findInstantiationOf(PD);
@@ -1390,8 +1399,7 @@
   }
 
   // We have either an unexpanded pack or a specific expansion.
-  return RebuildParmVarDeclRefExpr(cast<ParmVarDecl>(TransformedDecl),
-                                   E->getExprLoc());
+  return RebuildVarDeclRefExpr(cast<VarDecl>(TransformedDecl), E->getExprLoc());
 }
 
 ExprResult
@@ -1409,7 +1417,7 @@
   }
 
   // Handle references to function parameter packs.
-  if (ParmVarDecl *PD = dyn_cast<ParmVarDecl>(D))
+  if (VarDecl *PD = dyn_cast<VarDecl>(D))
     if (PD->isParameterPack())
       return TransformFunctionParmPackRefExpr(E, PD);
 
@@ -2984,14 +2992,14 @@
 #endif
     Stored = Inst;
   } else if (DeclArgumentPack *Pack = Stored.dyn_cast<DeclArgumentPack *>()) {
-    Pack->push_back(cast<ParmVarDecl>(Inst));
+    Pack->push_back(cast<VarDecl>(Inst));
   } else {
     assert(Stored.get<Decl *>() == Inst && "Already instantiated this local");
   }
 }
 
 void LocalInstantiationScope::InstantiatedLocalPackArg(const Decl *D,
-                                                       ParmVarDecl *Inst) {
+                                                       VarDecl *Inst) {
   D = getCanonicalParmVarDecl(D);
   DeclArgumentPack *Pack = LocalDecls[D].get<DeclArgumentPack *>();
   Pack->push_back(Inst);