//===----------------------------------------------------------------------===// // // 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 #include #include "test_macros.h" #include "test_workarounds.h" #if TEST_STD_VER >= 11 namespace ArchetypeBases { template 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 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 ::type = true> explicit TestBase(int x) noexcept : value(x) { ++alive; ++constructed; ++value_constructed; } template ::type = true> TestBase(int x) noexcept : value(x) { ++alive; ++constructed; ++value_constructed; } template ::type = true> explicit TestBase(int, int y) noexcept : value(y) { ++alive; ++constructed; ++value_constructed; } template ::type = true> TestBase(int, int y) noexcept : value(y) { ++alive; ++constructed; ++value_constructed; } template ::type = true> explicit TestBase(std::initializer_list& il, int = 0) noexcept : value(static_cast(il.size())) { ++alive; ++constructed; ++value_constructed; } template ::type = true> explicit TestBase(std::initializer_list& il, int = 0) noexcept : value(static_cast(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 int TestBase::alive = 0; template int TestBase::constructed = 0; template int TestBase::value_constructed = 0; template int TestBase::default_constructed = 0; template int TestBase::copy_constructed = 0; template int TestBase::move_constructed = 0; template int TestBase::assigned = 0; template int TestBase::value_assigned = 0; template int TestBase::copy_assigned = 0; template int TestBase::move_assigned = 0; template int TestBase::destroyed = 0; template struct ValueBase { template ::type = true> explicit constexpr ValueBase(int x) : value(x) {} template ::type = true> constexpr ValueBase(int x) : value(x) {} template ::type = true> explicit constexpr ValueBase(int, int y) : value(y) {} template ::type = true> constexpr ValueBase(int, int y) : value(y) {} template ::type = true> explicit constexpr ValueBase(std::initializer_list& il, int = 0) : value(static_cast(il.size())) {} template ::type = true> constexpr ValueBase(std::initializer_list& il, int = 0) : value(static_cast(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 struct TrivialValueBase { template ::type = true> explicit constexpr TrivialValueBase(int x) : value(x) {} template ::type = true> constexpr TrivialValueBase(int x) : value(x) {} template ::type = true> explicit constexpr TrivialValueBase(int, int y) : value(y) {} template ::type = true> constexpr TrivialValueBase(int, int y) : value(y) {} template ::type = true> explicit constexpr TrivialValueBase(std::initializer_list& il, int = 0) : value(static_cast(il.size())) {} template ::type = true> constexpr TrivialValueBase(std::initializer_list& il, int = 0) : value(static_cast(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 #include "archetypes.ipp" using TestType = AllCtors; // Add equality operators template constexpr bool operator==(Tp const& L, Tp const& R) noexcept { return L.value == R.value; } template 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 #include "archetypes.ipp" using TestType = AllCtors; // Add equality operators template constexpr bool operator==(Tp const& L, Tp const& R) noexcept { return L.value == R.value; } template 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 constexpr bool operator==(Tp const& L, Tp const& R) noexcept { return L.value == R.value; } template 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 #include "archetypes.ipp" using TestType = AllCtors; // Add equality operators template constexpr bool operator==(Tp const& L, Tp const& R) noexcept { return L.value == R.value; } template 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 #include "archetypes.ipp" using TestType = AllCtors; // Add equality operators template constexpr bool operator==(Tp const& L, Tp const& R) noexcept { return L.value == R.value; } template 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 #include "archetypes.ipp" using TestType = AllCtors; // Add equality operators template constexpr bool operator==(Tp const& L, Tp const& R) noexcept { return L.value == R.value; } template 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