summaryrefslogtreecommitdiffstats
path: root/clang/test/CXX/class/class.compare/class.compare.default/p4.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/test/CXX/class/class.compare/class.compare.default/p4.cpp')
-rw-r--r--clang/test/CXX/class/class.compare/class.compare.default/p4.cpp146
1 files changed, 146 insertions, 0 deletions
diff --git a/clang/test/CXX/class/class.compare/class.compare.default/p4.cpp b/clang/test/CXX/class/class.compare/class.compare.default/p4.cpp
new file mode 100644
index 00000000000..1ab77075277
--- /dev/null
+++ b/clang/test/CXX/class/class.compare/class.compare.default/p4.cpp
@@ -0,0 +1,146 @@
+// RUN: %clang_cc1 -std=c++2a -verify %s
+
+// This test is for [class.compare.default]p3 as modified and renumbered to p4
+// by P2002R0.
+
+namespace std {
+ struct strong_ordering {
+ int n;
+ constexpr operator int() const { return n; }
+ static const strong_ordering less, equal, greater;
+ };
+ constexpr strong_ordering strong_ordering::less = {-1};
+ constexpr strong_ordering strong_ordering::equal = {0};
+ constexpr strong_ordering strong_ordering::greater = {1};
+}
+
+namespace N {
+ struct A {
+ friend constexpr std::strong_ordering operator<=>(const A&, const A&) = default;
+ };
+
+ constexpr bool (*test_a_not_found)(const A&, const A&) = &operator==; // expected-error {{undeclared}}
+
+ constexpr bool operator==(const A&, const A&);
+ constexpr bool (*test_a)(const A&, const A&) = &operator==;
+ static_assert((*test_a)(A(), A()));
+}
+
+struct B1 {
+ virtual std::strong_ordering operator<=>(const B1&) const = default;
+};
+bool (B1::*test_b)(const B1&) const = &B1::operator==;
+
+struct C1 : B1 {
+ // OK, B1::operator== is virtual.
+ bool operator==(const B1&) const override;
+};
+
+struct B2 {
+ std::strong_ordering operator<=>(const B2&) const = default;
+};
+
+struct C2 : B2 {
+ bool operator==(const B2&) const override; // expected-error {{only virtual member functions}}
+};
+
+struct D {
+ std::strong_ordering operator<=>(const D&) const;
+ virtual std::strong_ordering operator<=>(const struct E&) const = 0;
+};
+struct E : D {
+ // expected-error@+2 {{only virtual member functions}}
+ // expected-note@+1 {{while declaring the corresponding implicit 'operator==' for this defaulted 'operator<=>'}}
+ std::strong_ordering operator<=>(const E&) const override = default;
+};
+
+struct F {
+ [[deprecated("oh no")]] std::strong_ordering operator<=>(const F&) const = default; // expected-note 4{{deprecated}}
+};
+void use_f(F f) {
+ void(f <=> f); // expected-warning {{oh no}}
+ void(f < f); // expected-warning {{oh no}}
+ void(f == f); // expected-warning {{oh no}}
+ void(f != f); // expected-warning {{oh no}}
+}
+
+class G {
+ // expected-note@+2 {{implicitly declared private here}}
+ // expected-note-re@+1 {{{{^}}declared private here}}
+ std::strong_ordering operator<=>(const G&) const = default;
+public:
+};
+void use_g(G g) {
+ void(g <=> g); // expected-error {{private}}
+ void(g == g); // expected-error {{private}}
+}
+
+struct H {
+ bool operator==(const H&) const; // expected-note {{here}}
+ constexpr std::strong_ordering operator<=>(const H&) const { return std::strong_ordering::equal; }
+};
+
+struct I {
+ H h; // expected-note {{used to compare}}
+ // expected-error@+1 {{defaulted definition of three-way comparison operator cannot be declared constexpr because the corresponding implicit 'operator==' invokes a non-constexpr comparison function}}
+ constexpr std::strong_ordering operator<=>(const I&) const = default;
+};
+
+struct J {
+ std::strong_ordering operator<=>(const J&) const & = default; // expected-note {{candidate function (the implicit 'operator==' for this 'operator<=>)'}}
+ friend std::strong_ordering operator<=>(const J&, const J&) = default; // expected-note {{candidate function (the implicit 'operator==' for this 'operator<=>)'}}
+};
+void use_j(J j) {
+ void(j == j); // expected-error {{ambiguous}}
+}
+
+namespace DeleteAfterFirstDecl {
+ bool operator==(const struct Q&, const struct Q&);
+ struct Q {
+ struct X {
+ friend std::strong_ordering operator<=>(const X&, const X&);
+ } x; // expected-note {{no viable comparison}}
+ // expected-error@+1 {{defaulting the corresponding implicit 'operator==' for this defaulted 'operator<=>' would delete it after its first declaration}}
+ friend std::strong_ordering operator<=>(const Q&, const Q&) = default;
+ };
+}
+
+// Note, substitution here results in the second parameter of 'operator=='
+// referring to the first parameter of 'operator==', not to the first parameter
+// of 'operator<=>'.
+// FIXME: Find a case where this matters (attribute enable_if?).
+struct K {
+ friend std::strong_ordering operator<=>(const K &k, decltype(k)) = default;
+};
+bool test_k = K() == K();
+
+namespace NoInjectionIfOperatorEqualsDeclared {
+ struct A {
+ void operator==(int); // expected-note 2{{not viable}}
+ std::strong_ordering operator<=>(const A&) const = default;
+ };
+ bool test_a = A() == A(); // expected-error {{invalid operands}}
+
+ struct B {
+ friend void operator==(int, struct Q); // expected-note {{not viable}}
+ std::strong_ordering operator<=>(const B&) const = default;
+ };
+ bool test_b = B() == B(); // expected-error {{invalid operands}}
+
+ struct C {
+ void operator==(int); // expected-note 2{{not viable}}
+ friend std::strong_ordering operator<=>(const C&, const C&) = default;
+ };
+ bool test_c = C() == C(); // expected-error {{invalid operands}}
+
+ struct D {
+ void f() {
+ void operator==(const D&, int);
+ }
+ struct X {
+ friend void operator==(const D&, int);
+ };
+ friend std::strong_ordering operator<=>(const D&, const D&) = default;
+ };
+ bool test_d = D() == D();
+}
OpenPOWER on IntegriCloud