The standard says that if a template-id designates a single function, that is used when we don't have sufficient type information to guide deduction. But we were getting this wrong when passing to a variadic parameter due to a simple logic error.

Tested x86_64-pc-linux-gnu, applying to trunk and 4.6.
commit 08ca1e8bdad08f93ef2168550633ff05a3ae57ec
Author: Jason Merrill <ja...@redhat.com>
Date:   Tue Aug 16 18:42:54 2011 -0400

    	PR c++/50086
    	* pt.c (unify_pack_expansion): Correct overloaded unification
    	logic.

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 9a4419a..9ab110a 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -15434,7 +15434,6 @@ unify_pack_expansion (tree tparms, tree targs, tree packed_parms,
         tree arg = TREE_VEC_ELT (packed_args, i);
 	tree arg_expr = NULL_TREE;
         int arg_strict = strict;
-        bool skip_arg_p = false;
 
         if (call_args_p)
           {
@@ -15477,19 +15476,15 @@ unify_pack_expansion (tree tparms, tree targs, tree packed_parms,
                     if (resolve_overloaded_unification
                         (tparms, targs, parm, arg,
 			 (unification_kind_t) strict,
-			 sub_strict, explain_p)
-                        != 0)
-                      return 1;
-                    skip_arg_p = true;
+			 sub_strict, explain_p))
+		      goto unified;
+		    return unify_overload_resolution_failure (explain_p, arg);
                   }
 
-                if (!skip_arg_p)
-                  {
-		    arg_expr = arg;
-                    arg = unlowered_expr_type (arg);
-                    if (arg == error_mark_node)
-                      return 1;
-                  }
+		arg_expr = arg;
+		arg = unlowered_expr_type (arg);
+		if (arg == error_mark_node)
+		  return unify_invalid (explain_p);
               }
       
             arg_strict = sub_strict;
@@ -15500,16 +15495,14 @@ unify_pack_expansion (tree tparms, tree targs, tree packed_parms,
 						  &parm, &arg, arg_expr);
           }
 
-        if (!skip_arg_p)
-          {
-	    /* 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);
-          }
+	/* 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);
       }
 
+    unified:
       /* For each parameter pack, collect the deduced value.  */
       for (pack = packs; pack; pack = TREE_CHAIN (pack))
         {
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-unresolved.C b/gcc/testsuite/g++.dg/cpp0x/variadic-unresolved.C
new file mode 100644
index 0000000..a8463de
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic-unresolved.C
@@ -0,0 +1,12 @@
+// PR c++/50086
+// { dg-options -std=c++0x }
+
+template<typename T> void tfun();
+template<typename T> void fun1(T);
+template<typename... Types> void fun2(Types... args);
+
+int main()
+{
+  fun1(tfun<int>); // ok
+  fun2(tfun<int>); // error: unresolved overloaded function type
+}

Reply via email to