In try_one_overload(), it should not be a deduction failure if we deduced more arguments of an argument pack than were explicitly specified (as long as the arguments are otherwise equivalent).
This patch makes try_one_overload() manually check the argument packs, to permit such a case. Bootstrap + regtest in progress on x86_64-pc-linux-gnu, will also test against Boost. Is this OK to commit if testing succeeds? gcc/cp/ChangeLog: PR c++/69052 * pt.c (try_one_overload): Handle comparing argument packs so that there is no conflict if we deduced more arguments of an argument pack than were explicitly specified. gcc/testsuite/ChangeLog: PR c++/69052 g++.dg/cpp0x/pr69056.C: New test. --- gcc/cp/pt.c | 21 +++++++++++++++++++++ gcc/testsuite/g++.dg/cpp0x/pr69056.C | 30 ++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) create mode 100644 gcc/testsuite/g++.dg/cpp0x/pr69056.C diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index ff16b7c..cdbfadd 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -18694,6 +18694,27 @@ try_one_overload (tree tparms, template args used in the function parm list with our own template parms. Discard them. */ TREE_VEC_ELT (tempargs, i) = NULL_TREE; + else if (oldelt && ARGUMENT_PACK_P (oldelt)) + { + /* Check that the deduced argument at each index is equivalent to the + corresponding explicit argument. We may have deduced more + arguments than were explicitly specified, and that's OK. */ + gcc_assert (ARGUMENT_PACK_INCOMPLETE_P (oldelt)); + gcc_assert (ARGUMENT_PACK_ARGS (oldelt) + == ARGUMENT_PACK_EXPLICIT_ARGS (oldelt)); + + tree explicit_pack = ARGUMENT_PACK_ARGS (oldelt); + tree deduced_pack = ARGUMENT_PACK_ARGS (elt); + + if (TREE_VEC_LENGTH (deduced_pack) + < TREE_VEC_LENGTH (explicit_pack)) + return 0; + + for (int j = 0; j < TREE_VEC_LENGTH (explicit_pack); j++) + if (!template_args_equal (TREE_VEC_ELT (explicit_pack, j), + TREE_VEC_ELT (deduced_pack, j))) + return 0; + } else if (oldelt && !template_args_equal (oldelt, elt)) return 0; } diff --git a/gcc/testsuite/g++.dg/cpp0x/pr69056.C b/gcc/testsuite/g++.dg/cpp0x/pr69056.C new file mode 100644 index 0000000..ab4e071 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/pr69056.C @@ -0,0 +1,30 @@ +// { dg-do compile { target c++11 } } +// PR c++/69056 + +template <typename T, typename... Args> +void resolver(int (*) (T, Args...)); + +int funcA(int, float) { return 0; } +int funcA(double) { return 0; } + +int funcB(int, float, char) { return 0; } +int funcB(int, bool) { return 0; } +int funcB(double) { return 0; } + +int funcC(int) { return 0; } +int funcC(double) { return 0; } + +void +foo (void) +{ + resolver (&funcA); // { dg-error "no match" } + resolver<int> (&funcA); + resolver<double> (&funcA); + + resolver<int> (&funcB); // { dg-error "no match" } + resolver<int, char> (&funcB); // { dg-error "no match" } + resolver<int, float> (&funcB); + + resolver<int> (&funcC); + resolver<int, float> (&funcC); // { dg-error "no match" } +} -- 2.7.0.rc1.98.gacf58d0.dirty