1 // This test is for the [class.compare.default]p3 added by P2002R0
2 
3 // RUN: %clang_cc1 -std=c++2a -verify %s
4 
5 namespace std {
6   struct strong_ordering {
7     int n;
operator intstd::strong_ordering8     constexpr operator int() const { return n; }
9     static const strong_ordering less, equal, greater;
10   };
11   constexpr strong_ordering strong_ordering::less = {-1};
12   constexpr strong_ordering strong_ordering::equal = {0};
13   constexpr strong_ordering strong_ordering::greater = {1};
14 }
15 
16 struct A {
17   friend bool operator==(const A&, const A&) = default;
18   friend bool operator!=(const A&, const A&) = default;
19 
20   friend std::strong_ordering operator<=>(const A&, const A&) = default;
21   friend bool operator<(const A&, const A&) = default;
22   friend bool operator<=(const A&, const A&) = default;
23   friend bool operator>(const A&, const A&) = default;
24   friend bool operator>=(const A&, const A&) = default;
25 };
26 struct TestA {
27   friend constexpr bool operator==(const A&, const A&) noexcept;
28   friend constexpr bool operator!=(const A&, const A&) noexcept;
29 
30   friend constexpr std::strong_ordering operator<=>(const A&, const A&) noexcept;
31   friend constexpr bool operator<(const A&, const A&);
32   friend constexpr bool operator<=(const A&, const A&);
33   friend constexpr bool operator>(const A&, const A&);
34   friend constexpr bool operator>=(const A&, const A&);
35 };
36 
37 // Declaration order doesn't matter, even though the secondary operators need
38 // to know whether the primary ones are constexpr.
39 struct ReversedA {
40   friend bool operator>=(const ReversedA&, const ReversedA&) = default;
41   friend bool operator>(const ReversedA&, const ReversedA&) = default;
42   friend bool operator<=(const ReversedA&, const ReversedA&) = default;
43   friend bool operator<(const ReversedA&, const ReversedA&) = default;
44   friend std::strong_ordering operator<=>(const ReversedA&, const ReversedA&) = default;
45 
46   friend bool operator!=(const ReversedA&, const ReversedA&) = default;
47   friend bool operator==(const ReversedA&, const ReversedA&) = default;
48 };
49 struct TestReversedA {
50   friend constexpr bool operator>=(const ReversedA&, const ReversedA&);
51   friend constexpr bool operator>(const ReversedA&, const ReversedA&);
52   friend constexpr bool operator<=(const ReversedA&, const ReversedA&);
53   friend constexpr bool operator<(const ReversedA&, const ReversedA&);
54   friend constexpr std::strong_ordering operator<=>(const ReversedA&, const ReversedA&) noexcept;
55 
56   friend constexpr bool operator!=(const ReversedA&, const ReversedA&) noexcept;
57   friend constexpr bool operator==(const ReversedA&, const ReversedA&) noexcept;
58 };
59 
60 struct B {
61   A a;
62   friend bool operator==(const B&, const B&) = default;
63   friend bool operator!=(const B&, const B&) = default;
64 
65   friend std::strong_ordering operator<=>(const B&, const B&) = default;
66   friend bool operator<(const B&, const B&) = default;
67   friend bool operator<=(const B&, const B&) = default;
68   friend bool operator>(const B&, const B&) = default;
69   friend bool operator>=(const B&, const B&) = default;
70 };
71 struct TestB {
72   friend constexpr bool operator==(const B&, const B&) noexcept;
73   friend constexpr bool operator!=(const B&, const B&) noexcept;
74 
75   friend constexpr std::strong_ordering operator<=>(const B&, const B&);
76   friend constexpr bool operator<(const B&, const B&);
77   friend constexpr bool operator<=(const B&, const B&);
78   friend constexpr bool operator>(const B&, const B&);
79   friend constexpr bool operator>=(const B&, const B&);
80 };
81 
82 struct C {
83   friend bool operator==(const C&, const C&); // expected-note {{previous}} expected-note 2{{here}}
84   friend bool operator!=(const C&, const C&) = default; // expected-note {{previous}}
85 
86   friend std::strong_ordering operator<=>(const C&, const C&); // expected-note {{previous}} expected-note 2{{here}}
87   friend bool operator<(const C&, const C&) = default; // expected-note {{previous}}
88   friend bool operator<=(const C&, const C&) = default; // expected-note {{previous}}
89   friend bool operator>(const C&, const C&) = default; // expected-note {{previous}}
90   friend bool operator>=(const C&, const C&) = default; // expected-note {{previous}}
91 };
92 struct TestC {
93   friend constexpr bool operator==(const C&, const C&); // expected-error {{non-constexpr}}
94   friend constexpr bool operator!=(const C&, const C&); // expected-error {{non-constexpr}}
95 
96   friend constexpr std::strong_ordering operator<=>(const C&, const C&); // expected-error {{non-constexpr}}
97   friend constexpr bool operator<(const C&, const C&); // expected-error {{non-constexpr}}
98   friend constexpr bool operator<=(const C&, const C&); // expected-error {{non-constexpr}}
99   friend constexpr bool operator>(const C&, const C&); // expected-error {{non-constexpr}}
100   friend constexpr bool operator>=(const C&, const C&); // expected-error {{non-constexpr}}
101 };
102 
103 struct D {
104   A a;
105   C c;
106   A b;
107   friend bool operator==(const D&, const D&) = default; // expected-note {{previous}}
108   friend bool operator!=(const D&, const D&) = default; // expected-note {{previous}}
109 
110   friend std::strong_ordering operator<=>(const D&, const D&) = default; // expected-note {{previous}}
111   friend bool operator<(const D&, const D&) = default; // expected-note {{previous}}
112   friend bool operator<=(const D&, const D&) = default; // expected-note {{previous}}
113   friend bool operator>(const D&, const D&) = default; // expected-note {{previous}}
114   friend bool operator>=(const D&, const D&) = default; // expected-note {{previous}}
115 };
116 struct TestD {
117   friend constexpr bool operator==(const D&, const D&); // expected-error {{non-constexpr}}
118   friend constexpr bool operator!=(const D&, const D&); // expected-error {{non-constexpr}}
119 
120   friend constexpr std::strong_ordering operator<=>(const D&, const D&); // expected-error {{non-constexpr}}
121   friend constexpr bool operator<(const D&, const D&); // expected-error {{non-constexpr}}
122   friend constexpr bool operator<=(const D&, const D&); // expected-error {{non-constexpr}}
123   friend constexpr bool operator>(const D&, const D&); // expected-error {{non-constexpr}}
124   friend constexpr bool operator>=(const D&, const D&); // expected-error {{non-constexpr}}
125 };
126 
127 
128 struct E {
129   A a;
130   C c; // expected-note 2{{non-constexpr comparison function would be used to compare member 'c'}}
131   A b;
132   friend constexpr bool operator==(const E&, const E&) = default; // expected-error {{cannot be declared constexpr because it invokes a non-constexpr comparison function}}
133   friend constexpr bool operator!=(const E&, const E&) = default;
134 
135   friend constexpr std::strong_ordering operator<=>(const E&, const E&) = default; // expected-error {{cannot be declared constexpr because it invokes a non-constexpr comparison function}}
136   friend constexpr bool operator<(const E&, const E&) = default;
137   friend constexpr bool operator<=(const E&, const E&) = default;
138   friend constexpr bool operator>(const E&, const E&) = default;
139   friend constexpr bool operator>=(const E&, const E&) = default;
140 };
141 
142 struct E2 : A, C { // expected-note 2{{non-constexpr comparison function would be used to compare base class 'C'}}
143   friend constexpr bool operator==(const E2&, const E2&) = default; // expected-error {{cannot be declared constexpr because it invokes a non-constexpr comparison function}}
144   friend constexpr bool operator!=(const E2&, const E2&) = default;
145 
146   friend constexpr std::strong_ordering operator<=>(const E2&, const E2&) = default; // expected-error {{cannot be declared constexpr because it invokes a non-constexpr comparison function}}
147   friend constexpr bool operator<(const E2&, const E2&) = default;
148   friend constexpr bool operator<=(const E2&, const E2&) = default;
149   friend constexpr bool operator>(const E2&, const E2&) = default;
150   friend constexpr bool operator>=(const E2&, const E2&) = default;
151 };
152 
153 struct F {
154   friend bool operator==(const F&, const F&); // expected-note {{here}}
155   friend constexpr bool operator!=(const F&, const F&) = default; // expected-error {{cannot be declared constexpr because it invokes a non-constexpr comparison function}}
156 
157   friend std::strong_ordering operator<=>(const F&, const F&); // expected-note 4{{here}}
158   friend constexpr bool operator<(const F&, const F&) = default; // expected-error {{cannot be declared constexpr because it invokes a non-constexpr comparison function}}
159   friend constexpr bool operator<=(const F&, const F&) = default; // expected-error {{cannot be declared constexpr because it invokes a non-constexpr comparison function}}
160   friend constexpr bool operator>(const F&, const F&) = default; // expected-error {{cannot be declared constexpr because it invokes a non-constexpr comparison function}}
161   friend constexpr bool operator>=(const F&, const F&) = default; // expected-error {{cannot be declared constexpr because it invokes a non-constexpr comparison function}}
162 };
163 
164 // No implicit 'constexpr' if it's not the first declaration.
165 // FIXME: This rule creates problems for reordering of declarations; is this
166 // really the right model?
167 struct G;
168 bool operator==(const G&, const G&);
169 bool operator!=(const G&, const G&);
170 std::strong_ordering operator<=>(const G&, const G&);
171 bool operator<(const G&, const G&);
172 bool operator<=(const G&, const G&);
173 bool operator>(const G&, const G&);
174 bool operator>=(const G&, const G&);
175 struct G {
176   friend bool operator==(const G&, const G&) = default;
177   friend bool operator!=(const G&, const G&) = default;
178 
179   friend std::strong_ordering operator<=>(const G&, const G&) = default;
180   friend bool operator<(const G&, const G&) = default;
181   friend bool operator<=(const G&, const G&) = default;
182   friend bool operator>(const G&, const G&) = default;
183   friend bool operator>=(const G&, const G&) = default;
184 };
185 bool operator==(const G&, const G&);
186 bool operator!=(const G&, const G&);
187 
188 std::strong_ordering operator<=>(const G&, const G&);
189 bool operator<(const G&, const G&);
190 bool operator<=(const G&, const G&);
191 bool operator>(const G&, const G&);
192 bool operator>=(const G&, const G&);
193 
194 namespace PR44721 {
operator ==(T const &,T const &)195   template <typename T> bool operator==(T const &, T const &) { return true; }
operator !=(T const &,U const &)196   template <typename T, typename U> bool operator!=(T const &, U const &) { return true; }
operator <=>(T const &,T const &)197   template <typename T> int operator<=>(T const &, T const &) { return 0; }
198 
199   struct S {
200     friend bool operator==(const S &, const S &) = default;
201     friend bool operator<=>(const S &, const S &) = default;
202     int x;
203   };
204 }
205