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))
- {
- len--; /* LEN is the number of significant arguments for DECL1 */
- args1 = TREE_CHAIN (args1);
- if (!DECL_STATIC_FUNCTION_P (decl2))
+ /* 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))
+ {
+ /* 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 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 (decl2))
+ 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);
- if (!DECL_STATIC_FUNCTION_P (decl1))
+ }
+ 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)
{
- len--;
- args1 = TREE_CHAIN (args1);
+ 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. */
-// { 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
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;}
if ((b - a) != 2)
return 2;
- if ((b * a) != 6)
+ if ((b * a) != 6) // { dg-error "ambiguous" }
return 3;
}