diff mbox

Fix PR c++/69052 (argument pack deduction failure during overload resolution)

Message ID 1451235724-17299-1-git-send-email-patrick@parcs.ath.cx
State New
Headers show

Commit Message

Patrick Palka Dec. 27, 2015, 5:02 p.m. UTC
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

Comments

Patrick Palka Dec. 27, 2015, 5:05 p.m. UTC | #1
On Sun, Dec 27, 2015 at 12:02 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++/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.  */

Oops, I forgot to --amend a clarity change to the above comment.  It
should read:

         /* 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.  */
Patrick Palka Dec. 27, 2015, 5:10 p.m. UTC | #2
On Sun, Dec 27, 2015 at 12:05 PM, Patrick Palka <patrick@parcs.ath.cx> wrote:
> On Sun, Dec 27, 2015 at 12:02 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++/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.  */
>
> Oops, I forgot to --amend a clarity change to the above comment.  It
> should read:
>
>          /* 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.  */

... And I just realize I have been referring to the wrong PR :( It
should be c++/69056 not 69052... Sorry.

I suppose I will just resend a fixed version of this patch in a new
thread. Please ignore this one.
diff mbox

Patch

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" }
+}