Message ID | 1451236493-4007-1-git-send-email-patrick@parcs.ath.cx |
---|---|
State | New |
Headers | show |
On Sun, Dec 27, 2015 at 12:14 PM, Patrick Palka <patrick@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.
OK. Jason
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" } +}