Implement instantiation of pack expansions whose pattern is a type-id
in an exception specification.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@122297 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaTemplateVariadic.cpp b/lib/Sema/SemaTemplateVariadic.cpp
index 681bc8d..f2651ef 100644
--- a/lib/Sema/SemaTemplateVariadic.cpp
+++ b/lib/Sema/SemaTemplateVariadic.cpp
@@ -259,6 +259,11 @@
     .TraverseTemplateArgumentLoc(Arg);
 }
 
+void Sema::collectUnexpandedParameterPacks(QualType T,
+                   llvm::SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) {
+  CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseType(T);  
+}  
+
 ParsedTemplateArgument 
 Sema::ActOnPackExpansion(const ParsedTemplateArgument &Arg,
                          SourceLocation EllipsisLoc) {
@@ -327,3 +332,78 @@
          Pattern->getTypeLoc().getFullDataSize());
   return TSResult;
 }
+
+
+bool Sema::CheckParameterPacksForExpansion(SourceLocation EllipsisLoc,
+                                           SourceRange PatternRange,
+                                     const UnexpandedParameterPack *Unexpanded,
+                                           unsigned NumUnexpanded,
+                             const MultiLevelTemplateArgumentList &TemplateArgs,
+                                           bool &ShouldExpand,
+                                           unsigned &NumExpansions) {                                        
+  ShouldExpand = true;
+  std::pair<IdentifierInfo *, SourceLocation> FirstPack;
+  bool HaveFirstPack = false;
+  
+  for (unsigned I = 0; I != NumUnexpanded; ++I) {
+    // Compute the depth and index for this parameter pack.
+    unsigned Depth;
+    unsigned Index;
+    IdentifierInfo *Name;
+    
+    if (const TemplateTypeParmType *TTP
+        = Unexpanded[I].first.dyn_cast<const TemplateTypeParmType *>()) {
+      Depth = TTP->getDepth();
+      Index = TTP->getIndex();
+      Name = TTP->getName();
+    } else {
+      NamedDecl *ND = Unexpanded[I].first.get<NamedDecl *>();
+      if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(ND)) {
+        Depth = TTP->getDepth();
+        Index = TTP->getIndex();
+      } else if (NonTypeTemplateParmDecl *NTTP
+                 = dyn_cast<NonTypeTemplateParmDecl>(ND)) {        
+        Depth = NTTP->getDepth();
+        Index = NTTP->getIndex();
+      } else {
+        TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(ND);
+        Depth = TTP->getDepth();
+        Index = TTP->getIndex();
+      }
+      // FIXME: Variadic templates function parameter packs?
+      Name = ND->getIdentifier();
+    }
+    
+    // If we don't have a template argument at this depth/index, then we 
+    // cannot expand the pack expansion. Make a note of this, but we still 
+    // want to check that any parameter packs we *do* have arguments for.
+    if (!TemplateArgs.hasTemplateArgument(Depth, Index)) {
+      ShouldExpand = false;
+      continue;
+    }
+    
+    // Determine the size of the argument pack.
+    unsigned NewPackSize = TemplateArgs(Depth, Index).pack_size();
+    if (!HaveFirstPack) {
+      // The is the first pack we've seen for which we have an argument. 
+      // Record it.
+      NumExpansions = NewPackSize;
+      FirstPack.first = Name;
+      FirstPack.second = Unexpanded[I].second;
+      HaveFirstPack = true;
+      continue;
+    }
+    
+    if (NewPackSize != NumExpansions) {
+      // C++0x [temp.variadic]p5:
+      //   All of the parameter packs expanded by a pack expansion shall have 
+      //   the same number of arguments specified.
+      Diag(EllipsisLoc, diag::err_pack_expansion_length_conflict)
+        << FirstPack.first << Name << NumExpansions << NewPackSize
+        << SourceRange(FirstPack.second) << SourceRange(Unexpanded[I].second);
+      return true;
+    }
+  }
+  
+  return false;
+}