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