Teach template template argument pack expansions to keep track of the
number of expansions, when we know it, and propagate that information
through Sema.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@123493 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index a98e063..e1e6fd0 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -2768,7 +2768,7 @@
     case TemplateArgument::TemplateExpansion:
       return TemplateArgument(getCanonicalTemplateName(
                                          Arg.getAsTemplateOrTemplatePattern()),
-                              true);
+                              Arg.getNumTemplateExpansions());
 
     case TemplateArgument::Integral:
       return TemplateArgument(*Arg.getAsIntegral(),
diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp
index 7989b9f..f9fe18f 100644
--- a/lib/AST/ASTImporter.cpp
+++ b/lib/AST/ASTImporter.cpp
@@ -1823,7 +1823,7 @@
     if (ToTemplate.isNull())
       return TemplateArgument();
     
-    return TemplateArgument(ToTemplate, true);
+    return TemplateArgument(ToTemplate, From.getNumTemplateExpansions());
   }
 
   case TemplateArgument::Expression:
diff --git a/lib/AST/DeclTemplate.cpp b/lib/AST/DeclTemplate.cpp
index e7902e9..b6716b3 100644
--- a/lib/AST/DeclTemplate.cpp
+++ b/lib/AST/DeclTemplate.cpp
@@ -337,7 +337,10 @@
       Arg = TemplateArgument(E);
     } else {
       TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*Param);
-      Arg = TemplateArgument(TemplateName(TTP), TTP->isParameterPack());
+      if (TTP->isParameterPack())
+        Arg = TemplateArgument(TemplateName(TTP), llvm::Optional<unsigned>());
+      else
+        Arg = TemplateArgument(TemplateName(TTP));
     }
     
     if ((*Param)->isTemplateParameterPack())
diff --git a/lib/AST/TemplateBase.cpp b/lib/AST/TemplateBase.cpp
index 26c0c08..f3def3e 100644
--- a/lib/AST/TemplateBase.cpp
+++ b/lib/AST/TemplateBase.cpp
@@ -135,6 +135,14 @@
   return false;
 }
 
+llvm::Optional<unsigned> TemplateArgument::getNumTemplateExpansions() const {
+  assert(Kind == TemplateExpansion);
+  if (TemplateArg.NumExpansions)
+    return TemplateArg.NumExpansions - 1;
+  
+  return llvm::Optional<unsigned>();
+}
+
 void TemplateArgument::Profile(llvm::FoldingSetNodeID &ID,
                                const ASTContext &Context) const {
   ID.AddInteger(Kind);
@@ -223,7 +231,7 @@
     return cast<PackExpansionExpr>(getAsExpr())->getPattern();
     
   case TemplateExpansion:
-    return TemplateArgument(getAsTemplateOrTemplatePattern(), false);
+    return TemplateArgument(getAsTemplateOrTemplatePattern());
     
   case Declaration:
   case Integral:
@@ -389,8 +397,8 @@
   }
 
   case TemplateArgument::TemplateExpansion:
-    // FIXME: Variadic templates num expansions
     Ellipsis = getTemplateEllipsisLoc();
+    NumExpansions = Argument.getNumTemplateExpansions();
     return TemplateArgumentLoc(Argument.getPackExpansionPattern(),
                                getTemplateQualifierRange(),
                                getTemplateNameLoc());
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 5101b3b..3c9d386 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -467,8 +467,12 @@
     
   case ParsedTemplateArgument::Template: {
     TemplateName Template = Arg.getAsTemplate().get();
-    return TemplateArgumentLoc(TemplateArgument(Template,
-                                                Arg.getEllipsisLoc().isValid()),
+    TemplateArgument TArg;
+    if (Arg.getEllipsisLoc().isValid())
+      TArg = TemplateArgument(Template, llvm::Optional<unsigned int>());
+    else
+      TArg = Template;
+    return TemplateArgumentLoc(TArg,
                                Arg.getScopeSpec().getRange(),
                                Arg.getLocation(),
                                Arg.getEllipsisLoc());
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index 13cc17e..17b38bc 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -809,11 +809,8 @@
         assert(Arg.getKind() == TemplateArgument::Pack && 
                "Missing argument pack");
         
-        if (getSema().ArgumentPackSubstitutionIndex == -1) {
-          // FIXME: Variadic templates fun case.
-          getSema().Diag(Loc, diag::err_pack_expansion_mismatch_unsupported);
+        if (getSema().ArgumentPackSubstitutionIndex == -1)
           return 0;
-        }
         
         assert(getSema().ArgumentPackSubstitutionIndex < (int)Arg.pack_size());
         Arg = Arg.pack_begin()[getSema().ArgumentPackSubstitutionIndex];
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index 4abcb88..02c95bd 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -2188,7 +2188,7 @@
     case TemplateArgument::Template:
       return TemplateArgumentLoc(TemplateArgument(
                                           Pattern.getArgument().getAsTemplate(),
-                                                  true),
+                                                  NumExpansions),
                                  Pattern.getTemplateQualifierRange(),
                                  Pattern.getTemplateNameLoc(),
                                  EllipsisLoc);
diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp
index 2c52f7f..c6ecdea 100644
--- a/lib/Serialization/ASTReader.cpp
+++ b/lib/Serialization/ASTReader.cpp
@@ -4290,9 +4290,13 @@
     return TemplateArgument(Value, T);
   }
   case TemplateArgument::Template: 
+    return TemplateArgument(ReadTemplateName(Record, Idx));
   case TemplateArgument::TemplateExpansion: {
     TemplateName Name = ReadTemplateName(Record, Idx);
-    return TemplateArgument(Name, Kind == TemplateArgument::TemplateExpansion);
+    llvm::Optional<unsigned> NumTemplateExpansions;
+    if (unsigned NumExpansions = Record[Idx++])
+      NumTemplateExpansions = NumExpansions - 1;
+    return TemplateArgument(Name, NumTemplateExpansions);
   }
   case TemplateArgument::Expression:
     return TemplateArgument(ReadExpr(F));
diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp
index 00d46bc..54a2648 100644
--- a/lib/Serialization/ASTWriter.cpp
+++ b/lib/Serialization/ASTWriter.cpp
@@ -3231,8 +3231,14 @@
     AddTypeRef(Arg.getIntegralType(), Record);
     break;
   case TemplateArgument::Template:
+    AddTemplateName(Arg.getAsTemplateOrTemplatePattern(), Record);
+    break;
   case TemplateArgument::TemplateExpansion:
     AddTemplateName(Arg.getAsTemplateOrTemplatePattern(), Record);
+    if (llvm::Optional<unsigned> NumExpansions = Arg.getNumTemplateExpansions())
+      Record.push_back(*NumExpansions + 1);
+    else
+      Record.push_back(0);
     break;
   case TemplateArgument::Expression:
     AddStmt(Arg.getAsExpr());