1 //===-- Unittests for type_traits -----------------------------------------===// 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 #include "src/__support/CPP/type_traits.h" 10 #include "src/__support/macros/config.h" 11 #include "test/UnitTest/Test.h" 12 13 // TODO: Split this file if it becomes too big. 14 15 namespace LIBC_NAMESPACE_DECL { 16 namespace cpp { 17 18 class Class {}; 19 union Union {}; 20 struct Struct {}; 21 enum Enum {}; 22 enum class EnumClass {}; 23 24 using UnqualObjectTypes = testing::TypeList<int, float, Class, Union, Struct>; 25 26 TYPED_TEST(LlvmLibcTypeTraitsTest, add_lvalue_reference, UnqualObjectTypes) { 27 // non-ref cv, adds ref 28 EXPECT_TRUE((is_same_v<add_lvalue_reference_t<T>, T &>)); 29 EXPECT_TRUE((is_same_v<add_lvalue_reference_t<const T>, const T &>)); 30 EXPECT_TRUE((is_same_v<add_lvalue_reference_t<volatile T>, volatile T &>)); 31 EXPECT_TRUE(( 32 is_same_v<add_lvalue_reference_t<const volatile T>, const volatile T &>)); 33 34 // pointer cv, adds ref 35 EXPECT_TRUE((is_same_v<add_lvalue_reference_t<T *>, T *&>)); 36 EXPECT_TRUE((is_same_v<add_lvalue_reference_t<const T *>, const T *&>)); 37 EXPECT_TRUE((is_same_v<add_lvalue_reference_t<volatile T *>, volatile T *&>)); 38 EXPECT_TRUE((is_same_v<add_lvalue_reference_t<const volatile T *>, 39 const volatile T *&>)); 40 41 // ref cv, returns same type 42 EXPECT_TRUE((is_same_v<add_lvalue_reference_t<T &>, T &>)); 43 EXPECT_TRUE((is_same_v<add_lvalue_reference_t<const T &>, const T &>)); 44 EXPECT_TRUE((is_same_v<add_lvalue_reference_t<volatile T &>, volatile T &>)); 45 EXPECT_TRUE((is_same_v<add_lvalue_reference_t<const volatile T &>, 46 const volatile T &>)); 47 } 48 49 TEST(LlvmLibcTypeTraitsTest, add_lvalue_reference_void) { 50 // void cannot be referenced 51 EXPECT_TRUE((is_same_v<add_lvalue_reference_t<void>, void>)); 52 EXPECT_TRUE((is_same_v<add_lvalue_reference_t<const void>, const void>)); 53 EXPECT_TRUE( 54 (is_same_v<add_lvalue_reference_t<volatile void>, volatile void>)); 55 EXPECT_TRUE((is_same_v<add_lvalue_reference_t<const volatile void>, 56 const volatile void>)); 57 } 58 59 TYPED_TEST(LlvmLibcTypeTraitsTest, add_pointer, UnqualObjectTypes) { 60 // object types -> pointer type 61 EXPECT_TRUE((is_same_v<add_pointer_t<T>, T *>)); 62 EXPECT_TRUE((is_same_v<add_pointer_t<const T>, const T *>)); 63 EXPECT_TRUE((is_same_v<add_pointer_t<volatile T>, volatile T *>)); 64 EXPECT_TRUE((is_same_v<add_pointer_t<const volatile T>, const volatile T *>)); 65 66 // pointer types -> pointer type 67 EXPECT_TRUE((is_same_v<add_pointer_t<T *>, T **>)); 68 EXPECT_TRUE((is_same_v<add_pointer_t<const T *>, const T **>)); 69 EXPECT_TRUE((is_same_v<add_pointer_t<volatile T *>, volatile T **>)); 70 EXPECT_TRUE( 71 (is_same_v<add_pointer_t<const volatile T *>, const volatile T **>)); 72 73 // reference type -> pointer type 74 EXPECT_TRUE((is_same_v<add_pointer_t<T &>, T *>)); 75 EXPECT_TRUE((is_same_v<add_pointer_t<const T &>, const T *>)); 76 EXPECT_TRUE((is_same_v<add_pointer_t<volatile T &>, volatile T *>)); 77 EXPECT_TRUE( 78 (is_same_v<add_pointer_t<const volatile T &>, const volatile T *>)); 79 } 80 81 TEST(LlvmLibcTypeTraitsTest, add_pointer_void) { 82 // void -> pointer type 83 EXPECT_TRUE((is_same_v<add_pointer_t<void>, void *>)); 84 EXPECT_TRUE((is_same_v<add_pointer_t<const void>, const void *>)); 85 EXPECT_TRUE((is_same_v<add_pointer_t<volatile void>, volatile void *>)); 86 EXPECT_TRUE( 87 (is_same_v<add_pointer_t<const volatile void>, const volatile void *>)); 88 } 89 90 TYPED_TEST(LlvmLibcTypeTraitsTest, add_rvalue_reference, UnqualObjectTypes) { 91 92 // non-ref cv, adds ref 93 EXPECT_TRUE((is_same_v<add_rvalue_reference_t<T>, T &&>)); 94 EXPECT_TRUE((is_same_v<add_rvalue_reference_t<const T>, const T &&>)); 95 EXPECT_TRUE((is_same_v<add_rvalue_reference_t<volatile T>, volatile T &&>)); 96 EXPECT_TRUE((is_same_v<add_rvalue_reference_t<const volatile T>, 97 const volatile T &&>)); 98 99 // ref cv, returns same type 100 EXPECT_TRUE((is_same_v<add_rvalue_reference_t<T &>, T &>)); 101 EXPECT_TRUE((is_same_v<add_rvalue_reference_t<const T &>, const T &>)); 102 EXPECT_TRUE((is_same_v<add_rvalue_reference_t<volatile T &>, volatile T &>)); 103 EXPECT_TRUE((is_same_v<add_rvalue_reference_t<const volatile T &>, 104 const volatile T &>)); 105 } 106 107 TEST(LlvmLibcTypeTraitsTest, add_rvalue_reference_void) { 108 // void cannot be referenced 109 EXPECT_TRUE((is_same_v<add_rvalue_reference_t<void>, void>)); 110 EXPECT_TRUE((is_same_v<add_rvalue_reference_t<const void>, const void>)); 111 EXPECT_TRUE( 112 (is_same_v<add_rvalue_reference_t<volatile void>, volatile void>)); 113 EXPECT_TRUE((is_same_v<add_rvalue_reference_t<const volatile void>, 114 const volatile void>)); 115 } 116 117 TEST(LlvmLibcTypeTraitsTest, aligned_storage) { 118 struct S { 119 int a, b; 120 }; 121 aligned_storage_t<sizeof(S), alignof(S)> buf; 122 EXPECT_EQ(alignof(decltype(buf)), alignof(S)); 123 EXPECT_EQ(sizeof(buf), sizeof(S)); 124 } 125 126 TEST(LlvmLibcTypeTraitsTest, bool_constant) { 127 EXPECT_TRUE((bool_constant<true>::value)); 128 EXPECT_FALSE((bool_constant<false>::value)); 129 } 130 131 TEST(LlvmLibcTypeTraitsTest, conditional_t) { 132 EXPECT_TRUE((is_same_v<conditional_t<true, int, float>, int>)); 133 EXPECT_TRUE((is_same_v<conditional_t<false, int, float>, float>)); 134 } 135 136 TEST(LlvmLibcTypeTraitsTest, decay) { 137 EXPECT_TRUE((is_same_v<decay_t<int>, int>)); 138 139 // array decay 140 EXPECT_TRUE((is_same_v<decay_t<int[2]>, int *>)); 141 EXPECT_TRUE((is_same_v<decay_t<int[2]>, int *>)); 142 EXPECT_TRUE((is_same_v<decay_t<int[2][4]>, int(*)[4]>)); 143 144 // cv ref decay 145 EXPECT_TRUE((is_same_v<decay_t<int &>, int>)); 146 EXPECT_TRUE((is_same_v<decay_t<const int &>, int>)); 147 EXPECT_TRUE((is_same_v<decay_t<volatile int &>, int>)); 148 EXPECT_TRUE((is_same_v<decay_t<const volatile int &>, int>)); 149 } 150 151 // TODO enable_if 152 153 TEST(LlvmLibcTypeTraitsTest, false_type) { EXPECT_FALSE((false_type::value)); } 154 155 TEST(LlvmLibcTypeTraitsTest, integral_constant) { 156 EXPECT_EQ((integral_constant<int, 4>::value), 4); 157 } 158 159 namespace invoke_detail { 160 161 enum State { INIT = 0, A_APPLY_CALLED, B_APPLY_CALLED }; 162 163 struct A { 164 State state = INIT; 165 virtual ~A() {} 166 virtual void apply() { state = A_APPLY_CALLED; } 167 }; 168 169 struct B : public A { 170 virtual ~B() {} 171 virtual void apply() override { state = B_APPLY_CALLED; } 172 }; 173 174 void free_function() {} 175 int free_function_return_5() { return 5; } 176 int free_function_passtrough(int value) { return value; } 177 178 struct Delegate { 179 int (*ptr)(int) = &free_function_passtrough; 180 }; 181 182 template <int tag> struct Tag { 183 static constexpr int value = tag; 184 }; 185 186 struct Functor { 187 auto operator()() & { return Tag<0>(); } 188 auto operator()() const & { return Tag<1>(); } 189 auto operator()() && { return Tag<2>(); } 190 auto operator()() const && { return Tag<3>(); } 191 192 const Tag<0> &operator()(const Tag<0> &a) { return a; } 193 const Tag<0> &&operator()(const Tag<0> &&a) { return cpp::move(a); } 194 Tag<1> operator()(Tag<1> a) { return a; } 195 }; 196 197 } // namespace invoke_detail 198 199 TEST(LlvmLibcTypeTraitsTest, invoke) { 200 using namespace invoke_detail; 201 { // member function call 202 A a; 203 EXPECT_EQ(a.state, INIT); 204 invoke(&A::apply, a); 205 EXPECT_EQ(a.state, A_APPLY_CALLED); 206 } 207 { // overriden member function call 208 B b; 209 EXPECT_EQ(b.state, INIT); 210 invoke(&A::apply, b); 211 EXPECT_EQ(b.state, B_APPLY_CALLED); 212 } 213 { // free function 214 invoke(&free_function); 215 EXPECT_EQ(invoke(&free_function_return_5), 5); 216 EXPECT_EQ(invoke(&free_function_passtrough, 1), 1); 217 } 218 { // pointer member function call 219 Delegate d; 220 EXPECT_EQ(invoke(&Delegate::ptr, d, 2), 2); 221 } 222 { // Functor with several ref qualifier 223 Functor f; 224 const Functor cf; 225 EXPECT_EQ(invoke(f).value, 0); 226 EXPECT_EQ(invoke(cf).value, 1); 227 EXPECT_EQ(invoke(move(f)).value, 2); 228 EXPECT_EQ(invoke(move(cf)).value, 3); 229 } 230 { // lambda 231 EXPECT_EQ(invoke([]() -> int { return 2; }), 2); 232 EXPECT_EQ(invoke([](int value) -> int { return value; }, 1), 1); 233 234 const auto lambda = [](int) { return 0; }; 235 EXPECT_EQ(invoke(lambda, 1), 0); 236 } 237 } 238 239 TEST(LlvmLibcTypeTraitsTest, invoke_result) { 240 using namespace invoke_detail; 241 EXPECT_TRUE((is_same_v<invoke_result_t<void (A::*)(), A>, void>)); 242 EXPECT_TRUE((is_same_v<invoke_result_t<void (A::*)(), B>, void>)); 243 EXPECT_TRUE((is_same_v<invoke_result_t<void (*)()>, void>)); 244 EXPECT_TRUE((is_same_v<invoke_result_t<int (*)()>, int>)); 245 EXPECT_TRUE((is_same_v<invoke_result_t<int (*)(int), int>, int>)); 246 EXPECT_TRUE(( 247 is_same_v<invoke_result_t<int (*Delegate::*)(int), Delegate, int>, int>)); 248 // Functor with several ref qualifiers 249 EXPECT_TRUE((is_same_v<invoke_result_t<Functor &>, Tag<0>>)); 250 EXPECT_TRUE((is_same_v<invoke_result_t<Functor const &>, Tag<1>>)); 251 EXPECT_TRUE((is_same_v<invoke_result_t<Functor &&>, Tag<2>>)); 252 EXPECT_TRUE((is_same_v<invoke_result_t<Functor const &&>, Tag<3>>)); 253 // Functor with several arg qualifiers 254 EXPECT_TRUE( 255 (is_same_v<invoke_result_t<Functor &&, Tag<0> &>, const Tag<0> &>)); 256 EXPECT_TRUE((is_same_v<invoke_result_t<Functor, Tag<0>>, const Tag<0> &&>)); 257 EXPECT_TRUE((is_same_v<invoke_result_t<Functor, Tag<1>>, Tag<1>>)); 258 { 259 auto lambda = []() {}; 260 EXPECT_TRUE((is_same_v<invoke_result_t<decltype(lambda)>, void>)); 261 } 262 { 263 auto lambda = []() { return 0; }; 264 EXPECT_TRUE((is_same_v<invoke_result_t<decltype(lambda)>, int>)); 265 } 266 { 267 auto lambda = [](int) -> double { return 0; }; 268 EXPECT_TRUE((is_same_v<invoke_result_t<decltype(lambda), int>, double>)); 269 } 270 } 271 272 using IntegralAndFloatingTypes = 273 testing::TypeList<bool, char, short, int, long, long long, unsigned char, 274 unsigned short, unsigned int, unsigned long, 275 unsigned long long, float, double, long double>; 276 277 TYPED_TEST(LlvmLibcTypeTraitsTest, is_arithmetic, IntegralAndFloatingTypes) { 278 EXPECT_TRUE((is_arithmetic_v<T>)); 279 EXPECT_TRUE((is_arithmetic_v<const T>)); 280 EXPECT_TRUE((is_arithmetic_v<volatile T>)); 281 EXPECT_TRUE((is_arithmetic_v<const volatile T>)); 282 283 EXPECT_FALSE((is_arithmetic_v<T *>)); 284 EXPECT_FALSE((is_arithmetic_v<T &>)); 285 } 286 287 TEST(LlvmLibcTypeTraitsTest, is_arithmetic_non_integral) { 288 EXPECT_FALSE((is_arithmetic_v<Union>)); 289 EXPECT_FALSE((is_arithmetic_v<Class>)); 290 EXPECT_FALSE((is_arithmetic_v<Struct>)); 291 EXPECT_FALSE((is_arithmetic_v<Enum>)); 292 } 293 294 TEST(LlvmLibcTypeTraitsTest, is_array) { 295 EXPECT_FALSE((is_array_v<int>)); 296 EXPECT_FALSE((is_array_v<float>)); 297 EXPECT_FALSE((is_array_v<Struct>)); 298 EXPECT_FALSE((is_array_v<int *>)); 299 300 EXPECT_TRUE((is_array_v<Class[]>)); 301 EXPECT_TRUE((is_array_v<Union[4]>)); 302 } 303 304 TEST(LlvmLibcTypeTraitsTest, is_base_of) { 305 struct A {}; 306 EXPECT_TRUE((is_base_of_v<A, A>)); 307 308 // Test public, protected and private inheritance. 309 struct B : public A {}; 310 EXPECT_TRUE((is_base_of_v<A, B>)); 311 EXPECT_FALSE((is_base_of_v<B, A>)); 312 313 struct C : protected A {}; 314 EXPECT_TRUE((is_base_of_v<A, C>)); 315 EXPECT_FALSE((is_base_of_v<C, A>)); 316 317 struct D : private A {}; 318 EXPECT_TRUE((is_base_of_v<A, D>)); 319 EXPECT_FALSE((is_base_of_v<D, A>)); 320 321 // Test inheritance chain. 322 struct E : private B {}; 323 EXPECT_TRUE((is_base_of_v<A, E>)); 324 } 325 326 TEST(LlvmLibcTypeTraitsTest, is_class) { 327 EXPECT_TRUE((is_class_v<Struct>)); 328 EXPECT_TRUE((is_class_v<Class>)); 329 330 // Pointer or ref do not qualify. 331 EXPECT_FALSE((is_class_v<Class *>)); 332 EXPECT_FALSE((is_class_v<Class &>)); 333 334 // Neither other types. 335 EXPECT_FALSE((is_class_v<Union>)); 336 EXPECT_FALSE((is_class_v<int>)); 337 EXPECT_FALSE((is_class_v<EnumClass>)); 338 } 339 340 TYPED_TEST(LlvmLibcTypeTraitsTest, is_const, UnqualObjectTypes) { 341 EXPECT_FALSE((is_const_v<T>)); 342 EXPECT_TRUE((is_const_v<const T>)); 343 344 using Aliased = const T; 345 EXPECT_TRUE((is_const_v<Aliased>)); 346 } 347 348 // TODO is_convertible 349 350 TYPED_TEST(LlvmLibcTypeTraitsTest, is_destructible, UnqualObjectTypes) { 351 EXPECT_TRUE((is_destructible_v<T>)); 352 } 353 TEST(LlvmLibcTypeTraitsTest, is_destructible_no_destructor) { 354 struct S { 355 ~S() = delete; 356 }; 357 EXPECT_FALSE((is_destructible_v<S>)); 358 } 359 360 TYPED_TEST(LlvmLibcTypeTraitsTest, is_enum, UnqualObjectTypes) { 361 EXPECT_FALSE((is_enum_v<T>)); 362 } 363 TEST(LlvmLibcTypeTraitsTest, is_enum_enum) { 364 EXPECT_TRUE((is_enum_v<Enum>)); 365 EXPECT_TRUE((is_enum_v<EnumClass>)); 366 } 367 368 // TODO is_floating_point 369 370 // TODO is_function 371 372 // TODO is_integral 373 374 // TODO is_lvalue_reference 375 376 // TODO is_member_pointer 377 378 // TODO is_null_pointer 379 380 TEST(LlvmLibcTypeTraitsTest, is_object) { 381 EXPECT_TRUE((is_object_v<int>)); // scalar 382 EXPECT_TRUE((is_object_v<Struct[]>)); // array 383 EXPECT_TRUE((is_object_v<Union>)); // union 384 EXPECT_TRUE((is_object_v<Class>)); // class 385 386 // pointers are still objects 387 EXPECT_TRUE((is_object_v<int *>)); // scalar 388 EXPECT_TRUE((is_object_v<Struct(*)[]>)); // array 389 EXPECT_TRUE((is_object_v<Union *>)); // union 390 EXPECT_TRUE((is_object_v<Class *>)); // class 391 392 // reference are not objects 393 EXPECT_FALSE((is_object_v<int &>)); // scalar 394 EXPECT_FALSE((is_object_v<Struct(&)[]>)); // array 395 EXPECT_FALSE((is_object_v<Union &>)); // union 396 EXPECT_FALSE((is_object_v<Class &>)); // class 397 398 // not an object 399 EXPECT_FALSE((is_object_v<void>)); 400 } 401 402 // TODO is_pointer 403 404 // TODO is_reference 405 406 // TODO is_rvalue_reference 407 408 // TODO is_same 409 410 // TODO is_scalar 411 412 // TODO is_signed 413 414 // TODO is_trivially_constructible 415 416 // TODO is_trivially_copyable 417 418 // TODO is_trivially_destructible 419 420 // TODO is_union 421 422 // TODO is_unsigned 423 424 // TODO is_void 425 426 // TODO make_signed 427 428 // TODO make_unsigned 429 430 // TODO remove_all_extents 431 432 // TODO remove_cv 433 434 // TODO remove_cvref 435 436 // TODO remove_extent 437 438 // TODO remove_reference 439 440 TEST(LlvmLibcTypeTraitsTest, true_type) { EXPECT_TRUE((true_type::value)); } 441 442 struct CompilerLeadingPadded { 443 char b; 444 int a; 445 }; 446 447 struct CompilerTrailingPadded { 448 int a; 449 char b; 450 }; 451 452 struct alignas(long long) ManuallyPadded { 453 int b; 454 char padding[sizeof(long long) - sizeof(int)]; 455 }; 456 457 TEST(LlvmLibcTypeTraitsTest, has_unique_object_representations) { 458 EXPECT_TRUE(has_unique_object_representations<int>::value); 459 EXPECT_FALSE(has_unique_object_representations_v<CompilerLeadingPadded>); 460 EXPECT_FALSE(has_unique_object_representations_v<CompilerTrailingPadded>); 461 EXPECT_TRUE(has_unique_object_representations_v<ManuallyPadded>); 462 } 463 464 // TODO type_identity 465 466 // TODO void_t 467 468 } // namespace cpp 469 } // namespace LIBC_NAMESPACE_DECL 470