re PR c++/57172 ([C++11][DR 1164] Template overload resolution ambiguous for T&&...
authorMarc Glisse <marc.glisse@inria.fr>
Thu, 27 Jun 2013 11:34:48 +0000 (13:34 +0200)
committerMarc Glisse <glisse@gcc.gnu.org>
Thu, 27 Jun 2013 11:34:48 +0000 (11:34 +0000)
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

gcc/cp/ChangeLog
gcc/cp/pt.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp0x/pr57172.C [new file with mode: 0644]

index 7b40665484f850333901b55230a2926d85b8444c..93e639e868711900b00fea2c616674fb34a90445 100644 (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>
 
        * typeck2.c (store_init_value): Diagnose a non-constant
index 667e37f2ec9b169d6ea10db75c81bf135d352416..e2ffe7314c44b9bb2bcd783bc7728f26a917851f 100644 (file)
@@ -17510,7 +17510,8 @@ check_undeduced_parms (tree targs, tree args, tree end)
    corresponding argument.  Deduction is done as for class templates.
    The arguments used in deduction have reference and top level cv
    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
    neither is more cv-qualified, they both are equal).  Unlike regular
    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 quals1 = -1;
       int quals2 = -1;
+      int ref1 = 0;
+      int ref2 = 0;
 
       if (TREE_CODE (arg1) == 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)
        {
+         ref1 = TYPE_REF_IS_RVALUE (arg1) + 1;
          arg1 = TREE_TYPE (arg1);
          quals1 = cp_type_quals (arg1);
        }
 
       if (TREE_CODE (arg2) == REFERENCE_TYPE)
        {
+         ref2 = TYPE_REF_IS_RVALUE (arg2) + 1;
          arg2 = TREE_TYPE (arg2);
          quals2 = cp_type_quals (arg2);
        }
@@ -17684,19 +17689,33 @@ more_specialized_fn (tree pat1, tree pat2, int len)
 
       /* "If, for a given type, deduction succeeds in both directions
         (i.e., the types are identical after the transformations above)
-        and if the type from the argument template is more cv-qualified
-        than the type from the parameter template (as described above)
-        that type is considered to be more specialized than the other. If
-        neither type is more cv-qualified than the other then neither type
-        is more specialized than the other."  */
-
-      if (deduce1 && deduce2
-         && quals1 != quals2 && quals1 >= 0 && quals2 >= 0)
+        and both P and A were reference types (before being replaced with
+        the type referred to above):
+        - if the type from the argument template was an lvalue reference and
+        the type from the parameter template was not, the argument type is
+        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 ((quals1 & quals2) == quals2)
-           lose2 = true;
-         if ((quals1 & quals2) == quals1)
-           lose1 = true;
+         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)
+               lose2 = true;
+             if ((quals1 & quals2) == quals1)
+               lose1 = true;
+           }
        }
 
       if (lose1 && lose2)
index f6ab2ba0468533458c5608bc5b6ac754b7949478..73cf781d1fe0f3df6ca5ac6a238bfa1b99e0a45c 100644 (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>
 
        * gcc.target/s390/htm-1.c: New file.
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr57172.C b/gcc/testsuite/g++.dg/cpp0x/pr57172.C
new file mode 100644 (file)
index 0000000..2108838
--- /dev/null
@@ -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);