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 #ifndef TEST_SUPPORT_ARCHETYPES_H
10 #define TEST_SUPPORT_ARCHETYPES_H
11 
12 #include <type_traits>
13 #include <cassert>
14 
15 #include "test_macros.h"
16 #include "test_workarounds.h"
17 
18 #if TEST_STD_VER >= 11
19 
20 namespace ArchetypeBases {
21 
22 template <bool, class T>
23 struct DepType : T {};
24 
25 struct NullBase {
26 #ifndef TEST_WORKAROUND_C1XX_BROKEN_ZA_CTOR_CHECK
27 protected:
28 #endif // !TEST_WORKAROUND_C1XX_BROKEN_ZA_CTOR_CHECK
29   NullBase() = default;
30   NullBase(NullBase const&) = default;
31   NullBase& operator=(NullBase const&) = default;
32   NullBase(NullBase &&) = default;
33   NullBase& operator=(NullBase &&) = default;
34 };
35 
36 template <class Derived, bool Explicit = false>
37 struct TestBase {
38     static int alive;
39     static int constructed;
40     static int value_constructed;
41     static int default_constructed;
42     static int copy_constructed;
43     static int move_constructed;
44     static int assigned;
45     static int value_assigned;
46     static int copy_assigned;
47     static int move_assigned;
48     static int destroyed;
49 
resetTestBase50     static void reset() {
51         assert(alive == 0);
52         alive = 0;
53         reset_constructors();
54     }
55 
reset_constructorsTestBase56     static void reset_constructors() {
57       constructed = value_constructed = default_constructed =
58         copy_constructed = move_constructed = 0;
59       assigned = value_assigned = copy_assigned = move_assigned = destroyed = 0;
60     }
61 
TestBaseTestBase62     TestBase() noexcept : value(0) {
63         ++alive; ++constructed; ++default_constructed;
64     }
65     template <bool Dummy = true, typename std::enable_if<Dummy && Explicit, bool>::type = true>
TestBaseTestBase66     explicit TestBase(int x) noexcept : value(x) {
67         ++alive; ++constructed; ++value_constructed;
68     }
69     template <bool Dummy = true, typename std::enable_if<Dummy && !Explicit, bool>::type = true>
TestBaseTestBase70     TestBase(int x) noexcept : value(x) {
71         ++alive; ++constructed; ++value_constructed;
72     }
73     template <bool Dummy = true, typename std::enable_if<Dummy && Explicit, bool>::type = true>
TestBaseTestBase74     explicit TestBase(int, int y) noexcept : value(y) {
75         ++alive; ++constructed; ++value_constructed;
76     }
77     template <bool Dummy = true, typename std::enable_if<Dummy && !Explicit, bool>::type = true>
TestBaseTestBase78     TestBase(int, int y) noexcept : value(y) {
79         ++alive; ++constructed; ++value_constructed;
80     }
81     template <bool Dummy = true, typename std::enable_if<Dummy && Explicit, bool>::type = true>
82     explicit TestBase(std::initializer_list<int>& il, int = 0) noexcept
83       : value(static_cast<int>(il.size())) {
84         ++alive; ++constructed; ++value_constructed;
85     }
86     template <bool Dummy = true, typename std::enable_if<Dummy && !Explicit, bool>::type = true>
87     explicit TestBase(std::initializer_list<int>& il, int = 0) noexcept : value(static_cast<int>(il.size())) {
88         ++alive; ++constructed; ++value_constructed;
89     }
90     TestBase& operator=(int xvalue) noexcept {
91       value = xvalue;
92       ++assigned; ++value_assigned;
93       return *this;
94     }
95 #ifndef TEST_WORKAROUND_C1XX_BROKEN_ZA_CTOR_CHECK
96 protected:
97 #endif // !TEST_WORKAROUND_C1XX_BROKEN_ZA_CTOR_CHECK
~TestBaseTestBase98     ~TestBase() {
99       assert(value != -999); assert(alive > 0);
100       --alive; ++destroyed; value = -999;
101     }
TestBaseTestBase102     explicit TestBase(TestBase const& o) noexcept : value(o.value) {
103         assert(o.value != -1); assert(o.value != -999);
104         ++alive; ++constructed; ++copy_constructed;
105     }
TestBaseTestBase106     explicit TestBase(TestBase && o) noexcept : value(o.value) {
107         assert(o.value != -1); assert(o.value != -999);
108         ++alive; ++constructed; ++move_constructed;
109         o.value = -1;
110     }
111     TestBase& operator=(TestBase const& o) noexcept {
112       assert(o.value != -1); assert(o.value != -999);
113       ++assigned; ++copy_assigned;
114       value = o.value;
115       return *this;
116     }
117     TestBase& operator=(TestBase&& o) noexcept {
118         assert(o.value != -1); assert(o.value != -999);
119         ++assigned; ++move_assigned;
120         value = o.value;
121         o.value = -1;
122         return *this;
123     }
124 public:
125     int value;
126 };
127 
128 template <class D, bool E> int TestBase<D, E>::alive = 0;
129 template <class D, bool E> int TestBase<D, E>::constructed = 0;
130 template <class D, bool E> int TestBase<D, E>::value_constructed = 0;
131 template <class D, bool E> int TestBase<D, E>::default_constructed = 0;
132 template <class D, bool E> int TestBase<D, E>::copy_constructed = 0;
133 template <class D, bool E> int TestBase<D, E>::move_constructed = 0;
134 template <class D, bool E> int TestBase<D, E>::assigned = 0;
135 template <class D, bool E> int TestBase<D, E>::value_assigned = 0;
136 template <class D, bool E> int TestBase<D, E>::copy_assigned = 0;
137 template <class D, bool E> int TestBase<D, E>::move_assigned = 0;
138 template <class D, bool E> int TestBase<D, E>::destroyed = 0;
139 
140 template <bool Explicit = false>
141 struct ValueBase {
142     template <bool Dummy = true, typename std::enable_if<Dummy && Explicit, bool>::type = true>
ValueBaseValueBase143     explicit constexpr ValueBase(int x) : value(x) {}
144     template <bool Dummy = true, typename std::enable_if<Dummy && !Explicit, bool>::type = true>
ValueBaseValueBase145     constexpr ValueBase(int x) : value(x) {}
146     template <bool Dummy = true, typename std::enable_if<Dummy && Explicit, bool>::type = true>
ValueBaseValueBase147     explicit constexpr ValueBase(int, int y) : value(y) {}
148     template <bool Dummy = true, typename std::enable_if<Dummy && !Explicit, bool>::type = true>
ValueBaseValueBase149     constexpr ValueBase(int, int y) : value(y) {}
150     template <bool Dummy = true, typename std::enable_if<Dummy && Explicit, bool>::type = true>
151     explicit constexpr ValueBase(std::initializer_list<int>& il, int = 0) : value(static_cast<int>(il.size())) {}
152     template <bool Dummy = true, typename std::enable_if<Dummy && !Explicit, bool>::type = true>
153     constexpr ValueBase(std::initializer_list<int>& il, int = 0) : value(static_cast<int>(il.size())) {}
154     TEST_CONSTEXPR_CXX14 ValueBase& operator=(int xvalue) noexcept {
155         value = xvalue;
156         return *this;
157     }
158     //~ValueBase() { assert(value != -999); value = -999; }
159     int value;
160 #ifndef TEST_WORKAROUND_C1XX_BROKEN_ZA_CTOR_CHECK
161 protected:
162 #endif // !TEST_WORKAROUND_C1XX_BROKEN_ZA_CTOR_CHECK
check_valueValueBase163     constexpr static int check_value(int const& val) {
164 #if TEST_STD_VER < 14
165       return val == -1 || val == 999 ? (TEST_THROW(42), 0) : val;
166 #else
167       assert(val != -1); assert(val != 999);
168       return val;
169 #endif
170     }
171     constexpr static int check_value(int& val, int val_cp = 0) {
172 #if TEST_STD_VER < 14
173       return val_cp = val, val = -1, (val_cp == -1 || val_cp == 999 ? (TEST_THROW(42), 0) : val_cp);
174 #else
175       assert(val != -1); assert(val != 999);
176       val_cp = val;
177       val = -1;
178       return val_cp;
179 #endif
180     }
ValueBaseValueBase181     constexpr ValueBase() noexcept : value(0) {}
ValueBaseValueBase182     constexpr ValueBase(ValueBase const& o) noexcept : value(check_value(o.value)) {
183     }
ValueBaseValueBase184     constexpr ValueBase(ValueBase && o) noexcept : value(check_value(o.value)) {
185     }
186     TEST_CONSTEXPR_CXX14 ValueBase& operator=(ValueBase const& o) noexcept {
187         assert(o.value != -1); assert(o.value != -999);
188         value = o.value;
189         return *this;
190     }
191     TEST_CONSTEXPR_CXX14 ValueBase& operator=(ValueBase&& o) noexcept {
192         assert(o.value != -1); assert(o.value != -999);
193         value = o.value;
194         o.value = -1;
195         return *this;
196     }
197 };
198 
199 
200 template <bool Explicit = false>
201 struct TrivialValueBase {
202     template <bool Dummy = true, typename std::enable_if<Dummy && Explicit, bool>::type = true>
TrivialValueBaseTrivialValueBase203     explicit constexpr TrivialValueBase(int x) : value(x) {}
204     template <bool Dummy = true, typename std::enable_if<Dummy && !Explicit, bool>::type = true>
TrivialValueBaseTrivialValueBase205     constexpr TrivialValueBase(int x) : value(x) {}
206     template <bool Dummy = true, typename std::enable_if<Dummy && Explicit, bool>::type = true>
TrivialValueBaseTrivialValueBase207     explicit constexpr TrivialValueBase(int, int y) : value(y) {}
208     template <bool Dummy = true, typename std::enable_if<Dummy && !Explicit, bool>::type = true>
TrivialValueBaseTrivialValueBase209     constexpr TrivialValueBase(int, int y) : value(y) {}
210     template <bool Dummy = true, typename std::enable_if<Dummy && Explicit, bool>::type = true>
211     explicit constexpr TrivialValueBase(std::initializer_list<int>& il, int = 0) : value(static_cast<int>(il.size())) {}
212     template <bool Dummy = true, typename std::enable_if<Dummy && !Explicit, bool>::type = true>
213     constexpr TrivialValueBase(std::initializer_list<int>& il, int = 0) : value(static_cast<int>(il.size())) {}
214     int value;
215 #ifndef TEST_WORKAROUND_C1XX_BROKEN_ZA_CTOR_CHECK
216 protected:
217 #endif // !TEST_WORKAROUND_C1XX_BROKEN_ZA_CTOR_CHECK
TrivialValueBaseTrivialValueBase218     constexpr TrivialValueBase() noexcept : value(0) {}
219 };
220 
221 }
222 
223 //============================================================================//
224 // Trivial Implicit Test Types
225 namespace ImplicitTypes {
226 #include "archetypes.ipp"
227 }
228 
229 //============================================================================//
230 // Trivial Explicit Test Types
231 namespace ExplicitTypes {
232 #define DEFINE_EXPLICIT explicit
233 #include "archetypes.ipp"
234 }
235 
236 //============================================================================//
237 //
238 namespace NonConstexprTypes {
239 #define DEFINE_CONSTEXPR
240 #include "archetypes.ipp"
241 }
242 
243 //============================================================================//
244 // Non-literal implicit test types
245 namespace NonLiteralTypes {
246 #define DEFINE_ASSIGN_CONSTEXPR
247 #define DEFINE_DTOR(Name) ~Name() {}
248 #include "archetypes.ipp"
249 }
250 
251 //============================================================================//
252 // Non-throwing implicit test types
253 namespace NonThrowingTypes {
254 #define DEFINE_NOEXCEPT noexcept
255 #include "archetypes.ipp"
256 }
257 
258 //============================================================================//
259 // Non-Trivially Copyable Implicit Test Types
260 namespace NonTrivialTypes {
261 #define DEFINE_CTOR {}
262 #define DEFINE_ASSIGN { return *this; }
263 #include "archetypes.ipp"
264 }
265 
266 //============================================================================//
267 // Implicit counting types
268 namespace TestTypes {
269 #define DEFINE_CONSTEXPR
270 #define DEFINE_BASE(Name) ::ArchetypeBases::TestBase<Name>
271 #include "archetypes.ipp"
272 
273 using TestType = AllCtors;
274 
275 // Add equality operators
276 template <class Tp>
277 constexpr bool operator==(Tp const& L, Tp const& R) noexcept {
278   return L.value == R.value;
279 }
280 
281 template <class Tp>
282 constexpr bool operator!=(Tp const& L, Tp const& R) noexcept {
283   return L.value != R.value;
284 }
285 
286 }
287 
288 //============================================================================//
289 // Implicit counting types
290 namespace ExplicitTestTypes {
291 #define DEFINE_CONSTEXPR
292 #define DEFINE_EXPLICIT explicit
293 #define DEFINE_BASE(Name) ::ArchetypeBases::TestBase<Name, true>
294 #include "archetypes.ipp"
295 
296 using TestType = AllCtors;
297 
298 // Add equality operators
299 template <class Tp>
300 constexpr bool operator==(Tp const& L, Tp const& R) noexcept {
301   return L.value == R.value;
302 }
303 
304 template <class Tp>
305 constexpr bool operator!=(Tp const& L, Tp const& R) noexcept {
306   return L.value != R.value;
307 }
308 
309 }
310 
311 //============================================================================//
312 // Implicit value types
313 namespace ConstexprTestTypes {
314 #define DEFINE_BASE(Name) ::ArchetypeBases::ValueBase<>
315 #include "archetypes.ipp"
316 
317 using TestType = AllCtors;
318 
319 // Add equality operators
320 template <class Tp>
321 constexpr bool operator==(Tp const& L, Tp const& R) noexcept {
322   return L.value == R.value;
323 }
324 
325 template <class Tp>
326 constexpr bool operator!=(Tp const& L, Tp const& R) noexcept {
327   return L.value != R.value;
328 }
329 
330 } // end namespace ConstexprTestTypes
331 
332 
333 //============================================================================//
334 //
335 namespace ExplicitConstexprTestTypes {
336 #define DEFINE_EXPLICIT explicit
337 #define DEFINE_BASE(Name) ::ArchetypeBases::ValueBase<true>
338 #include "archetypes.ipp"
339 
340 using TestType = AllCtors;
341 
342 // Add equality operators
343 template <class Tp>
344 constexpr bool operator==(Tp const& L, Tp const& R) noexcept {
345   return L.value == R.value;
346 }
347 
348 template <class Tp>
349 constexpr bool operator!=(Tp const& L, Tp const& R) noexcept {
350   return L.value != R.value;
351 }
352 
353 } // end namespace ExplicitConstexprTestTypes
354 
355 
356 //============================================================================//
357 //
358 namespace TrivialTestTypes {
359 #define DEFINE_BASE(Name) ::ArchetypeBases::TrivialValueBase<false>
360 #include "archetypes.ipp"
361 
362 using TestType = AllCtors;
363 
364 // Add equality operators
365 template <class Tp>
366 constexpr bool operator==(Tp const& L, Tp const& R) noexcept {
367   return L.value == R.value;
368 }
369 
370 template <class Tp>
371 constexpr bool operator!=(Tp const& L, Tp const& R) noexcept {
372   return L.value != R.value;
373 }
374 
375 } // end namespace TrivialTestTypes
376 
377 //============================================================================//
378 //
379 namespace ExplicitTrivialTestTypes {
380 #define DEFINE_EXPLICIT explicit
381 #define DEFINE_BASE(Name) ::ArchetypeBases::TrivialValueBase<true>
382 #include "archetypes.ipp"
383 
384 using TestType = AllCtors;
385 
386 // Add equality operators
387 template <class Tp>
388 constexpr bool operator==(Tp const& L, Tp const& R) noexcept {
389   return L.value == R.value;
390 }
391 
392 template <class Tp>
393 constexpr bool operator!=(Tp const& L, Tp const& R) noexcept {
394   return L.value != R.value;
395 }
396 
397 } // end namespace ExplicitTrivialTestTypes
398 
399 #endif // TEST_STD_VER >= 11
400 
401 #endif // TEST_SUPPORT_ARCHETYPES_H
402