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