1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 // UNSUPPORTED: c++03, c++11, c++14, c++17
10 
11 // <compare>
12 
13 // class strong_ordering
14 
15 
16 #include <compare>
17 #include <type_traits>
18 #include <cassert>
19 
20 #include "test_macros.h"
21 
22 const volatile void* volatile sink;
23 
24 void test_static_members() {
25   DoNotOptimize(&std::strong_ordering::less);
26   DoNotOptimize(&std::strong_ordering::equal);
27   DoNotOptimize(&std::strong_ordering::equivalent);
28   DoNotOptimize(&std::strong_ordering::greater);
29 }
30 
31 void test_signatures() {
32   auto& Eq = std::strong_ordering::equivalent;
33 
34   ASSERT_NOEXCEPT(Eq == 0);
35   ASSERT_NOEXCEPT(0 == Eq);
36   ASSERT_NOEXCEPT(Eq != 0);
37   ASSERT_NOEXCEPT(0 != Eq);
38   ASSERT_NOEXCEPT(0 < Eq);
39   ASSERT_NOEXCEPT(Eq < 0);
40   ASSERT_NOEXCEPT(0 <= Eq);
41   ASSERT_NOEXCEPT(Eq <= 0);
42   ASSERT_NOEXCEPT(0 > Eq);
43   ASSERT_NOEXCEPT(Eq > 0);
44   ASSERT_NOEXCEPT(0 >= Eq);
45   ASSERT_NOEXCEPT(Eq >= 0);
46 #ifndef TEST_HAS_NO_SPACESHIP_OPERATOR
47   ASSERT_NOEXCEPT(0 <=> Eq);
48   ASSERT_NOEXCEPT(Eq <=> 0);
49   ASSERT_SAME_TYPE(decltype(Eq <=> 0), std::strong_ordering);
50   ASSERT_SAME_TYPE(decltype(0 <=> Eq), std::strong_ordering);
51 #endif
52 }
53 
54 constexpr bool test_conversion() {
55   static_assert(std::is_convertible<const std::strong_ordering&,
56       std::weak_equality>::value, "");
57   { // value == 0
58     auto V = std::strong_ordering::equivalent;
59     std::weak_equality WV = V;
60     assert(WV == 0);
61   }
62   std::strong_ordering WeakTestCases[] = {
63       std::strong_ordering::less,
64       std::strong_ordering::greater,
65   };
66   for (auto V : WeakTestCases)
67   { // value != 0
68     std::weak_equality WV = V;
69     assert(WV != 0);
70   }
71   static_assert(std::is_convertible<const std::strong_ordering&,
72       std::strong_equality>::value, "");
73   { // value == 0
74     auto V = std::strong_ordering::equivalent;
75     std::strong_equality WV = V;
76     assert(WV == 0);
77   }
78   { // value == 0
79     auto V = std::strong_ordering::equal;
80     std::strong_equality WV = V;
81     assert(WV == 0);
82   }
83   std::strong_ordering StrongTestCases[] = {
84       std::strong_ordering::less,
85       std::strong_ordering::greater,
86   };
87   for (auto V : StrongTestCases)
88   { // value != 0
89     std::strong_equality WV = V;
90     assert(WV != 0);
91   }
92 
93   static_assert(std::is_convertible<const std::strong_ordering&,
94       std::partial_ordering>::value, "");
95   { // value == 0
96     auto V = std::strong_ordering::equivalent;
97     std::partial_ordering WV = V;
98     assert(WV == 0);
99   }
100   { // value < 0
101     auto V = std::strong_ordering::less;
102     std::partial_ordering WV = V;
103     assert(WV < 0);
104   }
105   { // value > 0
106     auto V = std::strong_ordering::greater;
107     std::partial_ordering WV = V;
108     assert(WV > 0);
109   }
110 
111   static_assert(std::is_convertible<const std::strong_ordering&,
112       std::weak_ordering>::value, "");
113   { // value == 0
114     auto V = std::strong_ordering::equivalent;
115     std::weak_ordering WV = V;
116     assert(WV == 0);
117   }
118   { // value < 0
119     auto V = std::strong_ordering::less;
120     std::weak_ordering WV = V;
121     assert(WV < 0);
122   }
123   { // value > 0
124     auto V = std::strong_ordering::greater;
125     std::weak_ordering WV = V;
126     assert(WV > 0);
127   }
128   return true;
129 }
130 
131 constexpr bool test_constexpr() {
132   auto& Eq = std::strong_ordering::equal;
133   auto& Equiv = std::strong_ordering::equivalent;
134   auto& Less = std::strong_ordering::less;
135   auto& Greater = std::strong_ordering::greater;
136   struct {
137     std::strong_ordering Value;
138     bool ExpectEq;
139     bool ExpectNeq;
140     bool ExpectLess;
141     bool ExpectGreater;
142   } TestCases[] = {
143       {Eq, true, false, false, false},
144       {Equiv, true, false, false, false},
145       {Less, false, true, true, false},
146       {Greater, false, true, false, true},
147   };
148   for (auto TC : TestCases) {
149     auto V = TC.Value;
150     assert((V == 0) == TC.ExpectEq);
151     assert((0 == V) == TC.ExpectEq);
152     assert((V != 0) == TC.ExpectNeq);
153     assert((0 != V) == TC.ExpectNeq);
154 
155     assert((V < 0) == TC.ExpectLess);
156     assert((V > 0) == TC.ExpectGreater);
157     assert((V <= 0) == (TC.ExpectLess || TC.ExpectEq));
158     assert((V >= 0) == (TC.ExpectGreater || TC.ExpectEq));
159 
160     assert((0 < V) == TC.ExpectGreater);
161     assert((0 > V) == TC.ExpectLess);
162     assert((0 <= V) == (TC.ExpectGreater || TC.ExpectEq));
163     assert((0 >= V) == (TC.ExpectLess || TC.ExpectEq));
164   }
165 #ifndef TEST_HAS_NO_SPACESHIP_OPERATOR
166   {
167     std::strong_ordering res = (Eq <=> 0);
168     ((void)res);
169     res = (0 <=> Eq);
170     ((void)res);
171   }
172   enum ExpectRes {
173     ER_Greater,
174     ER_Less,
175     ER_Equiv
176   };
177   struct {
178     std::strong_ordering Value;
179     ExpectRes Expect;
180   } SpaceshipTestCases[] = {
181       {std::strong_ordering::equivalent, ER_Equiv},
182       {std::strong_ordering::less, ER_Less},
183       {std::strong_ordering::greater, ER_Greater},
184   };
185   for (auto TC : SpaceshipTestCases)
186   {
187     std::strong_ordering Res = (TC.Value <=> 0);
188     switch (TC.Expect) {
189     case ER_Equiv:
190       assert(Res == 0);
191       assert(0 == Res);
192       break;
193     case ER_Less:
194       assert(Res < 0);
195       break;
196     case ER_Greater:
197       assert(Res > 0);
198       break;
199     }
200   }
201   {
202     static_assert(std::strong_ordering::less == std::strong_ordering::less);
203     static_assert(std::strong_ordering::less != std::strong_ordering::equal);
204     static_assert(std::strong_ordering::less != std::strong_ordering::greater);
205 
206     static_assert(std::strong_ordering::equal != std::strong_ordering::less);
207     static_assert(std::strong_ordering::equal == std::strong_ordering::equal);
208     static_assert(std::strong_ordering::equal != std::strong_ordering::greater);
209 
210     static_assert(std::strong_ordering::greater != std::strong_ordering::less);
211     static_assert(std::strong_ordering::greater != std::strong_ordering::equal);
212     static_assert(std::strong_ordering::greater ==
213                   std::strong_ordering::greater);
214   }
215 #endif
216 
217   return true;
218 }
219 
220 int main(int, char**) {
221   test_static_members();
222   test_signatures();
223   static_assert(test_conversion(), "conversion test failed");
224   static_assert(test_constexpr(), "constexpr test failed");
225 
226   return 0;
227 }
228