xref: /llvm-project/libc/test/src/__support/CPP/type_traits_test.cpp (revision f75c84674cd8ea3b45b6c711d627144efcf582f5)
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