On Sun, Dec 27, 2015 at 12:14 PM, Patrick Palka <patr...@parcs.ath.cx> wrote: > 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++/69056 > * 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++/69056 > g++.dg/cpp0x/pr69056.C: New test. > --- > gcc/cp/pt.c | 22 ++++++++++++++++++++++ > gcc/testsuite/g++.dg/cpp0x/pr69056.C | 30 ++++++++++++++++++++++++++++++ > 2 files changed, 52 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..e8cf1fa 100644 > --- a/gcc/cp/pt.c > +++ b/gcc/cp/pt.c > @@ -18694,6 +18694,28 @@ 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 argument at each index of the deduced argument > pack > + is equivalent to the corresponding explicitly specified 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 >
Ping.