PR9023: A template template parameter whose template parameter list contains an
unexpanded parameter pack is a pack expansion. Thus, as with a non-type template
parameter which is a pack expansion, it needs to be expanded early into a fixed
list of template parameters.

Since the expanded list of template parameters is not itself a parameter pack,
it is permitted to appear before the end of the template parameter list, so also
remove that restriction (for both template template parameter pack expansions and
non-type template parameter pack expansions).


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@163369 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/DeclTemplate.cpp b/lib/AST/DeclTemplate.cpp
index a7e8999..fc31d2f 100644
--- a/lib/AST/DeclTemplate.cpp
+++ b/lib/AST/DeclTemplate.cpp
@@ -32,9 +32,25 @@
                                              NamedDecl **Params, unsigned NumParams,
                                              SourceLocation RAngleLoc)
   : TemplateLoc(TemplateLoc), LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc),
-    NumParams(NumParams) {
-  for (unsigned Idx = 0; Idx < NumParams; ++Idx)
-    begin()[Idx] = Params[Idx];
+    NumParams(NumParams), ContainsUnexpandedParameterPack(false) {
+  assert(this->NumParams == NumParams && "Too many template parameters");
+  for (unsigned Idx = 0; Idx < NumParams; ++Idx) {
+    NamedDecl *P = Params[Idx];
+    begin()[Idx] = P;
+
+    if (!P->isTemplateParameterPack()) {
+      if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(P))
+        if (NTTP->getType()->containsUnexpandedParameterPack())
+          ContainsUnexpandedParameterPack = true;
+
+      if (TemplateTemplateParmDecl *TTP = dyn_cast<TemplateTemplateParmDecl>(P))
+        if (TTP->getTemplateParameters()->containsUnexpandedParameterPack())
+          ContainsUnexpandedParameterPack = true;
+
+      // FIXME: If a default argument contains an unexpanded parameter pack, the
+      // template parameter list does too.
+    }
+  }
 }
 
 TemplateParameterList *
@@ -577,6 +593,19 @@
 
 void TemplateTemplateParmDecl::anchor() { }
 
+TemplateTemplateParmDecl::TemplateTemplateParmDecl(
+    DeclContext *DC, SourceLocation L, unsigned D, unsigned P,
+    IdentifierInfo *Id, TemplateParameterList *Params,
+    unsigned NumExpansions, TemplateParameterList * const *Expansions)
+  : TemplateDecl(TemplateTemplateParm, DC, L, Id, Params),
+    TemplateParmPosition(D, P), DefaultArgument(),
+    DefaultArgumentWasInherited(false), ParameterPack(true),
+    ExpandedParameterPack(true), NumExpandedParams(NumExpansions) {
+  if (Expansions)
+    std::memcpy(reinterpret_cast<void*>(this + 1), Expansions,
+                sizeof(TemplateParameterList*) * NumExpandedParams);
+}
+
 TemplateTemplateParmDecl *
 TemplateTemplateParmDecl::Create(const ASTContext &C, DeclContext *DC,
                                  SourceLocation L, unsigned D, unsigned P,
@@ -587,12 +616,35 @@
 }
 
 TemplateTemplateParmDecl *
+TemplateTemplateParmDecl::Create(const ASTContext &C, DeclContext *DC,
+                                 SourceLocation L, unsigned D, unsigned P,
+                                 IdentifierInfo *Id,
+                                 TemplateParameterList *Params,
+                            llvm::ArrayRef<TemplateParameterList*> Expansions) {
+  void *Mem = C.Allocate(sizeof(TemplateTemplateParmDecl) +
+                         sizeof(TemplateParameterList*) * Expansions.size());
+  return new (Mem) TemplateTemplateParmDecl(DC, L, D, P, Id, Params,
+                                            Expansions.size(),
+                                            Expansions.data());
+}
+
+TemplateTemplateParmDecl *
 TemplateTemplateParmDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
   void *Mem = AllocateDeserializedDecl(C, ID, sizeof(TemplateTemplateParmDecl));
   return new (Mem) TemplateTemplateParmDecl(0, SourceLocation(), 0, 0, false,
                                             0, 0);
 }
 
+TemplateTemplateParmDecl *
+TemplateTemplateParmDecl::CreateDeserialized(ASTContext &C, unsigned ID,
+                                             unsigned NumExpansions) {
+  unsigned Size = sizeof(TemplateTemplateParmDecl) +
+                  sizeof(TemplateParameterList*) * NumExpansions;
+  void *Mem = AllocateDeserializedDecl(C, ID, Size);
+  return new (Mem) TemplateTemplateParmDecl(0, SourceLocation(), 0, 0, 0, 0,
+                                            NumExpansions, 0);
+}
+
 //===----------------------------------------------------------------------===//
 // TemplateArgumentList Implementation
 //===----------------------------------------------------------------------===//