commit dca90afa40bc6dae2198c18e60bc07334772564d
Author: Jason Merrill <jason@redhat.com>
Date:   Tue Sep 27 01:38:51 2011 -0400

    	PR c++/35722
    	Implement N2555 (expanding pack expansion to fixed parm list)
    	* pt.c (coerce_template_parms): Allow expanding a pack expansion
    	to a fixed-length argument list.
    	(unify_pack_expansion): Handle explicit args properly.
    	(unify) [TREE_VEC]: Handle pack expansions here.
    	[TYPE_ARGUMENT_PACK]: Not here.
    	(tsubst_pack_expansion): Don't try to do partial substitution.
    	(pack_deducible_p): New.
    	(fn_type_unification): Use it.
    	(find_parameter_packs_r): Take the TYPE_MAIN_VARIANT
    	of a type parameter.
    	(check_non_deducible_conversion): Split out from fn_type_unification.

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 4d57f94..1b7337e 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -2961,6 +2961,7 @@ find_parameter_packs_r (tree *tp, int *walk_subtrees, void* data)
       break;
 
     case TEMPLATE_TYPE_PARM:
+      t = TYPE_MAIN_VARIANT (t);
     case TEMPLATE_TEMPLATE_PARM:
       if (TEMPLATE_TYPE_PARAMETER_PACK (t))
         parameter_pack_p = true;
@@ -6741,22 +6742,10 @@ coerce_template_parms (tree parms,
 	{
           if (PACK_EXPANSION_P (arg))
             {
-	      if (complain & tf_error)
-		{
-		  /* FIXME this restriction was removed by N2555; see
-		     bug 35722.  */
-		  /* If ARG is a pack expansion, but PARM is not a
-		     template parameter pack (if it were, we would have
-		     handled it above), we're trying to expand into a
-		     fixed-length argument list.  */
-		  if (TREE_CODE (arg) == EXPR_PACK_EXPANSION)
-		    sorry ("cannot expand %<%E%> into a fixed-length "
-			   "argument list", arg);
-		  else
-		    sorry ("cannot expand %<%T%> into a fixed-length "
-			   "argument list", arg);
-		}
-	      ++lost;
+              /* We don't know how many args we have yet, just
+                 use the unconverted ones for now.  */
+              new_inner_args = args;
+              break;
             }
         }
       else if (require_all_args)
@@ -9116,7 +9105,6 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
   tree pack, packs = NULL_TREE, unsubstituted_packs = NULL_TREE;
   int i, len = -1;
   tree result;
-  int incomplete = 0;
   htab_t saved_local_specializations = NULL;
 
   gcc_assert (PACK_EXPANSION_P (t));
@@ -9189,21 +9177,15 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
           int my_len = 
             TREE_VEC_LENGTH (ARGUMENT_PACK_ARGS (arg_pack));
 
-          /* It's all-or-nothing with incomplete argument packs.  */
-          if (incomplete && !ARGUMENT_PACK_INCOMPLETE_P (arg_pack))
-            return error_mark_node;
-          
+	  /* Don't bother trying to do a partial substitution with
+	     incomplete packs; we'll try again after deduction.  */
           if (ARGUMENT_PACK_INCOMPLETE_P (arg_pack))
-            incomplete = 1;
+            return t;
 
           if (len < 0)
 	    len = my_len;
           else if (len != my_len)
             {
-	      if (incomplete)
-		/* We got explicit args for some packs but not others;
-		   do nothing now and try again after deduction.  */
-		return t;
               if (TREE_CODE (t) == TYPE_PACK_EXPANSION)
                 error ("mismatched argument pack lengths while expanding "
                        "%<%T%>",
@@ -9261,8 +9243,8 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
 
   /* For each argument in each argument pack, substitute into the
      pattern.  */
-  result = make_tree_vec (len + incomplete);
-  for (i = 0; i < len + incomplete; ++i)
+  result = make_tree_vec (len);
+  for (i = 0; i < len; ++i)
     {
       /* For parameter pack, change the substitution of the parameter
          pack to the ith argument in its argument pack, then expand
@@ -9307,13 +9289,6 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
       else
         TREE_VEC_ELT (result, i) = tsubst (pattern, args, complain, in_decl);
 
-      if (i == len)
-        /* When we have incomplete argument packs, the last "expanded"
-           result is itself a pack expansion, which allows us
-           to deduce more arguments.  */
-        TREE_VEC_ELT (result, i) = 
-          make_pack_expansion (TREE_VEC_ELT (result, i));
-
       if (TREE_VEC_ELT (result, i) == error_mark_node)
 	{
 	  result = error_mark_node;
@@ -14289,6 +14264,40 @@ pop_deduction_access_scope (tree tmpl)
     pop_deferring_access_checks ();
 }
 
+/* PARM is a template parameter pack for FN.  Returns true iff
+   PARM is used in a deducible way in the argument list of FN.  */
+
+static bool
+pack_deducible_p (tree parm, tree fn)
+{
+  tree t = FUNCTION_FIRST_USER_PARMTYPE (fn);
+  for (; t; t = TREE_CHAIN (t))
+    {
+      tree type = TREE_VALUE (t);
+      tree packs;
+      if (!PACK_EXPANSION_P (type))
+	continue;
+      for (packs = PACK_EXPANSION_PARAMETER_PACKS (type);
+	   packs; packs = TREE_CHAIN (packs))
+	if (TREE_VALUE (packs) == parm)
+	  {
+	    /* The template parameter pack is used in a function parameter
+	       pack.  If this is the end of the parameter list, the
+	       template parameter pack is deducible.  */
+	    if (TREE_CHAIN (t) == void_list_node)
+	      return true;
+	    else
+	      /* Otherwise, not.  Well, it could be deduced from
+		 a non-pack parameter, but doing so would end up with
+		 a deduction mismatch, so don't bother.  */
+	      return false;
+	  }
+    }
+  /* The template parameter pack isn't used in any function parameter
+     packs, but it might be used deeper, e.g. tuple<Args...>.  */
+  return true;
+}
+
 /* The FN is a TEMPLATE_DECL for a function.  ARGS is an array with
    NARGS elements of the arguments that are being used when calling
    it.  TARGS is a vector into which the deduced template arguments
@@ -14334,7 +14343,6 @@ fn_type_unification (tree fn,
   tree parms;
   tree fntype;
   int result;
-  bool incomplete_argument_packs_p = false;
 
   gcc_assert (TREE_CODE (fn) == TEMPLATE_DECL);
 
@@ -14386,6 +14394,7 @@ fn_type_unification (tree fn,
         {
           tree parm = TREE_VALUE (TREE_VEC_ELT (tparms, i));
           bool parameter_pack = false;
+	  tree targ = TREE_VEC_ELT (converted_args, i);
 
           /* Dig out the actual parm.  */
           if (TREE_CODE (parm) == TYPE_DECL
@@ -14400,16 +14409,15 @@ fn_type_unification (tree fn,
               parameter_pack = TEMPLATE_PARM_PARAMETER_PACK (parm);
             }
 
-          if (parameter_pack)
-            {
-              int level, idx;
-              tree targ;
-              template_parm_level_and_index (parm, &level, &idx);
+	  if (!parameter_pack && targ == NULL_TREE)
+	    /* No explicit argument for this template parameter.  */
+	    incomplete = true;
 
+          if (parameter_pack && pack_deducible_p (parm, fn))
+            {
               /* Mark the argument pack as "incomplete". We could
                  still deduce more arguments during unification.
 	         We remove this mark in type_unification_real.  */
-              targ = TMPL_ARG (converted_args, level, idx);
               if (targ)
                 {
                   ARGUMENT_PACK_INCOMPLETE_P(targ) = 1;
@@ -14418,18 +14426,10 @@ fn_type_unification (tree fn,
                 }
 
               /* We have some incomplete argument packs.  */
-              incomplete_argument_packs_p = true;
+              incomplete = true;
             }
         }
 
-      if (incomplete_argument_packs_p)
-        /* Any substitution is guaranteed to be incomplete if there
-           are incomplete argument packs, because we can still deduce
-           more arguments.  */
-        incomplete = 1;
-      else
-        incomplete = NUM_TMPL_ARGS (explicit_targs) != NUM_TMPL_ARGS (targs);
-
       processing_template_decl += incomplete;
       fntype = deduction_tsubst_fntype (fn, converted_args,
 					(explain_p
@@ -14643,6 +14643,44 @@ maybe_adjust_types_for_deduction (unification_kind_t strict,
   return result;
 }
 
+/* Subroutine of type_unification_real and unify_pack_expansion.  PARM is a
+   function parameter of a template which does contain any deducible
+   template parameters; check if ARG is a suitable match for it.  STRICT,
+   FLAGS and EXPLAIN_P are as in fn_type_unification.  */
+
+static int
+check_non_deducible_conversion (tree parm, tree arg, int strict,
+				int flags, bool explain_p)
+{
+  tree type;
+
+  if (!TYPE_P (arg))
+    type = TREE_TYPE (arg);
+  else
+    type = arg;
+
+  if (same_type_p (parm, type))
+    return unify_success (explain_p);
+
+  if (strict == DEDUCE_CONV)
+    {
+      if (can_convert_arg (type, parm, NULL_TREE, flags))
+	return unify_success (explain_p);
+    }
+  else if (strict != DEDUCE_EXACT)
+    {
+      if (can_convert_arg (parm, type,
+			   TYPE_P (arg) ? NULL_TREE : arg,
+			   flags))
+	return unify_success (explain_p);
+    }
+
+  if (strict == DEDUCE_EXACT)
+    return unify_type_mismatch (explain_p, parm, arg);
+  else
+    return unify_arg_conversion (explain_p, parm, type, arg);
+}
+
 /* Most parms like fn_type_unification.
 
    If SUBR is 1, we're being called recursively (to unify the
@@ -14739,34 +14777,15 @@ type_unification_real (tree tparms,
 	 corresponds with a function parameter that contains only
 	 non-deducible template parameters and explicitly specified
 	 template parameters.  */
+      /* FIXME uses_deducible_template_parms */
       if (!uses_template_parms (parm))
 	{
-	  tree type;
-
-	  if (!TYPE_P (arg))
-	    type = TREE_TYPE (arg);
+	  int ret = check_non_deducible_conversion (parm, arg, strict,
+						    flags, explain_p);
+	  if (ret)
+	    return ret;
 	  else
-	    type = arg;
-
-	  if (same_type_p (parm, type))
 	    continue;
-	  if (strict == DEDUCE_CONV)
-	    {
-	      if (can_convert_arg (type, parm, NULL_TREE, flags))
-		continue;
-	    }
-	  else if (strict != DEDUCE_EXACT)
-	    {
-	      if (can_convert_arg (parm, type,
-				   TYPE_P (arg) ? NULL_TREE : arg,
-				   flags))
-		continue;
-	    }
-
-	  if (strict == DEDUCE_EXACT)
-	    return unify_type_mismatch (explain_p, parm, arg);
-	  else
-	    return unify_arg_conversion (explain_p, parm, type, arg);
 	}
 
       if (!TYPE_P (arg))
@@ -15495,21 +15514,64 @@ unify_pack_expansion (tree tparms, tree targs, tree packed_parms,
      unified and unify each with the pattern.  */
   for (i = start; i < len; i++)
     {
-      tree parm = pattern;
+      tree parm;
+      bool any_explicit = false;
+      tree arg = TREE_VEC_ELT (packed_args, i);
 
-      /* For each parameter pack, clear out the deduced value so that
-         we can deduce it again.  */
+      /* For each parameter pack, set its TMPL_ARG to either NULL_TREE
+	 or the element of its argument pack at the current index if
+	 this argument was explicitly specified.  */
       for (pack = packs; pack; pack = TREE_CHAIN (pack))
         {
           int idx, level;
+          tree arg, pargs;
           template_parm_level_and_index (TREE_PURPOSE (pack), &level, &idx);
 
-          TMPL_ARG (targs, level, idx) = NULL_TREE;
+          arg = NULL_TREE;
+          if (TREE_VALUE (pack)
+              && (pargs = ARGUMENT_PACK_EXPLICIT_ARGS (TREE_VALUE (pack)))
+              && (i < TREE_VEC_LENGTH (pargs)))
+            {
+              any_explicit = true;
+              arg = TREE_VEC_ELT (pargs, i);
+            }
+          TMPL_ARG (targs, level, idx) = arg;
         }
 
+      /* If we had explicit template arguments, substitute them into the
+	 pattern before deduction.  */
+      if (any_explicit)
+	{
+	  /* Some arguments might still be unspecified or dependent.  */
+	  bool dependent;
+	  ++processing_template_decl;
+	  dependent = any_dependent_template_arguments_p (targs);
+	  if (!dependent)
+	    --processing_template_decl;
+	  parm = tsubst (pattern, targs,
+			 explain_p ? tf_warning_or_error : tf_none,
+			 NULL_TREE);
+	  if (dependent)
+	    --processing_template_decl;
+	  if (parm == error_mark_node)
+	    return 1;
+	  /* FIXME uses_deducible_template_parms */
+	  if (!uses_template_parms (parm))
+	    {
+	      int ret = check_non_deducible_conversion (parm, arg, strict,
+							LOOKUP_IMPLICIT,
+							explain_p);
+	      if (ret)
+		return ret;
+	      else
+		goto unified;
+	    }
+	}
+      else
+	parm = pattern;
+
       /* Unify the pattern with the current argument.  */
       {
-        tree arg = TREE_VEC_ELT (packed_args, i);
 	tree arg_expr = NULL_TREE;
         int arg_strict = strict;
 
@@ -15619,21 +15681,12 @@ unify_pack_expansion (tree tparms, tree targs, tree packed_parms,
 
       if (old_pack && ARGUMENT_PACK_INCOMPLETE_P (old_pack))
         {
-          /* Prepend the explicit arguments onto NEW_ARGS.  */
+          /* If we had fewer function args than explicit template args,
+             just use the explicits.  */
           tree explicit_args = ARGUMENT_PACK_EXPLICIT_ARGS (old_pack);
-          tree old_args = new_args;
-          int i, explicit_len = TREE_VEC_LENGTH (explicit_args);
-          int len = explicit_len + TREE_VEC_LENGTH (old_args);
-
-          /* Copy the explicit arguments.  */
-          new_args = make_tree_vec (len);
-          for (i = 0; i < explicit_len; i++)
-            TREE_VEC_ELT (new_args, i) = TREE_VEC_ELT (explicit_args, i);
-
-          /* Copy the deduced arguments.  */
-          for (; i < len; i++)
-            TREE_VEC_ELT (new_args, i) =
-              TREE_VEC_ELT (old_args, i - explicit_len);
+          int explicit_len = TREE_VEC_LENGTH (explicit_args);
+          if (len < explicit_len)
+            new_args = explicit_args;
         }
 
       if (!old_pack)
@@ -16253,17 +16306,56 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict,
 
     case TREE_VEC:
       {
-	int i;
+	int i, len, argslen;
+	int parm_variadic_p = 0;
+
 	if (TREE_CODE (arg) != TREE_VEC)
 	  return unify_template_argument_mismatch (explain_p, parm, arg);
-	if (TREE_VEC_LENGTH (parm) != TREE_VEC_LENGTH (arg))
-	  return unify_arity (explain_p, TREE_VEC_LENGTH (arg),
-			      TREE_VEC_LENGTH (parm));
-	for (i = 0; i < TREE_VEC_LENGTH (parm); ++i)
-	  RECUR_AND_CHECK_FAILURE (tparms, targs,
-				   TREE_VEC_ELT (parm, i),
-				   TREE_VEC_ELT (arg, i),
-				   UNIFY_ALLOW_NONE, explain_p);
+
+	len = TREE_VEC_LENGTH (parm);
+	argslen = TREE_VEC_LENGTH (arg);
+
+	/* Check for pack expansions in the parameters.  */
+	for (i = 0; i < len; ++i)
+	  {
+	    if (PACK_EXPANSION_P (TREE_VEC_ELT (parm, i)))
+	      {
+		if (i == len - 1)
+		  /* We can unify against something with a trailing
+		     parameter pack.  */
+		  parm_variadic_p = 1;
+		else
+		  /* [temp.deduct.type]/9: If the template argument list of
+		     P contains a pack expansion that is not the last
+		     template argument, the entire template argument list
+		     is a non-deduced context.  */
+		  return unify_success (explain_p);
+	      }
+	  }
+
+        /* If we don't have enough arguments to satisfy the parameters
+           (not counting the pack expression at the end), or we have
+           too many arguments for a parameter list that doesn't end in
+           a pack expression, we can't unify.  */
+	if (parm_variadic_p
+	    ? argslen < len - parm_variadic_p
+	    : argslen != len)
+	  return unify_arity (explain_p, TREE_VEC_LENGTH (arg), len);
+
+	/* Unify all of the parameters that precede the (optional)
+	   pack expression.  */
+	for (i = 0; i < len - parm_variadic_p; ++i)
+	  {
+	    RECUR_AND_CHECK_FAILURE (tparms, targs,
+				     TREE_VEC_ELT (parm, i),
+				     TREE_VEC_ELT (arg, i),
+				     UNIFY_ALLOW_NONE, explain_p);
+	  }
+	if (parm_variadic_p)
+	  return unify_pack_expansion (tparms, targs, parm, arg,
+				       UNIFY_ALLOW_NONE,
+				       /*call_args_p=*/false,
+				       /*subr=*/false, explain_p);
 	return unify_success (explain_p);
       }
 
@@ -16425,58 +16517,8 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict,
 
     case TYPE_ARGUMENT_PACK:
     case NONTYPE_ARGUMENT_PACK:
-      {
-        tree packed_parms = ARGUMENT_PACK_ARGS (parm);
-        tree packed_args = ARGUMENT_PACK_ARGS (arg);
-        int i, len = TREE_VEC_LENGTH (packed_parms);
-        int argslen = TREE_VEC_LENGTH (packed_args);
-        int parm_variadic_p = 0;
-
-	for (i = 0; i < len; ++i)
-	  {
-	    if (PACK_EXPANSION_P (TREE_VEC_ELT (packed_parms, i)))
-	      {
-		if (i == len - 1)
-		  /* We can unify against something with a trailing
-		     parameter pack.  */
-		  parm_variadic_p = 1;
-		else
-		  /* Since there is something following the pack
-		     expansion, we cannot unify this template argument
-		     list.  */
-		  return unify_success (explain_p);
-	      }
-	  }
-	  
-
-        /* If we don't have enough arguments to satisfy the parameters
-           (not counting the pack expression at the end), or we have
-           too many arguments for a parameter list that doesn't end in
-           a pack expression, we can't unify.  */
-        if (argslen < (len - parm_variadic_p))
-	  return unify_too_few_arguments (explain_p, argslen, len);
-	if (argslen > len && !parm_variadic_p)
-	  return unify_too_many_arguments (explain_p, argslen, len);
-
-        /* Unify all of the parameters that precede the (optional)
-           pack expression.  */
-        for (i = 0; i < len - parm_variadic_p; ++i)
-          {
-	    RECUR_AND_CHECK_FAILURE (tparms, targs,
-				     TREE_VEC_ELT (packed_parms, i),
-				     TREE_VEC_ELT (packed_args, i),
-				     strict, explain_p);
-          }
-
-        if (parm_variadic_p)
-          return unify_pack_expansion (tparms, targs, 
-                                       packed_parms, packed_args,
-                                       strict, /*call_args_p=*/false,
-                                       /*subr=*/false, explain_p);
-        return unify_success (explain_p);
-      }
-
-      break;
+      return unify (tparms, targs, ARGUMENT_PACK_ARGS (parm),
+		    ARGUMENT_PACK_ARGS (arg), strict, explain_p);
 
     case TYPEOF_TYPE:
     case DECLTYPE_TYPE:
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-explicit1.C b/gcc/testsuite/g++.dg/cpp0x/variadic-explicit1.C
new file mode 100644
index 0000000..a097f43
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic-explicit1.C
@@ -0,0 +1,11 @@
+// { dg-options -std=c++0x }
+
+template<class T, class U> struct A { };
+template<class... T, class ... U> void f( A<T,U>... p);
+
+void g() {
+    f<int>(
+        A<int,unsigned>(),
+        A<short,unsigned short>()
+        );
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-nondeduce1.C b/gcc/testsuite/g++.dg/cpp0x/variadic-nondeduce1.C
new file mode 100644
index 0000000..a64d797
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic-nondeduce1.C
@@ -0,0 +1,12 @@
+// { dg-options -std=c++0x }
+
+template <class... T>
+void f(T..., int, T...) { }
+
+int main()
+{
+  f(0);
+  f<int>(0,0,0);
+  f<int,int>(0,0,0,0,0);
+  f(0,0,0);			// { dg-error "" }
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic105.C b/gcc/testsuite/g++.dg/cpp0x/variadic105.C
index 66387b2..66d24a7 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic105.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic105.C
@@ -20,6 +20,6 @@ struct call_sum {
 
 int main() {
   // This shouldn't be an error; this is bug 35722.
-  reverse<call_sum>(1,2);	// { dg-bogus "no match" "" { xfail *-*-* } }
-  // { dg-bogus "sorry, unimplemented" "candidate explanation" { xfail *-*-* } 6 }
+  reverse<call_sum>(1,2);	// { dg-bogus "no match" "" }
+  // { dg-bogus "sorry, unimplemented" "candidate explanation" { target *-*-* } 6 }
 }
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic117.C b/gcc/testsuite/g++.dg/cpp0x/variadic117.C
new file mode 100644
index 0000000..22f2fc5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic117.C
@@ -0,0 +1,11 @@
+// { dg-options -std=c++0x }
+
+template <class T> struct A { typedef T type; };
+
+template <template <class...> class T, class... U>
+void f(typename T<U...>::type);
+
+int main()
+{
+  f<A,int>(42);
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic118.C b/gcc/testsuite/g++.dg/cpp0x/variadic118.C
new file mode 100644
index 0000000..43bf9ba
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic118.C
@@ -0,0 +1,11 @@
+// This should fail deduction, before it produces a candidate.
+// { dg-options -std=c++0x }
+
+template <class... T>
+void f(T... ts);		// { dg-message "deduction" }
+
+struct B { };
+int main()
+{
+  f<int>(B(), 1);		// { dg-error "" }
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic35.C b/gcc/testsuite/g++.dg/cpp0x/variadic35.C
index 1f21976..666a1f5 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic35.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic35.C
@@ -5,6 +5,5 @@ void get_ith(const Args&... args); // { dg-message "note" }
 void f()
 {
   get_ith<1, float>(1, 2.0, 'x');
-  get_ith<1, int, double, char, int>(1, 2.0, 'x'); // { dg-error "no matching function" }
-  // { dg-message "candidate" "candidate note" { target *-*-* } 8 }
+  get_ith<1, int, double, char, int>(1, 2.0, 'x'); // { dg-error "too few arguments" }
 }
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic65.C b/gcc/testsuite/g++.dg/cpp0x/variadic65.C
index 1c815d1..77be106 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic65.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic65.C
@@ -5,4 +5,9 @@ template<typename T1 = unused, typename T2 = unused, typename T3 = unused,
 struct tuple {};
 
 template<typename... Args>
-void foo(tuple<Args...>) { } // { dg-bogus "cannot expand" "" { xfail *-*-* } }
+tuple<Args...> foo() { } // { dg-bogus "cannot expand" "" }
+
+int main()
+{
+  foo<int,int,int,int,int,int>();
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic82.C b/gcc/testsuite/g++.dg/cpp0x/variadic82.C
index fb3ddb3..03aec80 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic82.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic82.C
@@ -3,9 +3,9 @@
 
 template<typename> struct A;
 
-template<typename... T> struct A<T*...> // { dg-bogus "cannot expand" "" { xfail *-*-* } }
+template<typename... T> struct A<T*...> // { dg-bogus "cannot expand" "" }
 {
   struct B;
 };
 
-A<void*> a; // { dg-bogus "incomplete type" "" { xfail *-*-* } }
+A<void*> a; // { dg-bogus "incomplete type" "" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic83.C b/gcc/testsuite/g++.dg/cpp0x/variadic83.C
index 2613d62..c446e69 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic83.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic83.C
@@ -3,6 +3,6 @@
 
 template<typename> struct A;
 
-template<typename... T> struct A<T...> { }; // { dg-bogus "cannot expand" "" { xfail *-*-* } }
+template<typename... T> struct A<T...> { }; // { dg-bogus "cannot expand" "" }
 
-A<int> a; // { dg-bogus "incomplete type" "" { xfail *-*-* } }
+A<int> a; // { dg-bogus "incomplete type" "" }
diff --git a/libstdc++-v3/testsuite/util/testsuite_tr1.h b/libstdc++-v3/testsuite/util/testsuite_tr1.h
index 94207a6..f063896 100644
--- a/libstdc++-v3/testsuite/util/testsuite_tr1.h
+++ b/libstdc++-v3/testsuite/util/testsuite_tr1.h
@@ -68,13 +68,14 @@ namespace __gnu_test
     }
 
 #ifdef __GXX_EXPERIMENTAL_CXX0X__
-  template<template<typename...> class Property, typename... Types>
+  template<template<typename...> class Property,
+	   typename Type1, typename... Types>
     bool
-    test_property(typename Property<Types...>::value_type value)
+    test_property(typename Property<Type1, Types...>::value_type value)
     {
       bool ret = true;
-      ret &= Property<Types...>::value == value;
-      ret &= Property<Types...>::type::value == value;
+      ret &= Property<Type1, Types...>::value == value;
+      ret &= Property<Type1, Types...>::type::value == value;
       return ret;
     }
 #endif

commit 976897e911845b27b1fd26fabe6455816b8db00a
Author: Jason Merrill <jason@redhat.com>
Date:   Fri Sep 30 16:06:27 2011 -0400

    	* pt.c (unify_one_argument): Split from type_unification_real...
    	(unify_pack_expansion): ...and here.  Drop call_args_p parm.
    	(type_unification_real, unify, more_specialized_fn): Adjust.

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 1b7337e..015ee37 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -165,7 +165,7 @@ static int template_decl_level (tree);
 static int check_cv_quals_for_unify (int, tree, tree);
 static void template_parm_level_and_index (tree, int*, int*);
 static int unify_pack_expansion (tree, tree, tree,
-				 tree, int, bool, bool, bool);
+				 tree, unification_kind_t, bool, bool);
 static tree tsubst_template_arg (tree, tree, tsubst_flags_t, tree);
 static tree tsubst_template_args (tree, tree, tsubst_flags_t, tree);
 static tree tsubst_template_parms (tree, tree, tsubst_flags_t);
@@ -14643,10 +14643,10 @@ maybe_adjust_types_for_deduction (unification_kind_t strict,
   return result;
 }
 
-/* Subroutine of type_unification_real and unify_pack_expansion.  PARM is a
-   function parameter of a template which does contain any deducible
-   template parameters; check if ARG is a suitable match for it.  STRICT,
-   FLAGS and EXPLAIN_P are as in fn_type_unification.  */
+/* Subroutine of unify_one_argument.  PARM is a function parameter of a
+   template which does contain any deducible template parameters; check if
+   ARG is a suitable match for it.  STRICT, FLAGS and EXPLAIN_P are as in
+   unify_one_argument.  */
 
 static int
 check_non_deducible_conversion (tree parm, tree arg, int strict,
@@ -14681,6 +14681,96 @@ check_non_deducible_conversion (tree parm, tree arg, int strict,
     return unify_arg_conversion (explain_p, parm, type, arg);
 }
 
+/* Subroutine of type_unification_real and unify_pack_expansion to
+   handle unification of a single P/A pair.  Parameters are as
+   for those functions.  */
+
+static int
+unify_one_argument (tree tparms, tree targs, tree parm, tree arg,
+		    int subr, unification_kind_t strict, int flags,
+		    bool explain_p)
+{
+  tree arg_expr = NULL_TREE;
+  int arg_strict;
+
+  if (arg == error_mark_node || parm == error_mark_node)
+    return unify_invalid (explain_p);
+  if (arg == unknown_type_node)
+    /* We can't deduce anything from this, but we might get all the
+       template args from other function args.  */
+    return unify_success (explain_p);
+
+  /* FIXME uses_deducible_template_parms */
+  if (TYPE_P (parm) && !uses_template_parms (parm))
+    return check_non_deducible_conversion (parm, arg, strict, flags,
+					   explain_p);
+
+  switch (strict)
+    {
+    case DEDUCE_CALL:
+      arg_strict = (UNIFY_ALLOW_OUTER_LEVEL
+		    | UNIFY_ALLOW_MORE_CV_QUAL
+		    | UNIFY_ALLOW_DERIVED);
+      break;
+
+    case DEDUCE_CONV:
+      arg_strict = UNIFY_ALLOW_LESS_CV_QUAL;
+      break;
+
+    case DEDUCE_EXACT:
+      arg_strict = UNIFY_ALLOW_NONE;
+      break;
+
+    default:
+      gcc_unreachable ();
+    }
+
+  /* We only do these transformations if this is the top-level
+     parameter_type_list in a call or declaration matching; in other
+     situations (nested function declarators, template argument lists) we
+     won't be comparing a type to an expression, and we don't do any type
+     adjustments.  */
+  if (!subr)
+    {
+      if (!TYPE_P (arg))
+	{
+	  gcc_assert (TREE_TYPE (arg) != NULL_TREE);
+	  if (type_unknown_p (arg))
+	    {
+	      /* [temp.deduct.type] A template-argument can be
+		 deduced from a pointer to function or pointer
+		 to member function argument if the set of
+		 overloaded functions does not contain function
+		 templates and at most one of a set of
+		 overloaded functions provides a unique
+		 match.  */
+
+	      if (resolve_overloaded_unification
+		  (tparms, targs, parm, arg, strict,
+		   arg_strict, explain_p))
+		return unify_success (explain_p);
+	      return unify_overload_resolution_failure (explain_p, arg);
+	    }
+
+	  arg_expr = arg;
+	  arg = unlowered_expr_type (arg);
+	  if (arg == error_mark_node)
+	    return unify_invalid (explain_p);
+	}
+
+      arg_strict |=
+	maybe_adjust_types_for_deduction (strict, &parm, &arg, arg_expr);
+    }
+  else
+    gcc_assert ((TYPE_P (parm) || TREE_CODE (parm) == TEMPLATE_DECL)
+		== (TYPE_P (arg) || TREE_CODE (arg) == TEMPLATE_DECL));
+
+  /* For deduction from an init-list we need the actual list.  */
+  if (arg_expr && BRACE_ENCLOSED_INITIALIZER_P (arg_expr))
+    arg = arg_expr;
+  return unify (tparms, targs, parm, arg, arg_strict, explain_p);
+}
+
 /* Most parms like fn_type_unification.
 
    If SUBR is 1, we're being called recursively (to unify the
@@ -14698,10 +14788,9 @@ type_unification_real (tree tparms,
 		       int flags,
 		       bool explain_p)
 {
-  tree parm, arg, arg_expr;
+  tree parm, arg;
   int i;
   int ntparms = TREE_VEC_LENGTH (tparms);
-  int sub_strict;
   int saw_undeduced = 0;
   tree parms;
   const tree *args;
@@ -14716,25 +14805,6 @@ type_unification_real (tree tparms,
      in TARGS.  */
   NON_DEFAULT_TEMPLATE_ARGS_COUNT (targs) = NULL_TREE;
 
-  switch (strict)
-    {
-    case DEDUCE_CALL:
-      sub_strict = (UNIFY_ALLOW_OUTER_LEVEL | UNIFY_ALLOW_MORE_CV_QUAL
-		    | UNIFY_ALLOW_DERIVED);
-      break;
-
-    case DEDUCE_CONV:
-      sub_strict = UNIFY_ALLOW_LESS_CV_QUAL;
-      break;
-
-    case DEDUCE_EXACT:
-      sub_strict = UNIFY_ALLOW_NONE;
-      break;
-
-    default:
-      gcc_unreachable ();
-    }
-
  again:
   parms = xparms;
   args = xargs;
@@ -14764,71 +14834,12 @@ type_unification_real (tree tparms,
 
       arg = args[ia];
       ++ia;
-      arg_expr = NULL;
-
-      if (arg == error_mark_node)
-	return unify_invalid (explain_p);
-      if (arg == unknown_type_node)
-	/* We can't deduce anything from this, but we might get all the
-	   template args from other function args.  */
-	continue;
-
-      /* Conversions will be performed on a function argument that
-	 corresponds with a function parameter that contains only
-	 non-deducible template parameters and explicitly specified
-	 template parameters.  */
-      /* FIXME uses_deducible_template_parms */
-      if (!uses_template_parms (parm))
-	{
-	  int ret = check_non_deducible_conversion (parm, arg, strict,
-						    flags, explain_p);
-	  if (ret)
-	    return ret;
-	  else
-	    continue;
-	}
-
-      if (!TYPE_P (arg))
-	{
-	  gcc_assert (TREE_TYPE (arg) != NULL_TREE);
-	  if (type_unknown_p (arg))
-	    {
-	      /* [temp.deduct.type] 
-
-	         A template-argument can be deduced from a pointer to
-		 function or pointer to member function argument if
-		 the set of overloaded functions does not contain
-		 function templates and at most one of a set of
-		 overloaded functions provides a unique match.  */
-	      if (resolve_overloaded_unification
-		  (tparms, targs, parm, arg, strict, sub_strict, explain_p))
-		continue;
-
-	      return unify_overload_resolution_failure (explain_p, arg);
-	    }
-	  arg_expr = arg;
-	  arg = unlowered_expr_type (arg);
-	  if (arg == error_mark_node)
-	    return unify_invalid (explain_p);
-	}
-
-      {
-	int arg_strict = sub_strict;
-
-	if (!subr)
-	  arg_strict |= maybe_adjust_types_for_deduction (strict, &parm, &arg,
-							  arg_expr);
 
-	if (arg == init_list_type_node && arg_expr)
-	  arg = arg_expr;
-	if (unify (tparms, targs, parm, arg, arg_strict, explain_p))
-	  /* If unification failed, the recursive call will have updated
-	     UI appropriately.  */
-	  return 1;
-      }
+      if (unify_one_argument (tparms, targs, parm, arg, subr, strict,
+			      flags, explain_p))
+	return 1;
     }
 
-
   if (parms 
       && parms != void_list_node
       && TREE_CODE (TREE_VALUE (parms)) == TYPE_PACK_EXPANSION)
@@ -14845,7 +14856,7 @@ type_unification_real (tree tparms,
       /* Copy the parameter into parmvec.  */
       TREE_VEC_ELT (parmvec, 0) = TREE_VALUE (parms);
       if (unify_pack_expansion (tparms, targs, parmvec, argvec, strict,
-                                /*call_args_p=*/true, /*subr=*/subr, explain_p))
+                                /*subr=*/subr, explain_p))
         return 1;
 
       /* Advance to the end of the list of parameters.  */
@@ -15480,10 +15491,12 @@ template_parm_level_and_index (tree parm, int* level, int* index)
    unify. CALL_ARGS_P is true iff PACKED_ARGS is actually a function
    call argument list. We'll need to adjust the arguments to make them
    types. SUBR tells us if this is from a recursive call to
-   type_unification_real.  */
+   type_unification_real, or for comparing two template argument
+   lists. */
+
 static int
 unify_pack_expansion (tree tparms, tree targs, tree packed_parms, 
-                      tree packed_args, int strict, bool call_args_p,
+                      tree packed_args, unification_kind_t strict,
                       bool subr, bool explain_p)
 {
   tree parm 
@@ -15555,94 +15568,15 @@ unify_pack_expansion (tree tparms, tree targs, tree packed_parms,
 	    --processing_template_decl;
 	  if (parm == error_mark_node)
 	    return 1;
-	  /* FIXME uses_deducible_template_parms */
-	  if (!uses_template_parms (parm))
-	    {
-	      int ret = check_non_deducible_conversion (parm, arg, strict,
-							LOOKUP_IMPLICIT,
-							explain_p);
-	      if (ret)
-		return ret;
-	      else
-		goto unified;
-	    }
 	}
       else
 	parm = pattern;
 
       /* Unify the pattern with the current argument.  */
-      {
-	tree arg_expr = NULL_TREE;
-        int arg_strict = strict;
-
-        if (call_args_p)
-          {
-            int sub_strict;
-
-            /* This mirrors what we do in type_unification_real.  */
-            switch (strict)
-              {
-              case DEDUCE_CALL:
-                sub_strict = (UNIFY_ALLOW_OUTER_LEVEL 
-                              | UNIFY_ALLOW_MORE_CV_QUAL
-                              | UNIFY_ALLOW_DERIVED);
-                break;
-                
-              case DEDUCE_CONV:
-                sub_strict = UNIFY_ALLOW_LESS_CV_QUAL;
-                break;
-                
-              case DEDUCE_EXACT:
-                sub_strict = UNIFY_ALLOW_NONE;
-                break;
-                
-              default:
-                gcc_unreachable ();
-              }
-
-            if (!TYPE_P (arg))
-              {
-                gcc_assert (TREE_TYPE (arg) != NULL_TREE);
-                if (type_unknown_p (arg))
-                  {
-                    /* [temp.deduct.type] A template-argument can be
-                       deduced from a pointer to function or pointer
-                       to member function argument if the set of
-                       overloaded functions does not contain function
-                       templates and at most one of a set of
-                       overloaded functions provides a unique
-                       match.  */
-
-                    if (resolve_overloaded_unification
-                        (tparms, targs, parm, arg,
-			 (unification_kind_t) strict,
-			 sub_strict, explain_p))
-		      goto unified;
-		    return unify_overload_resolution_failure (explain_p, arg);
-                  }
-
-		arg_expr = arg;
-		arg = unlowered_expr_type (arg);
-		if (arg == error_mark_node)
-		  return unify_invalid (explain_p);
-              }
-      
-            arg_strict = sub_strict;
-
-            if (!subr)
-              arg_strict |= 
-                maybe_adjust_types_for_deduction ((unification_kind_t) strict,
-						  &parm, &arg, arg_expr);
-          }
-
-	/* For deduction from an init-list we need the actual list.  */
-	if (arg_expr && BRACE_ENCLOSED_INITIALIZER_P (arg_expr))
-	  arg = arg_expr;
-	RECUR_AND_CHECK_FAILURE (tparms, targs, parm, arg, arg_strict,
-				 explain_p);
-      }
+      if (unify_one_argument (tparms, targs, parm, arg, subr, strict,
+			      LOOKUP_IMPLICIT, explain_p))
+	return 1;
 
-    unified:
       /* For each parameter pack, collect the deduced value.  */
       for (pack = packs; pack; pack = TREE_CHAIN (pack))
         {
@@ -16014,9 +15948,8 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict,
 	    if (parm_variadic_p
 		&& unify_pack_expansion (tparms, targs,
 					 parmvec, argvec,
-					 UNIFY_ALLOW_NONE,
-					 /*call_args_p=*/false,
-					 /*subr=*/false, explain_p))
+					 DEDUCE_EXACT,
+					 /*subr=*/true, explain_p))
 	      return 1;
 	  }
 	  arg = TYPE_TI_TEMPLATE (arg);
@@ -16353,9 +16286,8 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict,
 	  }
 	if (parm_variadic_p)
 	  return unify_pack_expansion (tparms, targs, parm, arg,
-				       UNIFY_ALLOW_NONE,
-				       /*call_args_p=*/false,
-				       /*subr=*/false, explain_p);
+				       DEDUCE_EXACT,
+				       /*subr=*/true, explain_p);
 	return unify_success (explain_p);
       }
 
@@ -16827,9 +16759,8 @@ more_specialized_fn (tree pat1, tree pat2, int len)
             TREE_VEC_ELT (argvec, i) = TREE_VALUE (ta);
 
           deduce1 = (unify_pack_expansion (tparms1, targs1, parmvec,
-					   argvec, UNIFY_ALLOW_NONE, 
-                                           /*call_args_p=*/false, 
-					   /*subr=*/0, /*explain_p=*/false)
+					   argvec, DEDUCE_EXACT,
+					   /*subr=*/true, /*explain_p=*/false)
 		     == 0);
 
           /* We cannot deduce in the other direction, because ARG1 is
@@ -16852,9 +16783,8 @@ more_specialized_fn (tree pat1, tree pat2, int len)
             TREE_VEC_ELT (argvec, i) = TREE_VALUE (ta);
 
           deduce2 = (unify_pack_expansion (tparms2, targs2, parmvec,
-					   argvec, UNIFY_ALLOW_NONE, 
-                                           /*call_args_p=*/false, 
-					   /*subr=*/0, /*explain_p=*/false)
+					   argvec, DEDUCE_EXACT,
+					   /*subr=*/true, /*explain_p=*/false)
 		     == 0);
 
           /* We cannot deduce in the other direction, because ARG2 is
