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