1 // RUN: %clang_cc1 -std=c++2a -verify %s -fcxx-exceptions -triple=x86_64-linux-gnu
2
3 #include "Inputs/std-compare.h"
4
5 namespace ThreeWayComparison {
6 struct A {
7 int n;
operator <=>(const A & a,const A & b)8 constexpr friend int operator<=>(const A &a, const A &b) {
9 return a.n < b.n ? -1 : a.n > b.n ? 1 : 0;
10 }
11 };
12 static_assert(A{1} <=> A{2} < 0);
13 static_assert(A{2} <=> A{1} > 0);
14 static_assert(A{2} <=> A{2} == 0);
15
16 static_assert(1 <=> 2 < 0);
17 static_assert(2 <=> 1 > 0);
18 static_assert(1 <=> 1 == 0);
19 constexpr int k = (1 <=> 1, 0);
20 // expected-warning@-1 {{three-way comparison result unused}}
21
22 static_assert(std::strong_ordering::equal == 0);
23
f()24 constexpr void f() {
25 void(1 <=> 1);
26 }
27
28 struct MemPtr {
fooThreeWayComparison::MemPtr29 void foo() {}
barThreeWayComparison::MemPtr30 void bar() {}
31 int data;
32 int data2;
33 long data3;
34 };
35
36 struct MemPtr2 {
fooThreeWayComparison::MemPtr237 void foo() {}
barThreeWayComparison::MemPtr238 void bar() {}
39 int data;
40 int data2;
41 long data3;
42 };
43 using MemPtrT = void (MemPtr::*)();
44
45 using FnPtrT = void (*)();
46
FnPtr1()47 void FnPtr1() {}
FnPtr2()48 void FnPtr2() {}
49
50 #define CHECK(...) ((__VA_ARGS__) ? void() : throw "error")
51 #define CHECK_TYPE(...) static_assert(__is_same(__VA_ARGS__));
52
__anon62541c530102null53 constexpr bool test_constexpr_success = [] {
54 {
55 auto &EQ = std::strong_ordering::equal;
56 auto &LESS = std::strong_ordering::less;
57 auto &GREATER = std::strong_ordering::greater;
58 using SO = std::strong_ordering;
59 auto eq = (42 <=> 42);
60 CHECK_TYPE(decltype(eq), SO);
61 CHECK(eq.test_eq(EQ));
62
63 auto less = (-1 <=> 0);
64 CHECK_TYPE(decltype(less), SO);
65 CHECK(less.test_eq(LESS));
66
67 auto greater = (42l <=> 1u);
68 CHECK_TYPE(decltype(greater), SO);
69 CHECK(greater.test_eq(GREATER));
70 }
71 {
72 using PO = std::partial_ordering;
73 auto EQUIV = PO::equivalent;
74 auto LESS = PO::less;
75 auto GREATER = PO::greater;
76
77 auto eq = (42.0 <=> 42.0);
78 CHECK_TYPE(decltype(eq), PO);
79 CHECK(eq.test_eq(EQUIV));
80
81 auto less = (39.0 <=> 42.0);
82 CHECK_TYPE(decltype(less), PO);
83 CHECK(less.test_eq(LESS));
84
85 auto greater = (-10.123 <=> -101.1);
86 CHECK_TYPE(decltype(greater), PO);
87 CHECK(greater.test_eq(GREATER));
88 }
89 {
90 using SE = std::strong_equality;
91 auto EQ = SE::equal;
92 auto NEQ = SE::nonequal;
93
94 MemPtrT P1 = &MemPtr::foo;
95 MemPtrT P12 = &MemPtr::foo;
96 MemPtrT P2 = &MemPtr::bar;
97 MemPtrT P3 = nullptr;
98
99 auto eq = (P1 <=> P12);
100 CHECK_TYPE(decltype(eq), SE);
101 CHECK(eq.test_eq(EQ));
102
103 auto neq = (P1 <=> P2);
104 CHECK_TYPE(decltype(eq), SE);
105 CHECK(neq.test_eq(NEQ));
106
107 auto eq2 = (P3 <=> nullptr);
108 CHECK_TYPE(decltype(eq2), SE);
109 CHECK(eq2.test_eq(EQ));
110 }
111 {
112 using SE = std::strong_equality;
113 auto EQ = SE::equal;
114 auto NEQ = SE::nonequal;
115
116 FnPtrT F1 = &FnPtr1;
117 FnPtrT F12 = &FnPtr1;
118 FnPtrT F2 = &FnPtr2;
119 FnPtrT F3 = nullptr;
120
121 auto eq = (F1 <=> F12);
122 CHECK_TYPE(decltype(eq), SE);
123 CHECK(eq.test_eq(EQ));
124
125 auto neq = (F1 <=> F2);
126 CHECK_TYPE(decltype(neq), SE);
127 CHECK(neq.test_eq(NEQ));
128 }
129 { // mixed nullptr tests
130 using SO = std::strong_ordering;
131 using SE = std::strong_equality;
132
133 int x = 42;
134 int *xp = &x;
135
136 MemPtrT mf = nullptr;
137 MemPtrT mf2 = &MemPtr::foo;
138 auto r3 = (mf <=> nullptr);
139 CHECK_TYPE(decltype(r3), std::strong_equality);
140 CHECK(r3.test_eq(SE::equal));
141 }
142
143 return true;
144 }();
145
146 template <auto LHS, auto RHS, bool ExpectTrue = false>
test_constexpr()147 constexpr bool test_constexpr() {
148 using nullptr_t = decltype(nullptr);
149 using LHSTy = decltype(LHS);
150 using RHSTy = decltype(RHS);
151 // expected-note@+1 {{subexpression not valid in a constant expression}}
152 auto Res = (LHS <=> RHS);
153 if constexpr (__is_same(LHSTy, nullptr_t) || __is_same(RHSTy, nullptr_t)) {
154 CHECK_TYPE(decltype(Res), std::strong_equality);
155 }
156 if (ExpectTrue)
157 return Res == 0;
158 return Res != 0;
159 }
160 int dummy = 42;
161 int dummy2 = 101;
162
163 constexpr bool tc1 = test_constexpr<nullptr, &dummy>();
164 constexpr bool tc2 = test_constexpr<&dummy, nullptr>();
165
166 // OK, equality comparison only
167 constexpr bool tc3 = test_constexpr<&MemPtr::foo, nullptr>();
168 constexpr bool tc4 = test_constexpr<nullptr, &MemPtr::foo>();
169 constexpr bool tc5 = test_constexpr<&MemPtr::foo, &MemPtr::bar>();
170
171 constexpr bool tc6 = test_constexpr<&MemPtr::data, nullptr>();
172 constexpr bool tc7 = test_constexpr<nullptr, &MemPtr::data>();
173 constexpr bool tc8 = test_constexpr<&MemPtr::data, &MemPtr::data2>();
174
175 // expected-error@+1 {{must be initialized by a constant expression}}
176 constexpr bool tc9 = test_constexpr<&dummy, &dummy2>(); // expected-note {{in call}}
177
178 template <class T, class R, class I>
makeComplex(R r,I i)179 constexpr T makeComplex(R r, I i) {
180 T res{r, i};
181 return res;
182 };
183
184 template <class T, class ResultT>
complex_test(T x,T y,ResultT Expect)185 constexpr bool complex_test(T x, T y, ResultT Expect) {
186 auto res = x <=> y;
187 CHECK_TYPE(decltype(res), ResultT);
188 return res.test_eq(Expect);
189 }
190 static_assert(complex_test(makeComplex<_Complex double>(0.0, 0.0),
191 makeComplex<_Complex double>(0.0, 0.0),
192 std::weak_equality::equivalent));
193 static_assert(complex_test(makeComplex<_Complex double>(0.0, 0.0),
194 makeComplex<_Complex double>(1.0, 0.0),
195 std::weak_equality::nonequivalent));
196 static_assert(complex_test(makeComplex<_Complex double>(0.0, 0.0),
197 makeComplex<_Complex double>(0.0, 1.0),
198 std::weak_equality::nonequivalent));
199 static_assert(complex_test(makeComplex<_Complex int>(0, 0),
200 makeComplex<_Complex int>(0, 0),
201 std::strong_equality::equal));
202 static_assert(complex_test(makeComplex<_Complex int>(0, 0),
203 makeComplex<_Complex int>(1, 0),
204 std::strong_equality::nonequal));
205 // TODO: defaulted operator <=>
206 } // namespace ThreeWayComparison
207
for_range_init()208 constexpr bool for_range_init() {
209 int k = 0;
210 for (int arr[3] = {1, 2, 3}; int n : arr) k += n;
211 return k == 6;
212 }
213 static_assert(for_range_init());
214