re PR c++/57172 ([C++11][DR 1164] Template overload resolution ambiguous for T&& versus T&)

2013-06-27  Marc Glisse  <marc.glisse@inria.fr>

	PR c++/57172
gcc/cp/
	* pt.c (more_specialized_fn): If both arguments are references,
	give priority to an lvalue.

gcc/testsuite/
	* g++.dg/cpp0x/pr57172.C: New testcase.

From-SVN: r200463
This commit is contained in:
Marc Glisse 2013-06-27 13:34:48 +02:00 committed by Marc Glisse
parent 7b61c5a9cb
commit 85afa0754c
4 changed files with 49 additions and 12 deletions

View File

@ -1,3 +1,9 @@
2013-06-27 Marc Glisse <marc.glisse@inria.fr>
PR c++/57172
* pt.c (more_specialized_fn): If both arguments are references,
give priority to an lvalue.
2013-06-26 Jason Merrill <jason@redhat.com> 2013-06-26 Jason Merrill <jason@redhat.com>
* typeck2.c (store_init_value): Diagnose a non-constant * typeck2.c (store_init_value): Diagnose a non-constant

View File

@ -17510,7 +17510,8 @@ check_undeduced_parms (tree targs, tree args, tree end)
corresponding argument. Deduction is done as for class templates. corresponding argument. Deduction is done as for class templates.
The arguments used in deduction have reference and top level cv The arguments used in deduction have reference and top level cv
qualifiers removed. Iff both arguments were originally reference qualifiers removed. Iff both arguments were originally reference
types *and* deduction succeeds in both directions, the template types *and* deduction succeeds in both directions, an lvalue reference
wins against an rvalue reference and otherwise the template
with the more cv-qualified argument wins for that pairing (if with the more cv-qualified argument wins for that pairing (if
neither is more cv-qualified, they both are equal). Unlike regular neither is more cv-qualified, they both are equal). Unlike regular
deduction, after all the arguments have been deduced in this way, deduction, after all the arguments have been deduced in this way,
@ -17586,6 +17587,8 @@ more_specialized_fn (tree pat1, tree pat2, int len)
int deduce1, deduce2; int deduce1, deduce2;
int quals1 = -1; int quals1 = -1;
int quals2 = -1; int quals2 = -1;
int ref1 = 0;
int ref2 = 0;
if (TREE_CODE (arg1) == TYPE_PACK_EXPANSION if (TREE_CODE (arg1) == TYPE_PACK_EXPANSION
&& TREE_CODE (arg2) == TYPE_PACK_EXPANSION) && TREE_CODE (arg2) == TYPE_PACK_EXPANSION)
@ -17601,12 +17604,14 @@ more_specialized_fn (tree pat1, tree pat2, int len)
if (TREE_CODE (arg1) == REFERENCE_TYPE) if (TREE_CODE (arg1) == REFERENCE_TYPE)
{ {
ref1 = TYPE_REF_IS_RVALUE (arg1) + 1;
arg1 = TREE_TYPE (arg1); arg1 = TREE_TYPE (arg1);
quals1 = cp_type_quals (arg1); quals1 = cp_type_quals (arg1);
} }
if (TREE_CODE (arg2) == REFERENCE_TYPE) if (TREE_CODE (arg2) == REFERENCE_TYPE)
{ {
ref2 = TYPE_REF_IS_RVALUE (arg2) + 1;
arg2 = TREE_TYPE (arg2); arg2 = TREE_TYPE (arg2);
quals2 = cp_type_quals (arg2); quals2 = cp_type_quals (arg2);
} }
@ -17684,20 +17689,34 @@ more_specialized_fn (tree pat1, tree pat2, int len)
/* "If, for a given type, deduction succeeds in both directions /* "If, for a given type, deduction succeeds in both directions
(i.e., the types are identical after the transformations above) (i.e., the types are identical after the transformations above)
and if the type from the argument template is more cv-qualified and both P and A were reference types (before being replaced with
than the type from the parameter template (as described above) the type referred to above):
that type is considered to be more specialized than the other. If - if the type from the argument template was an lvalue reference and
neither type is more cv-qualified than the other then neither type the type from the parameter template was not, the argument type is
is more specialized than the other." */ considered to be more specialized than the other; otherwise,
- if the type from the argument template is more cv-qualified
than the type from the parameter template (as described above),
the argument type is considered to be more specialized than the other;
otherwise,
- neither type is more specialized than the other." */
if (deduce1 && deduce2 if (deduce1 && deduce2)
&& quals1 != quals2 && quals1 >= 0 && quals2 >= 0) {
if (ref1 && ref2 && ref1 != ref2)
{
if (ref1 > ref2)
lose1 = true;
else
lose2 = true;
}
else if (quals1 != quals2 && quals1 >= 0 && quals2 >= 0)
{ {
if ((quals1 & quals2) == quals2) if ((quals1 & quals2) == quals2)
lose2 = true; lose2 = true;
if ((quals1 & quals2) == quals1) if ((quals1 & quals2) == quals1)
lose1 = true; lose1 = true;
} }
}
if (lose1 && lose2) if (lose1 && lose2)
/* We've failed to deduce something in either direction. /* We've failed to deduce something in either direction.

View File

@ -1,3 +1,8 @@
2013-06-27 Marc Glisse <marc.glisse@inria.fr>
PR c++/57172
* g++.dg/cpp0x/pr57172.C: New testcase.
2013-06-27 Andreas Krebbel <Andreas.Krebbel@de.ibm.com> 2013-06-27 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
* gcc.target/s390/htm-1.c: New file. * gcc.target/s390/htm-1.c: New file.

View File

@ -0,0 +1,7 @@
// PR c++/57172
// { dg-do compile { target c++11 } }
template <typename T> int f (T&) { return 0; }
template <typename T> int f (T&&) = delete;
int i;
int j = f (i);