Merging r221832:

------------------------------------------------------------------------
r221832 | richard-llvm | 2014-11-12 18:38:38 -0500 (Wed, 12 Nov 2014) | 5 lines

PR19372: Keep checking template arguments after we see an argument pack
expansion into a parameter pack; we know that we're still filling in that
parameter's arguments. Previously, if we hit this case for an alias template,
we'd try to substitute using non-canonical template arguments.

------------------------------------------------------------------------

git-svn-id: https://llvm.org/svn/llvm-project/cfe/branches/release_35@223719 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 5596a01..7e8f0b7 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -3692,12 +3692,12 @@
                                 ArgumentPack.size(), Converted))
         return true;
 
-      if (TemplateArgs[ArgIdx].getArgument().isPackExpansion() &&
-          isa<TypeAliasTemplateDecl>(Template) &&
-          !(Param + 1 == ParamEnd && (*Param)->isTemplateParameterPack() &&
-            !getExpandedPackSize(*Param))) {
+      bool PackExpansionIntoNonPack =
+          TemplateArgs[ArgIdx].getArgument().isPackExpansion() &&
+          (!(*Param)->isTemplateParameterPack() || getExpandedPackSize(*Param));
+      if (PackExpansionIntoNonPack && isa<TypeAliasTemplateDecl>(Template)) {
         // Core issue 1430: we have a pack expansion as an argument to an
-        // alias template, and it's not part of a final parameter pack. This
+        // alias template, and it's not part of a parameter pack. This
         // can't be canonicalized, so reject it now.
         Diag(TemplateArgs[ArgIdx].getLocation(),
              diag::err_alias_template_expansion_into_fixed_list)
@@ -3720,16 +3720,11 @@
         ++Param;
       }
 
-      // If we just saw a pack expansion, then directly convert the remaining
-      // arguments, because we don't know what parameters they'll match up
-      // with.
-      if (TemplateArgs[ArgIdx-1].getArgument().isPackExpansion()) {
-        bool InFinalParameterPack = Param != ParamEnd &&
-                                    Param + 1 == ParamEnd &&
-                                    (*Param)->isTemplateParameterPack() &&
-                                    !getExpandedPackSize(*Param);
-
-        if (!InFinalParameterPack && !ArgumentPack.empty()) {
+      // If we just saw a pack expansion into a non-pack, then directly convert
+      // the remaining arguments, because we don't know what parameters they'll
+      // match up with.
+      if (PackExpansionIntoNonPack) {
+        if (!ArgumentPack.empty()) {
           // If we were part way through filling in an expanded parameter pack,
           // fall back to just producing individual arguments.
           Converted.insert(Converted.end(),
@@ -3738,22 +3733,10 @@
         }
 
         while (ArgIdx < NumArgs) {
-          if (InFinalParameterPack)
-            ArgumentPack.push_back(TemplateArgs[ArgIdx].getArgument());
-          else
-            Converted.push_back(TemplateArgs[ArgIdx].getArgument());
+          Converted.push_back(TemplateArgs[ArgIdx].getArgument());
           ++ArgIdx;
         }
 
-        // Push the argument pack onto the list of converted arguments.
-        if (InFinalParameterPack && !ArgumentPack.empty()) {
-          Converted.push_back(
-            TemplateArgument::CreatePackCopy(Context,
-                                             ArgumentPack.data(),
-                                             ArgumentPack.size()));
-          ArgumentPack.clear();
-        }
-
         return false;
       }
 
diff --git a/test/SemaTemplate/deduction.cpp b/test/SemaTemplate/deduction.cpp
index c089573..e942289 100644
--- a/test/SemaTemplate/deduction.cpp
+++ b/test/SemaTemplate/deduction.cpp
@@ -178,3 +178,17 @@
   template<typename ...T> void f(S<T...>);
   void g() { f(S<int, int>()); }
 }
+
+namespace PR19372 {
+  template <template<typename...> class C, typename ...Us> struct BindBack {
+    template <typename ...Ts> using apply = C<Ts..., Us...>;
+  };
+  template <typename, typename...> struct Y;
+  template <typename ...Ts> using Z = Y<Ts...>;
+
+  using T = BindBack<Z, int>::apply<>;
+  using T = Z<int>;
+
+  using U = BindBack<Z, int, int>::apply<char>;
+  using U = Z<char, int, int>;
+}