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-12
11 
12 // <compare>
13 
14 // class weak_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::weak_ordering::less);
27   DoNotOptimize(&std::weak_ordering::equivalent);
28   DoNotOptimize(&std::weak_ordering::greater);
29 }
30 
31 void test_signatures() {
32   auto& Eq = std::weak_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::weak_ordering);
50   ASSERT_SAME_TYPE(decltype(0 <=> Eq), std::weak_ordering);
51 #endif
52 }
53 
54 constexpr bool test_conversion() {
55   static_assert(std::is_convertible<const std::weak_ordering&,
56       std::partial_ordering>::value, "");
57   { // value == 0
58     auto V = std::weak_ordering::equivalent;
59     std::partial_ordering WV = V;
60     assert(WV == 0);
61   }
62   { // value < 0
63     auto V = std::weak_ordering::less;
64     std::partial_ordering WV = V;
65     assert(WV < 0);
66   }
67   { // value > 0
68     auto V = std::weak_ordering::greater;
69     std::partial_ordering WV = V;
70     assert(WV > 0);
71   }
72   return true;
73 }
74 
75 constexpr void test_equality() {
76 #ifndef TEST_HAS_NO_SPACESHIP_OPERATOR
77   auto& WeakEq = std::weak_ordering::equivalent;
78   auto& PartialEq = std::partial_ordering::equivalent;
79   assert(WeakEq == PartialEq);
80 
81   auto& StrongEq = std::strong_ordering::equal;
82   assert(WeakEq == StrongEq);
83 #endif
84 }
85 
86 constexpr bool test_constexpr() {
87   auto& Eq = std::weak_ordering::equivalent;
88   auto& Less = std::weak_ordering::less;
89   auto& Greater = std::weak_ordering::greater;
90   struct {
91     std::weak_ordering Value;
92     bool ExpectEq;
93     bool ExpectNeq;
94     bool ExpectLess;
95     bool ExpectGreater;
96   } TestCases[] = {
97       {Eq, true, false, false, false},
98       {Less, false, true, true, false},
99       {Greater, false, true, false, true},
100   };
101   for (auto TC : TestCases) {
102     auto V = TC.Value;
103     assert((V == 0) == TC.ExpectEq);
104     assert((0 == V) == TC.ExpectEq);
105     assert((V != 0) == TC.ExpectNeq);
106     assert((0 != V) == TC.ExpectNeq);
107 
108     assert((V < 0) == TC.ExpectLess);
109     assert((V > 0) == TC.ExpectGreater);
110     assert((V <= 0) == (TC.ExpectLess || TC.ExpectEq));
111     assert((V >= 0) == (TC.ExpectGreater || TC.ExpectEq));
112 
113     assert((0 < V) == TC.ExpectGreater);
114     assert((0 > V) == TC.ExpectLess);
115     assert((0 <= V) == (TC.ExpectGreater || TC.ExpectEq));
116     assert((0 >= V) == (TC.ExpectLess || TC.ExpectEq));
117   }
118 #ifndef TEST_HAS_NO_SPACESHIP_OPERATOR
119   {
120     std::weak_ordering res = (Eq <=> 0);
121     ((void)res);
122     res = (0 <=> Eq);
123     ((void)res);
124   }
125   enum ExpectRes {
126     ER_Greater,
127     ER_Less,
128     ER_Equiv
129   };
130   struct {
131     std::weak_ordering Value;
132     ExpectRes Expect;
133   } SpaceshipTestCases[] = {
134       {std::weak_ordering::equivalent, ER_Equiv},
135       {std::weak_ordering::less, ER_Less},
136       {std::weak_ordering::greater, ER_Greater},
137   };
138   for (auto TC : SpaceshipTestCases)
139   {
140     std::weak_ordering Res = (TC.Value <=> 0);
141     switch (TC.Expect) {
142     case ER_Equiv:
143       assert(Res == 0);
144       assert(0 == Res);
145       break;
146     case ER_Less:
147       assert(Res < 0);
148       break;
149     case ER_Greater:
150       assert(Res > 0);
151       break;
152     }
153   }
154 
155   {
156     static_assert(std::weak_ordering::less == std::weak_ordering::less);
157     static_assert(std::weak_ordering::less != std::weak_ordering::equivalent);
158     static_assert(std::weak_ordering::less != std::weak_ordering::greater);
159 
160     static_assert(std::weak_ordering::equivalent != std::weak_ordering::less);
161     static_assert(std::weak_ordering::equivalent ==
162                   std::weak_ordering::equivalent);
163     static_assert(std::weak_ordering::equivalent !=
164                   std::weak_ordering::greater);
165 
166     static_assert(std::weak_ordering::greater != std::weak_ordering::less);
167     static_assert(std::weak_ordering::greater !=
168                   std::weak_ordering::equivalent);
169     static_assert(std::weak_ordering::greater == std::weak_ordering::greater);
170   }
171 
172   test_equality();
173 #endif
174 
175   return true;
176 }
177 
178 int main(int, char**) {
179   test_static_members();
180   test_signatures();
181   test_equality();
182   static_assert(test_conversion(), "conversion test failed");
183   static_assert(test_constexpr(), "constexpr test failed");
184 
185   return 0;
186 }
187