public inbox for libstdc++-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r14-6221] c++: partial ordering of object parameter [PR53499]
@ 2023-12-06 14:02 Jason Merrill
  0 siblings, 0 replies; only message in thread
From: Jason Merrill @ 2023-12-06 14:02 UTC (permalink / raw)
  To: gcc-cvs, libstdc++-cvs

https://gcc.gnu.org/g:c1e54c82a9e1855499ef7bb8827540e6a097532b

commit r14-6221-gc1e54c82a9e1855499ef7bb8827540e6a097532b
Author: Jason Merrill <jason@redhat.com>
Date:   Tue Dec 5 15:28:16 2023 -0500

    c++: partial ordering of object parameter [PR53499]
    
    Looks like we implemented option 1 (skip the object parameter) for CWG532
    before the issue was resolved, and never updated to the final resolution of
    option 2 (model it as a reference).  More recently CWG2445 extended this
    handling to static member functions; I think that's wrong, and have
    opened CWG2834 to address that and how explicit object member functions
    interact with it.
    
    The FIXME comments are to guide how the explicit object member function
    support should change the uses of DECL_NONSTATIC_MEMBER_FUNCTION_P.
    
    The library testsuite changes are to make partial ordering work again
    between the generic operator- in the testcase and
    _Pointer_adapter::operator-.
    
            DR 532
            PR c++/53499
    
    gcc/cp/ChangeLog:
    
            * pt.cc (more_specialized_fn): Fix object parameter handling.
    
    gcc/testsuite/ChangeLog:
    
            * g++.dg/template/partial-order4.C: New test.
            * g++.dg/template/spec26.C: Adjust for CWG532.
    
    libstdc++-v3/ChangeLog:
    
            * testsuite/23_containers/vector/ext_pointer/types/1.cc
            * testsuite/23_containers/vector/ext_pointer/types/2.cc
            (N::operator-): Make less specialized.

Diff:
---
 gcc/cp/pt.cc                                       | 68 ++++++++++++++++------
 gcc/testsuite/g++.dg/template/partial-order4.C     | 17 ++++++
 gcc/testsuite/g++.dg/template/spec26.C             | 10 ++--
 .../23_containers/vector/ext_pointer/types/1.cc    |  4 +-
 .../23_containers/vector/ext_pointer/types/2.cc    |  4 +-
 5 files changed, 78 insertions(+), 25 deletions(-)

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 5765982277e..669d2ad65c3 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -25198,27 +25198,61 @@ more_specialized_fn (tree pat1, tree pat2, int len)
   bool lose1 = false;
   bool lose2 = false;
 
-  /* Remove the this parameter from non-static member functions.  If
-     one is a non-static member function and the other is not a static
-     member function, remove the first parameter from that function
-     also.  This situation occurs for operator functions where we
-     locate both a member function (with this pointer) and non-member
-     operator (with explicit first operand).  */
-  if (DECL_NONSTATIC_MEMBER_FUNCTION_P (decl1))
+  /* C++17 [temp.func.order]/3 (CWG532)
+
+     If only one of the function templates M is a non-static member of some
+     class A, M is considered to have a new first parameter inserted in its
+     function parameter list. Given cv as the cv-qualifiers of M (if any), the
+     new parameter is of type "rvalue reference to cv A" if the optional
+     ref-qualifier of M is && or if M has no ref-qualifier and the first
+     parameter of the other template has rvalue reference type. Otherwise, the
+     new parameter is of type "lvalue reference to cv A".  */
+
+  if (DECL_STATIC_FUNCTION_P (decl1) || DECL_STATIC_FUNCTION_P (decl2))
     {
-      len--; /* LEN is the number of significant arguments for DECL1 */
-      args1 = TREE_CHAIN (args1);
-      if (!DECL_STATIC_FUNCTION_P (decl2))
-	args2 = TREE_CHAIN (args2);
-    }
-  else if (DECL_NONSTATIC_MEMBER_FUNCTION_P (decl2))
-    {
-      args2 = TREE_CHAIN (args2);
-      if (!DECL_STATIC_FUNCTION_P (decl1))
+      /* Note C++20 DR2445 extended the above to static member functions, but
+	 I think think the old G++ behavior of just skipping the object
+	 parameter when comparing to a static member function was better, so
+	 let's stick with that for now.  This is CWG2834.  --jason 2023-12 */
+      if (DECL_NONSTATIC_MEMBER_FUNCTION_P (decl1)) /* FIXME or explicit */
 	{
-	  len--;
+	  len--; /* LEN is the number of significant arguments for DECL1 */
 	  args1 = TREE_CHAIN (args1);
 	}
+      else if (DECL_NONSTATIC_MEMBER_FUNCTION_P (decl2)) /* FIXME or explicit */
+	args2 = TREE_CHAIN (args2);
+    }
+  else if (DECL_NONSTATIC_MEMBER_FUNCTION_P (decl1) /* FIXME implicit only */
+	   && DECL_NONSTATIC_MEMBER_FUNCTION_P (decl2))
+    {
+      /* Note DR2445 also (IMO wrongly) removed the "only one" above, which
+	 would break e.g.  cpp1y/lambda-generic-variadic5.C.  */
+      len--;
+      args1 = TREE_CHAIN (args1);
+      args2 = TREE_CHAIN (args2);
+    }
+  else if (DECL_NONSTATIC_MEMBER_FUNCTION_P (decl1) /* FIXME implicit only */
+	   || DECL_NONSTATIC_MEMBER_FUNCTION_P (decl2))
+    {
+      /* The other is a non-member or explicit object member function;
+	 rewrite the implicit object parameter to a reference.  */
+      tree ns = DECL_NONSTATIC_MEMBER_FUNCTION_P (decl2) ? decl2 : decl1;
+      tree &nsargs = ns == decl2 ? args2 : args1;
+      tree obtype = TREE_TYPE (TREE_VALUE (nsargs));
+
+      nsargs = TREE_CHAIN (nsargs);
+
+      cp_ref_qualifier rqual = type_memfn_rqual (TREE_TYPE (ns));
+      if (rqual == REF_QUAL_NONE)
+	{
+	  tree otherfirst = ns == decl1 ? args2 : args1;
+	  otherfirst = TREE_VALUE (otherfirst);
+	  if (TREE_CODE (otherfirst) == REFERENCE_TYPE
+	      && TYPE_REF_IS_RVALUE (otherfirst))
+	    rqual = REF_QUAL_RVALUE;
+	}
+      obtype = cp_build_reference_type (obtype, rqual == REF_QUAL_RVALUE);
+      nsargs = tree_cons (NULL_TREE, obtype, nsargs);
     }
 
   /* If only one is a conversion operator, they are unordered.  */
diff --git a/gcc/testsuite/g++.dg/template/partial-order4.C b/gcc/testsuite/g++.dg/template/partial-order4.C
new file mode 100644
index 00000000000..89555ab7060
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/partial-order4.C
@@ -0,0 +1,17 @@
+// DR 532
+// PR c++/53499
+// [temp.func.order] says that we do ordering on the first parameter.
+
+struct A
+{
+  template <class T>
+  bool operator==(T);
+};
+
+template <class T, class U>
+bool operator==(T, U);
+
+int main()
+{
+  A() == A();
+}
diff --git a/gcc/testsuite/g++.dg/template/spec26.C b/gcc/testsuite/g++.dg/template/spec26.C
index fad8e3e1519..253d4211153 100644
--- a/gcc/testsuite/g++.dg/template/spec26.C
+++ b/gcc/testsuite/g++.dg/template/spec26.C
@@ -1,13 +1,15 @@
-// { dg-do run }
+// { dg-do compile { target c++11 } }
 // Copyright (C) 2005 Free Software Foundation, Inc.
 // Contributed by Nathan Sidwell 16 Sep 2005 <nathan@codesourcery.com>
 
 // PR 23519  template specialization ordering (DR214)
 // Origin:  Maxim Yegorushkin <maxim.yegorushkin@gmail.com>
 
+// DR532 clarified that the * expression is ambiguous.
+
 struct A
 {
-    template<class T> int operator+(T&) { return 1;}
+  template<class T> int operator+(T&) = delete;
 };
 
 template<class T> struct B
@@ -16,7 +18,7 @@ template<class T> struct B
   template<typename R> int operator*(R&) {return 3;}
 };
 
-template <typename T, typename R> int operator-(B<T>, R&) {return 4;}
+template <typename T, typename R> int operator-(B<T>, R&) = delete;
 template<class T> int operator+(A&, B<T>&) { return 5;}
 template <typename T> int operator*(T &, A&){return 6;}
 
@@ -30,6 +32,6 @@ int main()
   if ((b - a) != 2)
     return 2;
   
-  if ((b * a) != 6)
+  if ((b * a) != 6)		// { dg-error "ambiguous" }
     return 3;
 }
diff --git a/libstdc++-v3/testsuite/23_containers/vector/ext_pointer/types/1.cc b/libstdc++-v3/testsuite/23_containers/vector/ext_pointer/types/1.cc
index 5b3c673898e..2819851076c 100644
--- a/libstdc++-v3/testsuite/23_containers/vector/ext_pointer/types/1.cc
+++ b/libstdc++-v3/testsuite/23_containers/vector/ext_pointer/types/1.cc
@@ -36,8 +36,8 @@ namespace N
     X operator+(T, std::size_t)
     { return X(); }
 
-  template<typename T>
-    X operator-(T, T)
+  template<typename T, typename U>
+    X operator-(T, U)
     { return X(); }
 }
 
diff --git a/libstdc++-v3/testsuite/23_containers/vector/ext_pointer/types/2.cc b/libstdc++-v3/testsuite/23_containers/vector/ext_pointer/types/2.cc
index cc9519ee618..6c00d1568ae 100644
--- a/libstdc++-v3/testsuite/23_containers/vector/ext_pointer/types/2.cc
+++ b/libstdc++-v3/testsuite/23_containers/vector/ext_pointer/types/2.cc
@@ -38,8 +38,8 @@ namespace N
     X operator+(T, std::size_t)
     { return X(); }
 
-  template<typename T>
-    X operator-(T, T)
+  template<typename T, typename U>
+    X operator-(T, U)
     { return X(); }
 }

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2023-12-06 14:02 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-12-06 14:02 [gcc r14-6221] c++: partial ordering of object parameter [PR53499] Jason Merrill

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).