... I'm finishing testing the below. Thanks! Paolo.
//////////////////////
Index: cp/pt.c =================================================================== --- cp/pt.c (revision 213287) +++ cp/pt.c (working copy) @@ -5517,13 +5517,21 @@ unify_method_type_error (bool explain_p, tree arg) } static int -unify_arity (bool explain_p, int have, int wanted) +unify_arity (bool explain_p, int have, int wanted, bool least_p = false) { if (explain_p) - inform_n (input_location, wanted, - " candidate expects %d argument, %d provided", - " candidate expects %d arguments, %d provided", - wanted, have); + { + if (least_p) + inform_n (input_location, wanted, + " candidate expects at least %d argument, %d provided", + " candidate expects at least %d arguments, %d provided", + wanted, have); + else + inform_n (input_location, wanted, + " candidate expects %d argument, %d provided", + " candidate expects %d arguments, %d provided", + wanted, have); + } return 1; } @@ -5534,9 +5542,10 @@ unify_too_many_arguments (bool explain_p, int have } static int -unify_too_few_arguments (bool explain_p, int have, int wanted) +unify_too_few_arguments (bool explain_p, int have, int wanted, + bool least_p = false) { - return unify_arity (explain_p, have, wanted); + return unify_arity (explain_p, have, wanted, least_p); } static int @@ -16617,18 +16626,33 @@ type_unification_real (tree tparms, are present, and the parm list isn't variadic. */ if (ia < nargs && parms == void_list_node) return unify_too_many_arguments (explain_p, nargs, ia); - /* Fail if parms are left and they don't have default values. */ + /* Fail if parms are left and they don't have default values and + they aren't all deduced as empty packs, eg (c++/57397): + + template<class T1, class... Tn, class... Tm> + void foo(T1, Tn..., Tm...); + + int main() + { + foo(1); + } */ if (parms && parms != void_list_node && TREE_PURPOSE (parms) == NULL_TREE) { unsigned int count = nargs; tree p = parms; - while (p && p != void_list_node) + bool type_pack_p; + do { - count++; + type_pack_p = TREE_CODE (TREE_VALUE (p)) == TYPE_PACK_EXPANSION; + if (!type_pack_p) + count++; p = TREE_CHAIN (p); } - return unify_too_few_arguments (explain_p, ia, count); + while (p && p != void_list_node); + if (count != nargs) + return unify_too_few_arguments (explain_p, ia, count, + type_pack_p); } if (!subr) Index: testsuite/g++.dg/cpp0x/vt-57397-1.C =================================================================== --- testsuite/g++.dg/cpp0x/vt-57397-1.C (revision 0) +++ testsuite/g++.dg/cpp0x/vt-57397-1.C (working copy) @@ -0,0 +1,22 @@ +// PR c++/57397 +// { dg-do compile { target c++11 } } + +template<class T1, class... Tn> +void foo(T1, Tn...); + +template<class T1, class T2, class... Tn> +void bar(T1, T2, Tn...); + +int main() +{ + foo(); // { dg-error "no matching" } + // { dg-message "candidate expects at least 1 argument, 0 provided" "" { target *-*-* } 12 } + foo(1); + foo(1, 2); + bar(); // { dg-error "no matching" } + // { dg-message "candidate expects at least 2 arguments, 0 provided" "" { target *-*-* } 16 } + bar(1); // { dg-error "no matching" } + // { dg-message "candidate expects at least 2 arguments, 1 provided" "" { target *-*-* } 18 } + bar(1, 2); + bar(1, 2, 3); +} Index: testsuite/g++.dg/cpp0x/vt-57397-2.C =================================================================== --- testsuite/g++.dg/cpp0x/vt-57397-2.C (revision 0) +++ testsuite/g++.dg/cpp0x/vt-57397-2.C (working copy) @@ -0,0 +1,24 @@ +// PR c++/57397 +// { dg-do compile { target c++11 } } + +template<class T1, class... Tn, class... Tm> +void foo(T1, Tn..., Tm...); + +template<class T1, class T2, class... Tn, class... Tm> +void bar(T1, T2, Tn..., Tm...); + +int main() +{ + foo(); // { dg-error "no matching" } + // { dg-message "candidate expects at least 1 argument, 0 provided" "" { target *-*-* } 12 } + foo(1); + foo(1, 2); + foo(1, 2, 3); + bar(); // { dg-error "no matching" } + // { dg-message "candidate expects at least 2 arguments, 0 provided" "" { target *-*-* } 17 } + bar(1); // { dg-error "no matching" } + // { dg-message "candidate expects at least 2 arguments, 1 provided" "" { target *-*-* } 19 } + bar(1, 2); + bar(1, 2, 3); + bar(1, 2, 3, 4); +}