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