Keep track of the number of expansions to be produced from a type pack
expansion, when it is known due to the substitution of an out
parameter pack. This allows us to properly handle substitution into
pack expansions that involve multiple parameter packs at different
template parameter levels, even when this substitution happens one
level at a time (as with partial specializations of member class
templates and the signatures of member function templates).

Note that the diagnostic we provide when there is an arity mismatch
between an outer parameter pack and an inner parameter pack in this
case isn't as clear as the normal diagnostic for an arity
mismatch. However, this doesn't matter because these cases are very,
very rare and (even then) only typically occur in a SFINAE context.

The other kinds of pack expansions (expression, template, etc.) still
need to support optional tracking of the number of expansions, and we
need the moral equivalent of SubstTemplateTypeParmPackType for
substituted argument packs of template template and non-type template
parameters.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@123448 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index a18bfba..6b5713a 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -1977,7 +1977,8 @@
         
         bool Expand = false;
         bool RetainExpansion = false;
-        unsigned NumExpansions = 0;
+        llvm::Optional<unsigned> NumExpansions
+                                          = PackExpansion->getNumExpansions();
         if (SemaRef.CheckParameterPacksForExpansion(New->getLocation(), 
                                                     SourceRange(),
                                                     Unexpanded.data(), 
@@ -1990,7 +1991,8 @@
                       
         if (!Expand) {
           // We can't expand this pack expansion into separate arguments yet;
-          // just substitute into the argument pack.
+          // just substitute into the pattern and create a new pack expansion 
+          // type.
           Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, -1);
           QualType T = SemaRef.SubstType(PackExpansion->getPattern(), 
                                          TemplateArgs,
@@ -1998,13 +2000,14 @@
           if (T.isNull())
             break;
           
+          T = SemaRef.Context.getPackExpansionType(T, NumExpansions);
           Exceptions.push_back(T);
           continue;
         }
         
         // Substitute into the pack expansion pattern for each template
         bool Invalid = false;
-        for (unsigned ArgIdx = 0; ArgIdx != NumExpansions; ++ArgIdx) {
+        for (unsigned ArgIdx = 0; ArgIdx != *NumExpansions; ++ArgIdx) {
           Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, ArgIdx);
           
           QualType T = SemaRef.SubstType(PackExpansion->getPattern(), 
@@ -2384,7 +2387,7 @@
       collectUnexpandedParameterPacks(BaseTL, Unexpanded);
       bool ShouldExpand = false;
       bool RetainExpansion = false;
-      unsigned NumExpansions = 0;
+      llvm::Optional<unsigned> NumExpansions;
       if (CheckParameterPacksForExpansion(Init->getEllipsisLoc(), 
                                           BaseTL.getSourceRange(),
                                           Unexpanded.data(), 
@@ -2399,7 +2402,7 @@
       assert(ShouldExpand && "Partial instantiation of base initializer?");
       
       // Loop over all of the arguments in the argument pack(s), 
-      for (unsigned I = 0; I != NumExpansions; ++I) {
+      for (unsigned I = 0; I != *NumExpansions; ++I) {
         Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(*this, I);
 
         // Instantiate the initializer.