Patchwork C++ PATCH for c++/35722 (N2555 variadic pack expansion to fixed template parameter set)

login
register
mail settings
Submitter Jason Merrill
Date Oct. 2, 2011, 9:38 p.m.
Message ID <4E88D9F1.2070709@redhat.com>
Download mbox | patch
Permalink /patch/117379/
State New
Headers show

Comments

Jason Merrill - Oct. 2, 2011, 9:38 p.m.
This patch implements the extension voted in with paper N2555, after the 
initial implementation of variadic templates in GCC.  Under this 
extension, a template argument list can contain a pack expansion even if 
the template has a fixed parameter list.  For example,

template<typename G, typename H> struct foo {};
template<typename... G> struct bar : foo<G...> {};
int main() {
   bar<int, float> f;
}

Here the template argument pack specified for bar has two elements, so 
it ends up matching the parameter list for foo and all is good.

My implementation approach was as follows:

1) Don't try to do anything with an unknown or incomplete argument pack, 
just leave it alone until we know all the arguments.
2) Since we aren't substituting partial packs anymore, when deducing a 
function parameter pack, plug in explicit template arguments as we go.
3) If we see a template parameter pack used in a function parameter pack 
not at the end of the parameter list, we can't deduce it, so just plug 
in the explicit template arguments (if any).

This last point is an open area of discussion in the committee, but it 
gets the job done and seems like a reasonable approach to me.

The first patch here is the substantive changes; the second patch is 
just factoring out common code in type_unification_real and 
unify_pack_expansion into a separate function.

Tested x86_64-pc-linux-gnu, applying to trunk.

Patch

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