aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2020-06-18 17:41:43 -0400
committerGiuliano Belinassi <giuliano.belinassi@usp.br>2020-08-17 13:14:15 -0300
commit382b55e58514e39ca06f37b20a02bfd0f752de20 (patch)
tree83ffda61739732a3a420def1159f80a8b31a54f3 /gcc
parent89e3dc4dbca501d7990a8de8b862699c1b7a76b1 (diff)
downloadgcc-382b55e58514e39ca06f37b20a02bfd0f752de20.zip
gcc-382b55e58514e39ca06f37b20a02bfd0f752de20.tar.gz
gcc-382b55e58514e39ca06f37b20a02bfd0f752de20.tar.bz2
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.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/method.c38
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/spaceship-err4.C6
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/spaceship-friend1.C26
3 files changed, 48 insertions, 22 deletions
diff --git a/gcc/cp/method.c b/gcc/cp/method.c
index b23764b..2a98907 100644
--- a/gcc/cp/method.c
+++ b/gcc/cp/method.c
@@ -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))
diff --git a/gcc/testsuite/g++.dg/cpp2a/spaceship-err4.C b/gcc/testsuite/g++.dg/cpp2a/spaceship-err4.C
index b044914..a39e506 100644
--- a/gcc/testsuite/g++.dg/cpp2a/spaceship-err4.C
+++ b/gcc/testsuite/g++.dg/cpp2a/spaceship-err4.C
@@ -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" }
diff --git a/gcc/testsuite/g++.dg/cpp2a/spaceship-friend1.C b/gcc/testsuite/g++.dg/cpp2a/spaceship-friend1.C
new file mode 100644
index 0000000..24bbc74
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/spaceship-friend1.C
@@ -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" }
+
+}