Replace the representation of template template argument pack
expansions with something that is easier to use correctly: a new
template argment kind, rather than a bit on an existing kind. Update
all of the switch statements that deal with template arguments, fixing
a few latent bugs in the process. I"m happy with this representation,
now.

And, oh look! Template instantiation and deduction work for template
template argument pack expansions.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@122896 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index b452060..6e7f7c3 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -2692,7 +2692,12 @@
 
     case TemplateArgument::Template:
       return TemplateArgument(getCanonicalTemplateName(Arg.getAsTemplate()));
-      
+
+    case TemplateArgument::TemplateExpansion:
+      return TemplateArgument(getCanonicalTemplateName(
+                                         Arg.getAsTemplateOrTemplatePattern()),
+                              true);
+
     case TemplateArgument::Integral:
       return TemplateArgument(*Arg.getAsIntegral(),
                               getCanonicalType(Arg.getIntegralType()));
diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp
index 70c8632..5a94de9 100644
--- a/lib/AST/ASTImporter.cpp
+++ b/lib/AST/ASTImporter.cpp
@@ -301,7 +301,12 @@
     return IsStructurallyEquivalent(Context, 
                                     Arg1.getAsTemplate(), 
                                     Arg2.getAsTemplate());
-      
+
+  case TemplateArgument::TemplateExpansion:
+    return IsStructurallyEquivalent(Context, 
+                                    Arg1.getAsTemplateOrTemplatePattern(), 
+                                    Arg2.getAsTemplateOrTemplatePattern());
+
   case TemplateArgument::Expression:
     return IsStructurallyEquivalent(Context, 
                                     Arg1.getAsExpr(), Arg2.getAsExpr());
@@ -1785,7 +1790,16 @@
     
     return TemplateArgument(ToTemplate);
   }
-      
+
+  case TemplateArgument::TemplateExpansion: {
+    TemplateName ToTemplate 
+      = Importer.Import(From.getAsTemplateOrTemplatePattern());
+    if (ToTemplate.isNull())
+      return TemplateArgument();
+    
+    return TemplateArgument(ToTemplate, true);
+  }
+
   case TemplateArgument::Expression:
     if (Expr *ToExpr = Importer.Import(From.getAsExpr()))
       return TemplateArgument(ToExpr);
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index 08272e7..5b82ddd 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -179,7 +179,9 @@
       break;
 
     case TemplateArgument::Template:
-      if (TemplateDecl *Template = Args[I].getAsTemplate().getAsTemplateDecl())
+    case TemplateArgument::TemplateExpansion:
+      if (TemplateDecl *Template 
+                = Args[I].getAsTemplateOrTemplatePattern().getAsTemplateDecl())
         LV = merge(LV, getLVForDecl(Template, F));
       break;
 
diff --git a/lib/AST/DumpXML.cpp b/lib/AST/DumpXML.cpp
index 7465ea4..65a18aa 100644
--- a/lib/AST/DumpXML.cpp
+++ b/lib/AST/DumpXML.cpp
@@ -319,6 +319,10 @@
       break;
     }
     case TemplateArgument::Template:
+    case TemplateArgument::TemplateExpansion:
+      // FIXME: Implement!
+      break;
+        
     case TemplateArgument::Declaration: {
       visitDeclRef(A.getAsDecl());
       break;
diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp
index 17a9326..63c3197 100644
--- a/lib/AST/StmtProfile.cpp
+++ b/lib/AST/StmtProfile.cpp
@@ -972,7 +972,8 @@
     break;
 
   case TemplateArgument::Template:
-    VisitTemplateName(Arg.getAsTemplate());
+  case TemplateArgument::TemplateExpansion:
+    VisitTemplateName(Arg.getAsTemplateOrTemplatePattern());
     break;
       
   case TemplateArgument::Declaration:
diff --git a/lib/AST/TemplateBase.cpp b/lib/AST/TemplateBase.cpp
index 6eae6a4..de5531f 100644
--- a/lib/AST/TemplateBase.cpp
+++ b/lib/AST/TemplateBase.cpp
@@ -39,7 +39,10 @@
 
   case Template:
     return getAsTemplate().isDependent();
-      
+
+  case TemplateExpansion:
+    return true;
+
   case Declaration:
     if (DeclContext *DC = dyn_cast<DeclContext>(getAsDecl()))
       return DC->isDependentContext();
@@ -70,14 +73,15 @@
   case Declaration:
   case Integral:
   case Pack:    
+  case Template:
     return false;
       
+  case TemplateExpansion:
+    return true;
+      
   case Type:
     return isa<PackExpansionType>(getAsType());
-      
-  case Template:
-    return TemplateArg.PackExpansion;
-    
+          
   case Expression:
     return isa<PackExpansionExpr>(getAsExpr());
   }
@@ -90,6 +94,7 @@
   case Null:
   case Declaration:
   case Integral:
+  case TemplateExpansion:
     break;
 
   case Type:
@@ -98,8 +103,7 @@
     break;
 
   case Template:
-    if (!TemplateArg.PackExpansion && 
-        getAsTemplate().containsUnexpandedParameterPack())
+    if (getAsTemplate().containsUnexpandedParameterPack())
       return true;
     break;
         
@@ -135,20 +139,22 @@
     break;
 
   case Template:
-    ID.AddBoolean(TemplateArg.PackExpansion);
+  case TemplateExpansion: {
+    TemplateName Template = getAsTemplateOrTemplatePattern();
     if (TemplateTemplateParmDecl *TTP
           = dyn_cast_or_null<TemplateTemplateParmDecl>(
-                                       getAsTemplate().getAsTemplateDecl())) {
+                                                Template.getAsTemplateDecl())) {
       ID.AddBoolean(true);
       ID.AddInteger(TTP->getDepth());
       ID.AddInteger(TTP->getPosition());
       ID.AddBoolean(TTP->isParameterPack());
     } else {
       ID.AddBoolean(false);
-      ID.AddPointer(Context.getCanonicalTemplateName(getAsTemplate())
-                      .getAsVoidPointer());
+      ID.AddPointer(Context.getCanonicalTemplateName(Template)
+                                                          .getAsVoidPointer());
     }
     break;
+  }
       
   case Integral:
     getAsIntegral()->Profile(ID);
@@ -173,13 +179,11 @@
   case Null:
   case Type:
   case Declaration:
-  case Expression:
+  case Expression:      
+  case Template:
+  case TemplateExpansion:
     return TypeOrValue == Other.TypeOrValue;
 
-  case Template:
-    return TemplateArg.Template == Other.TemplateArg.Template &&
-           TemplateArg.PackExpansion == Other.TemplateArg.PackExpansion;
-      
   case Integral:
     return getIntegralType() == Other.getIntegralType() &&
            *getAsIntegral() == *Other.getAsIntegral();
@@ -206,13 +210,14 @@
   case Expression:
     return cast<PackExpansionExpr>(getAsExpr())->getPattern();
     
-  case Template:
-    return TemplateArgument(getAsTemplate(), false);
+  case TemplateExpansion:
+    return TemplateArgument(getAsTemplateOrTemplatePattern(), false);
     
   case Declaration:
   case Integral:
   case Pack:
   case Null:
+  case Template:
     return TemplateArgument();
   }
   
@@ -248,13 +253,15 @@
     break;
   }
     
-  case Template: {
+  case Template:
     getAsTemplate().print(Out, Policy);
-    if (TemplateArg.PackExpansion)
-      Out << "...";
     break;
-  }
-    
+
+  case TemplateExpansion:
+    getAsTemplateOrTemplatePattern().print(Out, Policy);
+    Out << "...";
+    break;
+      
   case Integral: {
     Out << getAsIntegral()->toString(10);
     break;
@@ -299,15 +306,18 @@
     else
       return SourceRange();
 
-  case TemplateArgument::Template: {
-    SourceLocation End = getTemplateNameLoc();
-    if (getTemplateEllipsisLoc().isValid())
-      End = getTemplateEllipsisLoc();
+  case TemplateArgument::Template:
     if (getTemplateQualifierRange().isValid())
-      return SourceRange(getTemplateQualifierRange().getBegin(), End);
-    return SourceRange(getTemplateNameLoc(), End);
-  }
-      
+      return SourceRange(getTemplateQualifierRange().getBegin(), 
+                         getTemplateNameLoc());
+    return SourceRange(getTemplateNameLoc());
+
+  case TemplateArgument::TemplateExpansion:
+    if (getTemplateQualifierRange().isValid())
+      return SourceRange(getTemplateQualifierRange().getBegin(), 
+                         getTemplateEllipsisLoc());
+    return SourceRange(getTemplateNameLoc(), getTemplateEllipsisLoc());
+
   case TemplateArgument::Integral:
   case TemplateArgument::Pack:
   case TemplateArgument::Null:
@@ -355,13 +365,14 @@
     Expr *Pattern = cast<PackExpansionExpr>(Argument.getAsExpr())->getPattern();
     return TemplateArgumentLoc(Pattern, Pattern);
   }
-      
-  case TemplateArgument::Template:
+
+  case TemplateArgument::TemplateExpansion:
     return TemplateArgumentLoc(Argument.getPackExpansionPattern(),
                                getTemplateQualifierRange(),
                                getTemplateNameLoc());
     
   case TemplateArgument::Declaration:
+  case TemplateArgument::Template:
   case TemplateArgument::Integral:
   case TemplateArgument::Pack:
   case TemplateArgument::Null:
@@ -389,11 +400,11 @@
     return DB << Arg.getAsIntegral()->toString(10);
       
   case TemplateArgument::Template:
-    DB << Arg.getAsTemplate();
-    if (Arg.isPackExpansion())
-      DB << "...";
-    return DB;
-      
+    return DB << Arg.getAsTemplate();
+
+  case TemplateArgument::TemplateExpansion:
+    return DB << Arg.getAsTemplateOrTemplatePattern() << "...";
+
   case TemplateArgument::Expression: {
     // This shouldn't actually ever happen, so it's okay that we're
     // regurgitating an expression here.
diff --git a/lib/CodeGen/Mangle.cpp b/lib/CodeGen/Mangle.cpp
index 0969b87..ff0e922 100644
--- a/lib/CodeGen/Mangle.cpp
+++ b/lib/CodeGen/Mangle.cpp
@@ -2169,6 +2169,11 @@
     // This is mangled as <type>.
     mangleType(A.getAsTemplate());
     break;
+  case TemplateArgument::TemplateExpansion:
+    // This is mangled as Dp <type>.
+    Out << "Dp";
+    mangleType(A.getAsTemplateOrTemplatePattern());
+    break;
   case TemplateArgument::Expression:
     Out << 'X';
     mangleExpression(A.getAsExpr());
diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp
index 5ed973b..161908e 100644
--- a/lib/Sema/SemaLookup.cpp
+++ b/lib/Sema/SemaLookup.cpp
@@ -1693,11 +1693,12 @@
       addAssociatedClassesAndNamespaces(Result, Arg.getAsType());
       break;
 
-    case TemplateArgument::Template: {
+    case TemplateArgument::Template: 
+    case TemplateArgument::TemplateExpansion: {
       // [...] the namespaces in which any template template arguments are
       // defined; and the classes in which any member templates used as
       // template template arguments are defined.
-      TemplateName Template = Arg.getAsTemplate();
+      TemplateName Template = Arg.getAsTemplateOrTemplatePattern();
       if (ClassTemplateDecl *ClassTemplate
                  = dyn_cast<ClassTemplateDecl>(Template.getAsTemplateDecl())) {
         DeclContext *Ctx = ClassTemplate->getDeclContext();
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 9adcf1c8..2c9a430 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -2256,10 +2256,12 @@
       break;
       
     case TemplateArgument::Template:
+    case TemplateArgument::TemplateExpansion:
       // We were given a template template argument. It may not be ill-formed;
       // see below.
       if (DependentTemplateName *DTN
-            = Arg.getArgument().getAsTemplate().getAsDependentTemplateName()) {
+            = Arg.getArgument().getAsTemplateOrTemplatePattern()
+                                              .getAsDependentTemplateName()) {
         // We have a template argument such as \c T::template X, which we
         // parsed as a template template argument. However, since we now
         // know that we need a non-type template argument, convert this
@@ -2273,6 +2275,17 @@
                                                Arg.getTemplateQualifierRange(),
                                                     NameInfo);
         
+        // If we parsed the template argument as a pack expansion, create a
+        // pack expansion expression.
+        if (Arg.getArgument().getKind() == TemplateArgument::TemplateExpansion){
+          ExprResult Expansion = ActOnPackExpansion(E, 
+                                                  Arg.getTemplateEllipsisLoc());
+          if (Expansion.isInvalid())
+            return true;
+          
+          E = Expansion.get();
+        }
+        
         TemplateArgument Result;
         if (CheckTemplateArgument(NTTP, NTTPType, E, Result))
           return true;
@@ -2348,6 +2361,7 @@
     return true;
     
   case TemplateArgument::Template:
+  case TemplateArgument::TemplateExpansion:
     if (CheckTemplateArgument(TempParm, Arg))
       return true;
       
diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp
index a72a293..5837ebd 100644
--- a/lib/Sema/SemaTemplateDeduction.cpp
+++ b/lib/Sema/SemaTemplateDeduction.cpp
@@ -168,7 +168,16 @@
     
     // All other combinations are incompatible.
     return DeducedTemplateArgument();      
-      
+
+  case TemplateArgument::TemplateExpansion:
+    if (Y.getKind() == TemplateArgument::TemplateExpansion &&
+        Context.hasSameTemplateName(X.getAsTemplateOrTemplatePattern(), 
+                                    Y.getAsTemplateOrTemplatePattern()))
+      return X;
+    
+    // All other combinations are incompatible.
+    return DeducedTemplateArgument();      
+
   case TemplateArgument::Expression:
     // If we deduced a dependent expression in one case and either an integral 
     // constant or a declaration in another case, keep the integral constant 
@@ -934,7 +943,7 @@
     Info.FirstArg = Param;
     Info.SecondArg = Arg;
     return Sema::TDK_NonDeducedMismatch;
-      
+
   case TemplateArgument::Template:
     if (Arg.getKind() == TemplateArgument::Template)
       return DeduceTemplateArguments(S, TemplateParams, 
@@ -943,6 +952,10 @@
     Info.FirstArg = Param;
     Info.SecondArg = Arg;
     return Sema::TDK_NonDeducedMismatch;
+
+  case TemplateArgument::TemplateExpansion:
+    llvm_unreachable("caller should handle pack expansions");
+    break;
       
   case TemplateArgument::Declaration:
     if (Arg.getKind() == TemplateArgument::Declaration &&
@@ -1282,10 +1295,11 @@
              Y.getAsDecl()->getCanonicalDecl();
 
     case TemplateArgument::Template:
-      return Context.getCanonicalTemplateName(X.getAsTemplate())
-               .getAsVoidPointer() ==
-             Context.getCanonicalTemplateName(Y.getAsTemplate())
-               .getAsVoidPointer();
+    case TemplateArgument::TemplateExpansion:
+      return Context.getCanonicalTemplateName(
+                    X.getAsTemplateOrTemplatePattern()).getAsVoidPointer() ==
+             Context.getCanonicalTemplateName(
+                    Y.getAsTemplateOrTemplatePattern()).getAsVoidPointer();
       
     case TemplateArgument::Integral:
       return *X.getAsIntegral() == *Y.getAsIntegral();
@@ -1356,9 +1370,11 @@
   }
     
   case TemplateArgument::Template:
-    return TemplateArgumentLoc(Arg, SourceRange(), Loc,
-                               Arg.isPackExpansion()? Loc : SourceLocation());
-    
+    return TemplateArgumentLoc(Arg, SourceRange(), Loc);
+
+  case TemplateArgument::TemplateExpansion:
+    return TemplateArgumentLoc(Arg, SourceRange(), Loc, Loc);
+
   case TemplateArgument::Expression:
     return TemplateArgumentLoc(Arg, Arg.getAsExpr());
     
@@ -3244,7 +3260,9 @@
     break;
 
   case TemplateArgument::Template:
-    MarkUsedTemplateParameters(SemaRef, TemplateArg.getAsTemplate(), 
+  case TemplateArgument::TemplateExpansion:
+    MarkUsedTemplateParameters(SemaRef, 
+                               TemplateArg.getAsTemplateOrTemplatePattern(), 
                                OnlyDeduced, Depth, Used);
     break;
 
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index 919f2c8..d15f91a 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -2123,12 +2123,18 @@
     }
         
     case TemplateArgument::Template:
-      llvm_unreachable("Unsupported pack expansion of templates");
+      return TemplateArgumentLoc(TemplateArgument(
+                                          Pattern.getArgument().getAsTemplate(),
+                                                  true),
+                                 Pattern.getTemplateQualifierRange(),
+                                 Pattern.getTemplateNameLoc(),
+                                 EllipsisLoc);
         
     case TemplateArgument::Null:
     case TemplateArgument::Integral:
     case TemplateArgument::Declaration:
     case TemplateArgument::Pack:
+    case TemplateArgument::TemplateExpansion:
       llvm_unreachable("Pack expansion pattern has no parameter packs");
         
     case TemplateArgument::Type:
@@ -2531,7 +2537,11 @@
   case TemplateArgument::Template:
     Output = TemplateArgumentLoc(Arg, SourceRange(), Loc);
     break;
-      
+
+  case TemplateArgument::TemplateExpansion:
+    Output = TemplateArgumentLoc(Arg, SourceRange(), Loc, Loc);
+    break;
+
   case TemplateArgument::Expression:
     Output = TemplateArgumentLoc(Arg, Arg.getAsExpr());
     break;
@@ -2600,7 +2610,10 @@
                                  Input.getTemplateNameLoc());
     return false;
   }
-      
+
+  case TemplateArgument::TemplateExpansion:
+    llvm_unreachable("Caller should expand pack expansions");
+
   case TemplateArgument::Expression: {
     // Template argument expressions are not potentially evaluated.
     EnterExpressionEvaluationContext Unevaluated(getSema(),
diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp
index ed0e58f..3bf51e6 100644
--- a/lib/Serialization/ASTReader.cpp
+++ b/lib/Serialization/ASTReader.cpp
@@ -3381,6 +3381,12 @@
   case TemplateArgument::Template: {
     SourceRange QualifierRange = ReadSourceRange(F, Record, Index);
     SourceLocation TemplateNameLoc = ReadSourceLocation(F, Record, Index);
+    return TemplateArgumentLocInfo(QualifierRange, TemplateNameLoc,
+                                   SourceLocation());
+  }
+  case TemplateArgument::TemplateExpansion: {
+    SourceRange QualifierRange = ReadSourceRange(F, Record, Index);
+    SourceLocation TemplateNameLoc = ReadSourceLocation(F, Record, Index);
     SourceLocation EllipsisLoc = ReadSourceLocation(F, Record, Index);
     return TemplateArgumentLocInfo(QualifierRange, TemplateNameLoc, 
                                    EllipsisLoc);
@@ -4216,7 +4222,8 @@
 TemplateArgument
 ASTReader::ReadTemplateArgument(PerFileData &F,
                                 const RecordData &Record, unsigned &Idx) {
-  switch ((TemplateArgument::ArgKind)Record[Idx++]) {
+  TemplateArgument::ArgKind Kind = (TemplateArgument::ArgKind)Record[Idx++];
+  switch (Kind) {
   case TemplateArgument::Null:
     return TemplateArgument();
   case TemplateArgument::Type:
@@ -4228,10 +4235,10 @@
     QualType T = GetType(Record[Idx++]);
     return TemplateArgument(Value, T);
   }
-  case TemplateArgument::Template: {
+  case TemplateArgument::Template: 
+  case TemplateArgument::TemplateExpansion: {
     TemplateName Name = ReadTemplateName(Record, Idx);
-    bool IsPackExpansion = Record[Idx++];
-    return TemplateArgument(Name, IsPackExpansion);
+    return TemplateArgument(Name, Kind == TemplateArgument::TemplateExpansion);
   }
   case TemplateArgument::Expression:
     return TemplateArgument(ReadExpr(F));
diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp
index 44f17e4..2c0239d 100644
--- a/lib/Serialization/ASTWriter.cpp
+++ b/lib/Serialization/ASTWriter.cpp
@@ -2889,6 +2889,10 @@
   case TemplateArgument::Template:
     AddSourceRange(Arg.getTemplateQualifierRange(), Record);
     AddSourceLocation(Arg.getTemplateNameLoc(), Record);
+    break;
+  case TemplateArgument::TemplateExpansion:
+    AddSourceRange(Arg.getTemplateQualifierRange(), Record);
+    AddSourceLocation(Arg.getTemplateNameLoc(), Record);
     AddSourceLocation(Arg.getTemplateEllipsisLoc(), Record);
     break;
   case TemplateArgument::Null:
@@ -3176,8 +3180,8 @@
     AddTypeRef(Arg.getIntegralType(), Record);
     break;
   case TemplateArgument::Template:
-    AddTemplateName(Arg.getAsTemplate(), Record);
-    Record.push_back(Arg.isPackExpansion());
+  case TemplateArgument::TemplateExpansion:
+    AddTemplateName(Arg.getAsTemplateOrTemplatePattern(), Record);
     break;
   case TemplateArgument::Expression:
     AddStmt(Arg.getAsExpr());