1 // RUN: %clang_cc1 -std=c++2a -verify %s
2
3 // This test is for [class.compare.default]p3 as modified and renumbered to p4
4 // by P2002R0.
5
6 namespace std {
7 struct strong_ordering {
8 int n;
operator intstd::strong_ordering9 constexpr operator int() const { return n; }
10 static const strong_ordering less, equal, greater;
11 };
12 constexpr strong_ordering strong_ordering::less = {-1};
13 constexpr strong_ordering strong_ordering::equal = {0};
14 constexpr strong_ordering strong_ordering::greater = {1};
15 }
16
17 namespace N {
18 struct A {
19 friend constexpr std::strong_ordering operator<=>(const A&, const A&) = default;
20 };
21
22 constexpr bool (*test_a_not_found)(const A&, const A&) = &operator==; // expected-error {{undeclared}}
23
24 constexpr bool operator==(const A&, const A&) noexcept;
25 constexpr bool (*test_a)(const A&, const A&) noexcept = &operator==;
26 static_assert((*test_a)(A(), A()));
27 }
28
29 struct B1 {
30 virtual std::strong_ordering operator<=>(const B1&) const = default;
31 };
32 bool (B1::*test_b)(const B1&) const = &B1::operator==;
33
34 struct C1 : B1 {
35 // OK, B1::operator== is virtual.
36 bool operator==(const B1&) const override;
37 };
38
39 struct B2 {
40 std::strong_ordering operator<=>(const B2&) const = default;
41 };
42
43 struct C2 : B2 {
44 bool operator==(const B2&) const override; // expected-error {{only virtual member functions}}
45 };
46
47 struct D {
48 std::strong_ordering operator<=>(const D&) const;
49 virtual std::strong_ordering operator<=>(const struct E&) const = 0;
50 };
51 struct E : D {
52 // expected-error@+2 {{only virtual member functions}}
53 // expected-note@+1 {{while declaring the corresponding implicit 'operator==' for this defaulted 'operator<=>'}}
54 std::strong_ordering operator<=>(const E&) const override = default;
55 };
56
57 struct F {
58 [[deprecated("oh no")]] std::strong_ordering operator<=>(const F&) const = default; // expected-note 4{{deprecated}}
59 };
use_f(F f)60 void use_f(F f) {
61 void(f <=> f); // expected-warning {{oh no}}
62 void(f < f); // expected-warning {{oh no}}
63 void(f == f); // expected-warning {{oh no}}
64 void(f != f); // expected-warning {{oh no}}
65 }
66
67 class G {
68 // expected-note@+2 {{implicitly declared private here}}
69 // expected-note-re@+1 {{{{^}}declared private here}}
70 std::strong_ordering operator<=>(const G&) const = default;
71 public:
72 };
use_g(G g)73 void use_g(G g) {
74 void(g <=> g); // expected-error {{private}}
75 void(g == g); // expected-error {{private}}
76 }
77
78 struct H {
79 bool operator==(const H&) const; // expected-note {{here}}
operator <=>H80 constexpr std::strong_ordering operator<=>(const H&) const { return std::strong_ordering::equal; }
81 };
82
83 struct I {
84 H h; // expected-note {{used to compare}}
85 // 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}}
86 constexpr std::strong_ordering operator<=>(const I&) const = default;
87 };
88
89 struct J {
90 std::strong_ordering operator<=>(const J&) const & = default; // expected-note {{candidate function (the implicit 'operator==' for this 'operator<=>)'}}
91 friend std::strong_ordering operator<=>(const J&, const J&) = default; // expected-note {{candidate function (the implicit 'operator==' for this 'operator<=>)'}}
92 };
use_j(J j)93 void use_j(J j) {
94 void(j == j); // expected-error {{ambiguous}}
95 }
96
97 namespace DeleteAfterFirstDecl {
98 bool operator==(const struct Q&, const struct Q&);
99 struct Q {
100 struct X {
101 friend std::strong_ordering operator<=>(const X&, const X&);
102 } x; // expected-note {{no viable comparison}}
103 // expected-error@+1 {{defaulting the corresponding implicit 'operator==' for this defaulted 'operator<=>' would delete it after its first declaration}}
104 friend std::strong_ordering operator<=>(const Q&, const Q&) = default;
105 };
106 }
107
108 // Note, substitution here results in the second parameter of 'operator=='
109 // referring to the first parameter of 'operator==', not to the first parameter
110 // of 'operator<=>'.
111 // FIXME: Find a case where this matters (attribute enable_if?).
112 struct K {
113 friend std::strong_ordering operator<=>(const K &k, decltype(k)) = default;
114 };
115 bool test_k = K() == K();
116
117 namespace NoInjectionIfOperatorEqualsDeclared {
118 struct A {
119 void operator==(int); // expected-note 2{{not viable}}
120 std::strong_ordering operator<=>(const A&) const = default;
121 };
122 bool test_a = A() == A(); // expected-error {{invalid operands}}
123
124 struct B {
125 friend void operator==(int, struct Q); // expected-note 2{{not viable}}
126 std::strong_ordering operator<=>(const B&) const = default;
127 };
128 bool test_b = B() == B(); // expected-error {{invalid operands}}
129
130 struct C {
131 void operator==(int); // expected-note 2{{not viable}}
132 friend std::strong_ordering operator<=>(const C&, const C&) = default;
133 };
134 bool test_c = C() == C(); // expected-error {{invalid operands}}
135
136 struct D {
fNoInjectionIfOperatorEqualsDeclared::D137 void f() {
138 void operator==(const D&, int);
139 }
140 struct X {
141 friend void operator==(const D&, int);
142 };
143 friend std::strong_ordering operator<=>(const D&, const D&) = default;
144 };
145 bool test_d = D() == D();
146 }
147