c++: Allow defaulted comparison outside class.
Implementing P2085, another refinement to the operator<=> specification from the Prague meeting. It was deemed desirable to be able to have a non-inline defaulted definition of a comparison operator just like you can with other defaulted functions. gcc/cp/ChangeLog: * method.c (early_check_defaulted_comparison): Allow defaulting comparison outside class. Complain if non-member operator isn't a friend. gcc/testsuite/ChangeLog: * g++.dg/cpp2a/spaceship-friend1.C: New test. * g++.dg/cpp2a/spaceship-err4.C: Adjust diagnostic.
This commit is contained in:
parent
4cea81adab
commit
4058454c9e
@ -1102,17 +1102,6 @@ early_check_defaulted_comparison (tree fn)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ctx)
|
||||
{
|
||||
if (DECL_OVERLOADED_OPERATOR_IS (fn, SPACESHIP_EXPR))
|
||||
error_at (loc, "three-way comparison operator can only be defaulted "
|
||||
"in a class definition");
|
||||
else
|
||||
error_at (loc, "equality comparison operator can only be defaulted "
|
||||
"in a class definition");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!DECL_OVERLOADED_OPERATOR_IS (fn, SPACESHIP_EXPR)
|
||||
&& !same_type_p (TREE_TYPE (TREE_TYPE (fn)), boolean_type_node))
|
||||
{
|
||||
@ -1146,16 +1135,27 @@ early_check_defaulted_comparison (tree fn)
|
||||
for (; parmnode != void_list_node; parmnode = TREE_CHAIN (parmnode))
|
||||
{
|
||||
tree parmtype = TREE_VALUE (parmnode);
|
||||
if (same_type_p (parmtype, ctx))
|
||||
if (CLASS_TYPE_P (parmtype))
|
||||
saw_byval = true;
|
||||
else if (TREE_CODE (parmtype) != REFERENCE_TYPE
|
||||
|| TYPE_REF_IS_RVALUE (parmtype)
|
||||
|| TYPE_QUALS (TREE_TYPE (parmtype)) != TYPE_QUAL_CONST
|
||||
|| !(same_type_ignoring_top_level_qualifiers_p
|
||||
(TREE_TYPE (parmtype), ctx)))
|
||||
saw_bad = true;
|
||||
else if (TREE_CODE (parmtype) == REFERENCE_TYPE
|
||||
&& !TYPE_REF_IS_RVALUE (parmtype)
|
||||
&& TYPE_QUALS (TREE_TYPE (parmtype)) == TYPE_QUAL_CONST)
|
||||
{
|
||||
saw_byref = true;
|
||||
parmtype = TREE_TYPE (parmtype);
|
||||
}
|
||||
else
|
||||
saw_byref = true;
|
||||
saw_bad = true;
|
||||
|
||||
if (!saw_bad && !ctx)
|
||||
{
|
||||
/* Defaulted outside the class body. */
|
||||
ctx = TYPE_MAIN_VARIANT (parmtype);
|
||||
if (!is_friend (ctx, fn))
|
||||
error_at (loc, "defaulted %qD is not a friend of %qT", fn, ctx);
|
||||
}
|
||||
else if (!same_type_ignoring_top_level_qualifiers_p (parmtype, ctx))
|
||||
saw_bad = true;
|
||||
}
|
||||
|
||||
if (saw_bad || (saw_byval && saw_byref))
|
||||
|
@ -2,6 +2,6 @@
|
||||
// { dg-do compile { target c++20 } }
|
||||
|
||||
struct B {};
|
||||
bool operator!=(const B&, const B&) = default; // { dg-error "equality comparison operator can only be defaulted in a class definition" }
|
||||
bool operator==(const B&, const B&) = default; // { dg-error "equality comparison operator can only be defaulted in a class definition" }
|
||||
bool operator<=>(const B&, const B&) = default; // { dg-error "three-way comparison operator can only be defaulted in a class definition" }
|
||||
bool operator!=(const B&, const B&) = default; // { dg-error "not a friend" }
|
||||
bool operator==(const B&, const B&) = default; // { dg-error "not a friend" }
|
||||
bool operator<=>(const B&, const B&) = default; // { dg-error "not a friend" }
|
||||
|
26
gcc/testsuite/g++.dg/cpp2a/spaceship-friend1.C
Normal file
26
gcc/testsuite/g++.dg/cpp2a/spaceship-friend1.C
Normal file
@ -0,0 +1,26 @@
|
||||
// P2085, separate definition of defaulted comparisons
|
||||
// { dg-do compile { target c++20 } }
|
||||
|
||||
namespace X {
|
||||
|
||||
struct A {
|
||||
int i;
|
||||
friend constexpr bool operator==(const A&,const A&);
|
||||
};
|
||||
|
||||
inline constexpr bool operator==(const A&,const A&)=default;
|
||||
|
||||
static_assert (A() == A());
|
||||
|
||||
}
|
||||
|
||||
namespace Y {
|
||||
|
||||
struct A {
|
||||
int i;
|
||||
// friend bool operator==(const A&,const A&);
|
||||
};
|
||||
|
||||
inline bool operator==(const A&,const A&)=default; // { dg-error "not a friend" }
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user