On Wed, 6 Dec 2023 at 02:21, Jason Merrill wrote: > > Tested x86_64-pc-linux-gnu. Are the library test changes OK?
Sure, they seem fine. > A reduced > example of the issue is at https://godbolt.org/z/cPxrcnKjG > > -- 8< -- > > 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. > --- > gcc/cp/pt.cc | 68 ++++++++++++++----- > .../g++.dg/template/partial-order4.C | 17 +++++ > gcc/testsuite/g++.dg/template/spec26.C | 10 +-- > .../vector/ext_pointer/types/1.cc | 4 +- > .../vector/ext_pointer/types/2.cc | 4 +- > 5 files changed, 78 insertions(+), 25 deletions(-) > create mode 100644 gcc/testsuite/g++.dg/template/partial-order4.C > > diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc > index 924a20973b4..4b2af4f7aca 100644 > --- a/gcc/cp/pt.cc > +++ b/gcc/cp/pt.cc > @@ -25218,27 +25218,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 <nat...@codesourcery.com> > > // PR 23519 template specialization ordering (DR214) > // Origin: Maxim Yegorushkin <maxim.yegorush...@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(); } > } > > > base-commit: 0e7fee57c00ae17611651e0b057dc03b6e276b82 > -- > 2.39.3 >