Properly rebuild pack expansions whose pattern is a non-type template
argument. As part of this, be more careful when determining if there
are any parameter packs that cannot be expanded.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@122776 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index c3cfbb8..1835899 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -3937,7 +3937,7 @@
       continue;
     }
 
-    // We can have a pack expansion of any of the above.
+    // We can have a pack expansion of any of the bullets below.
     if (PackExpansionExpr *Expansion = dyn_cast<PackExpansionExpr>(ArgExpr))
       ArgExpr = Expansion->getPattern();
     
diff --git a/lib/Sema/SemaTemplateVariadic.cpp b/lib/Sema/SemaTemplateVariadic.cpp
index 828d2a3..a3e308f 100644
--- a/lib/Sema/SemaTemplateVariadic.cpp
+++ b/lib/Sema/SemaTemplateVariadic.cpp
@@ -428,7 +428,8 @@
     // 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 any parameter packs we *do* have arguments for.
-    if (!TemplateArgs.hasTemplateArgument(Depth, Index)) {
+    if (Depth >= TemplateArgs.getNumLevels() ||
+        !TemplateArgs.hasTemplateArgument(Depth, Index)) {
       ShouldExpand = false;
       continue;
     }
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index 9088ae0..c38902a 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -2102,11 +2102,18 @@
   TemplateArgumentLoc RebuildPackExpansion(TemplateArgumentLoc Pattern,
                                            SourceLocation EllipsisLoc) {
     switch (Pattern.getArgument().getKind()) {
-    case TemplateArgument::Expression:
-        // FIXME: We should be able to handle this now!
+    case TemplateArgument::Expression: {
+      ExprResult Result
+        = getSema().ActOnPackExpansion(Pattern.getSourceExpression(),
+                                       EllipsisLoc);
+      if (Result.isInvalid())
+        return TemplateArgumentLoc();
+          
+      return TemplateArgumentLoc(Result.get(), Result.get());
+    }
         
     case TemplateArgument::Template:
-      llvm_unreachable("Unsupported pack expansion of expressions/templates");
+      llvm_unreachable("Unsupported pack expansion of templates");
         
     case TemplateArgument::Null:
     case TemplateArgument::Integral:
diff --git a/test/CXX/temp/temp.decls/temp.variadic/multi-level-substitution.cpp b/test/CXX/temp/temp.decls/temp.variadic/multi-level-substitution.cpp
new file mode 100644
index 0000000..649c9b8
--- /dev/null
+++ b/test/CXX/temp/temp.decls/temp.variadic/multi-level-substitution.cpp
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s
+
+template<typename T, T ...Values> struct value_tuple {};
+
+template<typename T>
+struct X0 {
+  template<T ...Values>
+  void f(value_tuple<T, Values...> * = 0);
+};
+
+void test_X0() {
+  X0<int>().f<1, 2, 3, 4, 5>();
+}
diff --git a/test/CXX/temp/temp.decls/temp.variadic/p5.cpp b/test/CXX/temp/temp.decls/temp.variadic/p5.cpp
index d52d9c5..729a6a0 100644
--- a/test/CXX/temp/temp.decls/temp.variadic/p5.cpp
+++ b/test/CXX/temp/temp.decls/temp.variadic/p5.cpp
@@ -212,7 +212,6 @@
 // FIXME: Test for unexpanded parameter packs in each of the statements.
 
 // Test unexpanded parameter packs in partial specializations.
-
 template<typename ...Types>
 struct TestUnexpandedDecls<int, Types>; // expected-error{{partial specialization contains unexpanded parameter pack 'Types'}}