| //===----------------------------------------------------------------------===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef TEST_SUPPORT_ARCHETYPES_H |
| #define TEST_SUPPORT_ARCHETYPES_H |
| |
| #include <type_traits> |
| #include <cassert> |
| |
| #include "test_macros.h" |
| #include "test_workarounds.h" |
| |
| #if TEST_STD_VER >= 11 |
| |
| namespace ArchetypeBases { |
| |
| template <bool, class T> |
| struct DepType : T {}; |
| |
| struct NullBase { |
| #ifndef TEST_WORKAROUND_C1XX_BROKEN_ZA_CTOR_CHECK |
| protected: |
| #endif // !TEST_WORKAROUND_C1XX_BROKEN_ZA_CTOR_CHECK |
| NullBase() = default; |
| NullBase(NullBase const&) = default; |
| NullBase& operator=(NullBase const&) = default; |
| NullBase(NullBase &&) = default; |
| NullBase& operator=(NullBase &&) = default; |
| }; |
| |
| template <class Derived, bool Explicit = false> |
| struct TestBase { |
| static int alive; |
| static int constructed; |
| static int value_constructed; |
| static int default_constructed; |
| static int copy_constructed; |
| static int move_constructed; |
| static int assigned; |
| static int value_assigned; |
| static int copy_assigned; |
| static int move_assigned; |
| static int destroyed; |
| |
| static void reset() { |
| assert(alive == 0); |
| alive = 0; |
| reset_constructors(); |
| } |
| |
| static void reset_constructors() { |
| constructed = value_constructed = default_constructed = |
| copy_constructed = move_constructed = 0; |
| assigned = value_assigned = copy_assigned = move_assigned = destroyed = 0; |
| } |
| |
| TestBase() noexcept : value(0) { |
| ++alive; ++constructed; ++default_constructed; |
| } |
| template <bool Dummy = true, typename std::enable_if<Dummy && Explicit, bool>::type = true> |
| explicit TestBase(int x) noexcept : value(x) { |
| ++alive; ++constructed; ++value_constructed; |
| } |
| template <bool Dummy = true, typename std::enable_if<Dummy && !Explicit, bool>::type = true> |
| TestBase(int x) noexcept : value(x) { |
| ++alive; ++constructed; ++value_constructed; |
| } |
| template <bool Dummy = true, typename std::enable_if<Dummy && Explicit, bool>::type = true> |
| explicit TestBase(int, int y) noexcept : value(y) { |
| ++alive; ++constructed; ++value_constructed; |
| } |
| template <bool Dummy = true, typename std::enable_if<Dummy && !Explicit, bool>::type = true> |
| TestBase(int, int y) noexcept : value(y) { |
| ++alive; ++constructed; ++value_constructed; |
| } |
| template <bool Dummy = true, typename std::enable_if<Dummy && Explicit, bool>::type = true> |
| explicit TestBase(std::initializer_list<int>& il, int = 0) noexcept |
| : value(static_cast<int>(il.size())) { |
| ++alive; ++constructed; ++value_constructed; |
| } |
| template <bool Dummy = true, typename std::enable_if<Dummy && !Explicit, bool>::type = true> |
| explicit TestBase(std::initializer_list<int>& il, int = 0) noexcept : value(static_cast<int>(il.size())) { |
| ++alive; ++constructed; ++value_constructed; |
| } |
| TestBase& operator=(int xvalue) noexcept { |
| value = xvalue; |
| ++assigned; ++value_assigned; |
| return *this; |
| } |
| #ifndef TEST_WORKAROUND_C1XX_BROKEN_ZA_CTOR_CHECK |
| protected: |
| #endif // !TEST_WORKAROUND_C1XX_BROKEN_ZA_CTOR_CHECK |
| ~TestBase() { |
| assert(value != -999); assert(alive > 0); |
| --alive; ++destroyed; value = -999; |
| } |
| explicit TestBase(TestBase const& o) noexcept : value(o.value) { |
| assert(o.value != -1); assert(o.value != -999); |
| ++alive; ++constructed; ++copy_constructed; |
| } |
| explicit TestBase(TestBase && o) noexcept : value(o.value) { |
| assert(o.value != -1); assert(o.value != -999); |
| ++alive; ++constructed; ++move_constructed; |
| o.value = -1; |
| } |
| TestBase& operator=(TestBase const& o) noexcept { |
| assert(o.value != -1); assert(o.value != -999); |
| ++assigned; ++copy_assigned; |
| value = o.value; |
| return *this; |
| } |
| TestBase& operator=(TestBase&& o) noexcept { |
| assert(o.value != -1); assert(o.value != -999); |
| ++assigned; ++move_assigned; |
| value = o.value; |
| o.value = -1; |
| return *this; |
| } |
| public: |
| int value; |
| }; |
| |
| template <class D, bool E> int TestBase<D, E>::alive = 0; |
| template <class D, bool E> int TestBase<D, E>::constructed = 0; |
| template <class D, bool E> int TestBase<D, E>::value_constructed = 0; |
| template <class D, bool E> int TestBase<D, E>::default_constructed = 0; |
| template <class D, bool E> int TestBase<D, E>::copy_constructed = 0; |
| template <class D, bool E> int TestBase<D, E>::move_constructed = 0; |
| template <class D, bool E> int TestBase<D, E>::assigned = 0; |
| template <class D, bool E> int TestBase<D, E>::value_assigned = 0; |
| template <class D, bool E> int TestBase<D, E>::copy_assigned = 0; |
| template <class D, bool E> int TestBase<D, E>::move_assigned = 0; |
| template <class D, bool E> int TestBase<D, E>::destroyed = 0; |
| |
| template <bool Explicit = false> |
| struct ValueBase { |
| template <bool Dummy = true, typename std::enable_if<Dummy && Explicit, bool>::type = true> |
| explicit constexpr ValueBase(int x) : value(x) {} |
| template <bool Dummy = true, typename std::enable_if<Dummy && !Explicit, bool>::type = true> |
| constexpr ValueBase(int x) : value(x) {} |
| template <bool Dummy = true, typename std::enable_if<Dummy && Explicit, bool>::type = true> |
| explicit constexpr ValueBase(int, int y) : value(y) {} |
| template <bool Dummy = true, typename std::enable_if<Dummy && !Explicit, bool>::type = true> |
| constexpr ValueBase(int, int y) : value(y) {} |
| template <bool Dummy = true, typename std::enable_if<Dummy && Explicit, bool>::type = true> |
| explicit constexpr ValueBase(std::initializer_list<int>& il, int = 0) : value(static_cast<int>(il.size())) {} |
| template <bool Dummy = true, typename std::enable_if<Dummy && !Explicit, bool>::type = true> |
| constexpr ValueBase(std::initializer_list<int>& il, int = 0) : value(static_cast<int>(il.size())) {} |
| TEST_CONSTEXPR_CXX14 ValueBase& operator=(int xvalue) noexcept { |
| value = xvalue; |
| return *this; |
| } |
| //~ValueBase() { assert(value != -999); value = -999; } |
| int value; |
| #ifndef TEST_WORKAROUND_C1XX_BROKEN_ZA_CTOR_CHECK |
| protected: |
| #endif // !TEST_WORKAROUND_C1XX_BROKEN_ZA_CTOR_CHECK |
| constexpr static int check_value(int const& val) { |
| #if TEST_STD_VER < 14 |
| return val == -1 || val == 999 ? (TEST_THROW(42), 0) : val; |
| #else |
| assert(val != -1); assert(val != 999); |
| return val; |
| #endif |
| } |
| constexpr static int check_value(int& val, int val_cp = 0) { |
| #if TEST_STD_VER < 14 |
| return val_cp = val, val = -1, (val_cp == -1 || val_cp == 999 ? (TEST_THROW(42), 0) : val_cp); |
| #else |
| assert(val != -1); assert(val != 999); |
| val_cp = val; |
| val = -1; |
| return val_cp; |
| #endif |
| } |
| constexpr ValueBase() noexcept : value(0) {} |
| constexpr ValueBase(ValueBase const& o) noexcept : value(check_value(o.value)) { |
| } |
| constexpr ValueBase(ValueBase && o) noexcept : value(check_value(o.value)) { |
| } |
| TEST_CONSTEXPR_CXX14 ValueBase& operator=(ValueBase const& o) noexcept { |
| assert(o.value != -1); assert(o.value != -999); |
| value = o.value; |
| return *this; |
| } |
| TEST_CONSTEXPR_CXX14 ValueBase& operator=(ValueBase&& o) noexcept { |
| assert(o.value != -1); assert(o.value != -999); |
| value = o.value; |
| o.value = -1; |
| return *this; |
| } |
| }; |
| |
| |
| template <bool Explicit = false> |
| struct TrivialValueBase { |
| template <bool Dummy = true, typename std::enable_if<Dummy && Explicit, bool>::type = true> |
| explicit constexpr TrivialValueBase(int x) : value(x) {} |
| template <bool Dummy = true, typename std::enable_if<Dummy && !Explicit, bool>::type = true> |
| constexpr TrivialValueBase(int x) : value(x) {} |
| template <bool Dummy = true, typename std::enable_if<Dummy && Explicit, bool>::type = true> |
| explicit constexpr TrivialValueBase(int, int y) : value(y) {} |
| template <bool Dummy = true, typename std::enable_if<Dummy && !Explicit, bool>::type = true> |
| constexpr TrivialValueBase(int, int y) : value(y) {} |
| template <bool Dummy = true, typename std::enable_if<Dummy && Explicit, bool>::type = true> |
| explicit constexpr TrivialValueBase(std::initializer_list<int>& il, int = 0) : value(static_cast<int>(il.size())) {} |
| template <bool Dummy = true, typename std::enable_if<Dummy && !Explicit, bool>::type = true> |
| constexpr TrivialValueBase(std::initializer_list<int>& il, int = 0) : value(static_cast<int>(il.size())) {} |
| int value; |
| #ifndef TEST_WORKAROUND_C1XX_BROKEN_ZA_CTOR_CHECK |
| protected: |
| #endif // !TEST_WORKAROUND_C1XX_BROKEN_ZA_CTOR_CHECK |
| constexpr TrivialValueBase() noexcept : value(0) {} |
| }; |
| |
| } |
| |
| //============================================================================// |
| // Trivial Implicit Test Types |
| namespace ImplicitTypes { |
| #include "archetypes.ipp" |
| } |
| |
| //============================================================================// |
| // Trivial Explicit Test Types |
| namespace ExplicitTypes { |
| #define DEFINE_EXPLICIT explicit |
| #include "archetypes.ipp" |
| } |
| |
| //============================================================================// |
| // |
| namespace NonConstexprTypes { |
| #define DEFINE_CONSTEXPR |
| #include "archetypes.ipp" |
| } |
| |
| //============================================================================// |
| // Non-literal implicit test types |
| namespace NonLiteralTypes { |
| #define DEFINE_ASSIGN_CONSTEXPR |
| #define DEFINE_DTOR(Name) ~Name() {} |
| #include "archetypes.ipp" |
| } |
| |
| //============================================================================// |
| // Non-throwing implicit test types |
| namespace NonThrowingTypes { |
| #define DEFINE_NOEXCEPT noexcept |
| #include "archetypes.ipp" |
| } |
| |
| //============================================================================// |
| // Non-Trivially Copyable Implicit Test Types |
| namespace NonTrivialTypes { |
| #define DEFINE_CTOR {} |
| #define DEFINE_ASSIGN { return *this; } |
| #include "archetypes.ipp" |
| } |
| |
| //============================================================================// |
| // Implicit counting types |
| namespace TestTypes { |
| #define DEFINE_CONSTEXPR |
| #define DEFINE_BASE(Name) ::ArchetypeBases::TestBase<Name> |
| #include "archetypes.ipp" |
| |
| using TestType = AllCtors; |
| |
| // Add equality operators |
| template <class Tp> |
| constexpr bool operator==(Tp const& L, Tp const& R) noexcept { |
| return L.value == R.value; |
| } |
| |
| template <class Tp> |
| constexpr bool operator!=(Tp const& L, Tp const& R) noexcept { |
| return L.value != R.value; |
| } |
| |
| } |
| |
| //============================================================================// |
| // Implicit counting types |
| namespace ExplicitTestTypes { |
| #define DEFINE_CONSTEXPR |
| #define DEFINE_EXPLICIT explicit |
| #define DEFINE_BASE(Name) ::ArchetypeBases::TestBase<Name, true> |
| #include "archetypes.ipp" |
| |
| using TestType = AllCtors; |
| |
| // Add equality operators |
| template <class Tp> |
| constexpr bool operator==(Tp const& L, Tp const& R) noexcept { |
| return L.value == R.value; |
| } |
| |
| template <class Tp> |
| constexpr bool operator!=(Tp const& L, Tp const& R) noexcept { |
| return L.value != R.value; |
| } |
| |
| } |
| |
| //============================================================================// |
| // Implicit value types |
| namespace ConstexprTestTypes { |
| #define DEFINE_BASE(Name) ::ArchetypeBases::ValueBase<> |
| #include "archetypes.ipp" |
| |
| using TestType = AllCtors; |
| |
| // Add equality operators |
| template <class Tp> |
| constexpr bool operator==(Tp const& L, Tp const& R) noexcept { |
| return L.value == R.value; |
| } |
| |
| template <class Tp> |
| constexpr bool operator!=(Tp const& L, Tp const& R) noexcept { |
| return L.value != R.value; |
| } |
| |
| } // end namespace ConstexprTestTypes |
| |
| |
| //============================================================================// |
| // |
| namespace ExplicitConstexprTestTypes { |
| #define DEFINE_EXPLICIT explicit |
| #define DEFINE_BASE(Name) ::ArchetypeBases::ValueBase<true> |
| #include "archetypes.ipp" |
| |
| using TestType = AllCtors; |
| |
| // Add equality operators |
| template <class Tp> |
| constexpr bool operator==(Tp const& L, Tp const& R) noexcept { |
| return L.value == R.value; |
| } |
| |
| template <class Tp> |
| constexpr bool operator!=(Tp const& L, Tp const& R) noexcept { |
| return L.value != R.value; |
| } |
| |
| } // end namespace ExplicitConstexprTestTypes |
| |
| |
| //============================================================================// |
| // |
| namespace TrivialTestTypes { |
| #define DEFINE_BASE(Name) ::ArchetypeBases::TrivialValueBase<false> |
| #include "archetypes.ipp" |
| |
| using TestType = AllCtors; |
| |
| // Add equality operators |
| template <class Tp> |
| constexpr bool operator==(Tp const& L, Tp const& R) noexcept { |
| return L.value == R.value; |
| } |
| |
| template <class Tp> |
| constexpr bool operator!=(Tp const& L, Tp const& R) noexcept { |
| return L.value != R.value; |
| } |
| |
| } // end namespace TrivialTestTypes |
| |
| //============================================================================// |
| // |
| namespace ExplicitTrivialTestTypes { |
| #define DEFINE_EXPLICIT explicit |
| #define DEFINE_BASE(Name) ::ArchetypeBases::TrivialValueBase<true> |
| #include "archetypes.ipp" |
| |
| using TestType = AllCtors; |
| |
| // Add equality operators |
| template <class Tp> |
| constexpr bool operator==(Tp const& L, Tp const& R) noexcept { |
| return L.value == R.value; |
| } |
| |
| template <class Tp> |
| constexpr bool operator!=(Tp const& L, Tp const& R) noexcept { |
| return L.value != R.value; |
| } |
| |
| } // end namespace ExplicitTrivialTestTypes |
| |
| #endif // TEST_STD_VER >= 11 |
| |
| #endif // TEST_SUPPORT_ARCHETYPES_H |