diff mbox

[C++] Implement DR1164

Message ID alpine.DEB.2.02.1306262345580.22211@stedding.saclay.inria.fr
State New
Headers show

Commit Message

Marc Glisse June 26, 2013, 9:56 p.m. UTC
Hello,

this patch tries to implement DR1164. It passes bootstrap+testsuite on 
x86_64-unknown-linux-gnu.

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.

Comments

Jason Merrill June 27, 2013, 2:23 a.m. UTC | #1
OK.

Jason
diff mbox

Patch

Index: gcc/testsuite/g++.dg/cpp0x/pr57172.C
===================================================================
--- gcc/testsuite/g++.dg/cpp0x/pr57172.C	(revision 0)
+++ gcc/testsuite/g++.dg/cpp0x/pr57172.C	(revision 0)
@@ -0,0 +1,7 @@ 
+// PR c++/57172
+// { dg-do compile { target c++11 } }
+
+template <typename T> int f (T&) { }
+template <typename T> int f (T&&) = delete;
+int i;
+int j = f (i);

Property changes on: gcc/testsuite/g++.dg/cpp0x/pr57172.C
___________________________________________________________________
Added: svn:keywords
   + Author Date Id Revision URL
Added: svn:eol-style
   + native

Index: gcc/cp/pt.c
===================================================================
--- gcc/cp/pt.c	(revision 200430)
+++ gcc/cp/pt.c	(working copy)
@@ -17503,21 +17503,22 @@  check_undeduced_parms (tree targs, tree
 
    The 1998 std underspecified function template partial ordering, and
    DR214 addresses the issue.  We take pairs of arguments, one from
    each of the templates, and deduce them against each other.  One of
    the templates will be more specialized if all the *other*
    template's arguments deduce against its arguments and at least one
    of its arguments *does* *not* deduce against the other template's
    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,
    we do *not* verify the deduced template argument values can be
    substituted into non-deduced contexts.
 
    The logic can be a bit confusing here, because we look at deduce1 and
    targs1 to see if pat2 is at least as specialized, and vice versa; if we
    can find template arguments for pat1 to make arg1 look like arg2, that
    means that arg2 is at least as specialized as arg1.  */
@@ -17579,41 +17580,45 @@  more_specialized_fn (tree pat1, tree pat
 
   while (len--
 	 /* Stop when an ellipsis is seen.  */
 	 && args1 != NULL_TREE && args2 != NULL_TREE)
     {
       tree arg1 = TREE_VALUE (args1);
       tree arg2 = TREE_VALUE (args2);
       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)
         {
           /* When both arguments are pack expansions, we need only
              unify the patterns themselves.  */
           arg1 = PACK_EXPANSION_PATTERN (arg1);
           arg2 = PACK_EXPANSION_PATTERN (arg2);
 
           /* This is the last comparison we need to do.  */
           len = 0;
         }
 
       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);
 	}
 
       arg1 = TYPE_MAIN_VARIANT (arg1);
       arg2 = TYPE_MAIN_VARIANT (arg2);
 
       if (TREE_CODE (arg1) == TYPE_PACK_EXPANSION)
         {
           int i, len2 = list_length (args2);
@@ -17677,33 +17682,47 @@  more_specialized_fn (tree pat1, tree pat
 
       /* If we couldn't deduce arguments for tparms1 to make arg1 match
 	 arg2, then arg2 is not as specialized as arg1.  */
       if (!deduce1)
 	lose2 = true;
       if (!deduce2)
 	lose1 = true;
 
       /* "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."  */
+	 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
-	  && quals1 != quals2 && quals1 >= 0 && quals2 >= 0)
+      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)
 	/* We've failed to deduce something in either direction.
 	   These must be unordered.  */
 	break;
 
       if (TREE_CODE (arg1) == TYPE_PACK_EXPANSION
           || TREE_CODE (arg2) == TYPE_PACK_EXPANSION)
         /* We have already processed all of the arguments in our