From 138dbdfb88a694bef8fd88b14641e69e51018e31 Mon Sep 17 00:00:00 2001 From: Guillaume Chatelet Date: Mon, 11 Sep 2023 12:51:54 +0000 Subject: [PATCH 1/3] [libc] Add type_traits tests --- libc/test/src/__support/CPP/CMakeLists.txt | 10 + .../src/__support/CPP/type_traits_test.cpp | 268 ++++++++++++++++++ .../libc/test/src/__support/CPP/BUILD.bazel | 10 + 3 files changed, 288 insertions(+) create mode 100644 libc/test/src/__support/CPP/type_traits_test.cpp diff --git a/libc/test/src/__support/CPP/CMakeLists.txt b/libc/test/src/__support/CPP/CMakeLists.txt index be2bc20d78047..5772a83a65cad 100644 --- a/libc/test/src/__support/CPP/CMakeLists.txt +++ b/libc/test/src/__support/CPP/CMakeLists.txt @@ -106,3 +106,13 @@ add_libc_test( libc.src.__support.CPP.string libc.src.__support.CPP.string_view ) + +add_libc_test( + type_traits_test + SUITE + libc-cpp-utils-tests + SRCS + type_traits_test.cpp + DEPENDS + libc.src.__support.CPP.type_traits +) diff --git a/libc/test/src/__support/CPP/type_traits_test.cpp b/libc/test/src/__support/CPP/type_traits_test.cpp new file mode 100644 index 0000000000000..69b7009e636b3 --- /dev/null +++ b/libc/test/src/__support/CPP/type_traits_test.cpp @@ -0,0 +1,268 @@ +//===-- Unittests for type_traits -----------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "src/__support/CPP/type_traits.h" +#include "test/UnitTest/Test.h" + +// TODO: Split this file if it becomes too big. + +namespace __llvm_libc::cpp { + +class Class {}; +union Union {}; +struct Struct {}; + +using UnqualObjectTypes = testing::TypeList; + +TYPED_TEST(LlvmLibcTypeTraitsTest, add_lvalue_reference, UnqualObjectTypes) { + + // non-ref cv, adds ref + EXPECT_TRUE((is_same_v, T &>)); + EXPECT_TRUE((is_same_v, const T &>)); + EXPECT_TRUE((is_same_v, volatile T &>)); + EXPECT_TRUE(( + is_same_v, const volatile T &>)); + + // ref cv, returns same type + EXPECT_TRUE((is_same_v, T &>)); + EXPECT_TRUE((is_same_v, const T &>)); + EXPECT_TRUE((is_same_v, volatile T &>)); + EXPECT_TRUE((is_same_v, + const volatile T &>)); +} + +TEST(LlvmLibcTypeTraitsTest, add_lvalue_reference_void) { + // void cannot be referenced + EXPECT_TRUE((is_same_v, void>)); + EXPECT_TRUE((is_same_v, const void>)); + EXPECT_TRUE( + (is_same_v, volatile void>)); + EXPECT_TRUE((is_same_v, + const volatile void>)); +} + +TYPED_TEST(LlvmLibcTypeTraitsTest, add_pointer, UnqualObjectTypes) { + // object types -> pointer type + EXPECT_TRUE((is_same_v, T *>)); + EXPECT_TRUE((is_same_v, const T *>)); + EXPECT_TRUE((is_same_v, volatile T *>)); + EXPECT_TRUE((is_same_v, const volatile T *>)); + + // reference type -> pointer type + EXPECT_TRUE((is_same_v, T *>)); + EXPECT_TRUE((is_same_v, const T *>)); + EXPECT_TRUE((is_same_v, volatile T *>)); + EXPECT_TRUE( + (is_same_v, const volatile T *>)); +} + +TEST(LlvmLibcTypeTraitsTest, add_pointer_void) { + // void -> pointer type + EXPECT_TRUE((is_same_v, void *>)); + EXPECT_TRUE((is_same_v, const void *>)); + EXPECT_TRUE((is_same_v, volatile void *>)); + EXPECT_TRUE( + (is_same_v, const volatile void *>)); +} + +TYPED_TEST(LlvmLibcTypeTraitsTest, add_rvalue_reference, UnqualObjectTypes) { + + // non-ref cv, adds ref + EXPECT_TRUE((is_same_v, T &&>)); + EXPECT_TRUE((is_same_v, const T &&>)); + EXPECT_TRUE((is_same_v, volatile T &&>)); + EXPECT_TRUE((is_same_v, + const volatile T &&>)); + + // ref cv, returns same type + EXPECT_TRUE((is_same_v, T &>)); + EXPECT_TRUE((is_same_v, const T &>)); + EXPECT_TRUE((is_same_v, volatile T &>)); + EXPECT_TRUE((is_same_v, + const volatile T &>)); +} + +TEST(LlvmLibcTypeTraitsTest, add_rvalue_reference_void) { + // void cannot be referenced + EXPECT_TRUE((is_same_v, void>)); + EXPECT_TRUE((is_same_v, const void>)); + EXPECT_TRUE( + (is_same_v, volatile void>)); + EXPECT_TRUE((is_same_v, + const volatile void>)); +} + +TEST(LlvmLibcTypeTraitsTest, bool_constant) { + EXPECT_TRUE((bool_constant::value)); + EXPECT_FALSE((bool_constant::value)); +} + +TEST(LlvmLibcTypeTraitsTest, conditional_t) { + EXPECT_TRUE((is_same_v, int>)); + EXPECT_TRUE((is_same_v, float>)); +} + +TEST(LlvmLibcTypeTraitsTest, decay) { + EXPECT_TRUE((is_same_v, int>)); + + // array decay + EXPECT_TRUE((is_same_v, int *>)); + EXPECT_TRUE((is_same_v, int *>)); + EXPECT_TRUE((is_same_v, int(*)[4]>)); + + // cv ref decay + EXPECT_TRUE((is_same_v, int>)); + EXPECT_TRUE((is_same_v, int>)); + EXPECT_TRUE((is_same_v, int>)); + EXPECT_TRUE((is_same_v, int>)); +} + +// TODO enable_if + +TEST(LlvmLibcTypeTraitsTest, false_type) { EXPECT_FALSE((false_type::value)); } + +TEST(LlvmLibcTypeTraitsTest, integral_constant) { + EXPECT_EQ((integral_constant::value), 4); +} + +using IntegralTypes = + testing::TypeList; + +TYPED_TEST(LlvmLibcTypeTraitsTest, is_arithmetic, IntegralTypes) { + EXPECT_TRUE((is_arithmetic_v)); + EXPECT_TRUE((is_arithmetic_v)); + EXPECT_TRUE((is_arithmetic_v)); + EXPECT_TRUE((is_arithmetic_v)); + + EXPECT_FALSE((is_arithmetic_v)); + EXPECT_FALSE((is_arithmetic_v)); +} + +TEST(LlvmLibcTypeTraitsTest, is_arithmetic_non_integral) { + EXPECT_FALSE((is_arithmetic_v)); + EXPECT_FALSE((is_arithmetic_v)); + EXPECT_FALSE((is_arithmetic_v)); +} + +TEST(LlvmLibcTypeTraitsTest, is_array) { + EXPECT_FALSE((is_array_v)); + EXPECT_FALSE((is_array_v)); + EXPECT_FALSE((is_array_v)); + + EXPECT_TRUE((is_array_v)); + EXPECT_TRUE((is_array_v)); +} + +TEST(LlvmLibcTypeTraitsTest, is_base_of) { + struct A {}; + EXPECT_TRUE((is_base_of_v)); + + struct B : public A {}; + EXPECT_TRUE((is_base_of_v)); + EXPECT_FALSE((is_base_of_v)); + + struct C : protected A {}; + EXPECT_TRUE((is_base_of_v)); + EXPECT_FALSE((is_base_of_v)); + + struct D : private A {}; + EXPECT_TRUE((is_base_of_v)); + EXPECT_FALSE((is_base_of_v)); +} + +TEST(LlvmLibcTypeTraitsTest, is_class) { + EXPECT_TRUE((is_class_v)); + EXPECT_TRUE((is_class_v)); + EXPECT_FALSE((is_class_v)); + EXPECT_FALSE((is_class_v)); +} + +TYPED_TEST(LlvmLibcTypeTraitsTest, is_const, UnqualObjectTypes) { + EXPECT_FALSE((is_const_v)); + EXPECT_TRUE((is_const_v)); +} + +// TODO is_convertible + +TYPED_TEST(LlvmLibcTypeTraitsTest, is_destructible, UnqualObjectTypes) { + EXPECT_TRUE((is_destructible_v)); +} +TEST(LlvmLibcTypeTraitsTest, is_destructible_no_destructor) { + struct S { + ~S() = delete; + }; + EXPECT_FALSE((is_destructible_v)); +} + +TYPED_TEST(LlvmLibcTypeTraitsTest, is_enum, UnqualObjectTypes) { + EXPECT_FALSE((is_enum_v)); +} +TEST(LlvmLibcTypeTraitsTest, is_enum_enum) { + enum Enum {}; + EXPECT_TRUE((is_enum_v)); +} + +// TODO is_floating_point + +// TODO is_function + +// TODO is_integral + +// TODO is_lvalue_reference + +// TODO is_member_pointer + +// TODO is_null_pointer + +// TODO is_pointer + +// TODO is_reference + +// TODO is_rvalue_reference + +// TODO is_same + +// TODO is_scalar + +// TODO is_signed + +// TODO is_trivially_constructible + +// TODO is_trivially_copyable + +// TODO is_trivially_destructible + +// TODO is_union + +// TODO is_unsigned + +// TODO is_void + +// TODO make_signed + +// TODO make_unsigned + +// TODO remove_all_extents + +// TODO remove_cv + +// TODO remove_cvref + +// TODO remove_extent + +// TODO remove_reference + +TEST(LlvmLibcTypeTraitsTest, true_type) { EXPECT_TRUE((true_type::value)); } + +// TODO type_identity + +// TODO void_t + +} // namespace __llvm_libc::cpp diff --git a/utils/bazel/llvm-project-overlay/libc/test/src/__support/CPP/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/test/src/__support/CPP/BUILD.bazel index c74f9821849a7..5ebd826003579 100644 --- a/utils/bazel/llvm-project-overlay/libc/test/src/__support/CPP/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/libc/test/src/__support/CPP/BUILD.bazel @@ -110,3 +110,13 @@ cc_test( "//libc/test/UnitTest:LibcUnitTest", ], ) + +cc_test( + name = "type_traits_test", + srcs = ["type_traits_test.cpp"], + deps = [ + "//libc:__support_cpp_type_traits", + "//libc:libc_root", + "//libc/test/UnitTest:LibcUnitTest", + ], +) From 801f82bd8397535a85fe5ee38c2a8dd420b1337c Mon Sep 17 00:00:00 2001 From: Guillaume Chatelet Date: Mon, 11 Sep 2023 14:07:58 +0000 Subject: [PATCH 2/3] Address commetns --- .../src/__support/CPP/type_traits_test.cpp | 39 ++++++++++++++++--- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/libc/test/src/__support/CPP/type_traits_test.cpp b/libc/test/src/__support/CPP/type_traits_test.cpp index 69b7009e636b3..849a35799e1c5 100644 --- a/libc/test/src/__support/CPP/type_traits_test.cpp +++ b/libc/test/src/__support/CPP/type_traits_test.cpp @@ -16,11 +16,12 @@ namespace __llvm_libc::cpp { class Class {}; union Union {}; struct Struct {}; +enum Enum {}; +enum class EnumClass {}; using UnqualObjectTypes = testing::TypeList; TYPED_TEST(LlvmLibcTypeTraitsTest, add_lvalue_reference, UnqualObjectTypes) { - // non-ref cv, adds ref EXPECT_TRUE((is_same_v, T &>)); EXPECT_TRUE((is_same_v, const T &>)); @@ -28,6 +29,13 @@ TYPED_TEST(LlvmLibcTypeTraitsTest, add_lvalue_reference, UnqualObjectTypes) { EXPECT_TRUE(( is_same_v, const volatile T &>)); + // pointer cv, adds ref + EXPECT_TRUE((is_same_v, T *&>)); + EXPECT_TRUE((is_same_v, const T *&>)); + EXPECT_TRUE((is_same_v, volatile T *&>)); + EXPECT_TRUE((is_same_v, + const volatile T *&>)); + // ref cv, returns same type EXPECT_TRUE((is_same_v, T &>)); EXPECT_TRUE((is_same_v, const T &>)); @@ -53,6 +61,13 @@ TYPED_TEST(LlvmLibcTypeTraitsTest, add_pointer, UnqualObjectTypes) { EXPECT_TRUE((is_same_v, volatile T *>)); EXPECT_TRUE((is_same_v, const volatile T *>)); + // pointer types -> pointer type + EXPECT_TRUE((is_same_v, T **>)); + EXPECT_TRUE((is_same_v, const T **>)); + EXPECT_TRUE((is_same_v, volatile T **>)); + EXPECT_TRUE( + (is_same_v, const volatile T **>)); + // reference type -> pointer type EXPECT_TRUE((is_same_v, T *>)); EXPECT_TRUE((is_same_v, const T *>)); @@ -130,12 +145,12 @@ TEST(LlvmLibcTypeTraitsTest, integral_constant) { EXPECT_EQ((integral_constant::value), 4); } -using IntegralTypes = +using IntegralAndFloatingTypes = testing::TypeList; + unsigned long long, float, double, long double>; -TYPED_TEST(LlvmLibcTypeTraitsTest, is_arithmetic, IntegralTypes) { +TYPED_TEST(LlvmLibcTypeTraitsTest, is_arithmetic, IntegralAndFloatingTypes) { EXPECT_TRUE((is_arithmetic_v)); EXPECT_TRUE((is_arithmetic_v)); EXPECT_TRUE((is_arithmetic_v)); @@ -149,12 +164,14 @@ TEST(LlvmLibcTypeTraitsTest, is_arithmetic_non_integral) { EXPECT_FALSE((is_arithmetic_v)); EXPECT_FALSE((is_arithmetic_v)); EXPECT_FALSE((is_arithmetic_v)); + EXPECT_FALSE((is_arithmetic_v)); } TEST(LlvmLibcTypeTraitsTest, is_array) { EXPECT_FALSE((is_array_v)); EXPECT_FALSE((is_array_v)); EXPECT_FALSE((is_array_v)); + EXPECT_FALSE((is_array_v)); EXPECT_TRUE((is_array_v)); EXPECT_TRUE((is_array_v)); @@ -164,6 +181,7 @@ TEST(LlvmLibcTypeTraitsTest, is_base_of) { struct A {}; EXPECT_TRUE((is_base_of_v)); + // Test public, protected and private inheritance. struct B : public A {}; EXPECT_TRUE((is_base_of_v)); EXPECT_FALSE((is_base_of_v)); @@ -175,13 +193,24 @@ TEST(LlvmLibcTypeTraitsTest, is_base_of) { struct D : private A {}; EXPECT_TRUE((is_base_of_v)); EXPECT_FALSE((is_base_of_v)); + + // Test inheritance chain. + struct E : private B {}; + EXPECT_TRUE((is_base_of_v)); } TEST(LlvmLibcTypeTraitsTest, is_class) { EXPECT_TRUE((is_class_v)); EXPECT_TRUE((is_class_v)); + + // Pointer or ref do not qualify. + EXPECT_FALSE((is_class_v)); + EXPECT_FALSE((is_class_v)); + + // Neither other types. EXPECT_FALSE((is_class_v)); EXPECT_FALSE((is_class_v)); + EXPECT_FALSE((is_class_v)); } TYPED_TEST(LlvmLibcTypeTraitsTest, is_const, UnqualObjectTypes) { @@ -205,8 +234,8 @@ TYPED_TEST(LlvmLibcTypeTraitsTest, is_enum, UnqualObjectTypes) { EXPECT_FALSE((is_enum_v)); } TEST(LlvmLibcTypeTraitsTest, is_enum_enum) { - enum Enum {}; EXPECT_TRUE((is_enum_v)); + EXPECT_TRUE((is_enum_v)); } // TODO is_floating_point From 71936cde14df474aaf5951d8a59e524cee00ccfd Mon Sep 17 00:00:00 2001 From: Guillaume Chatelet Date: Mon, 11 Sep 2023 14:10:26 +0000 Subject: [PATCH 3/3] Fixing a missed comment --- libc/test/src/__support/CPP/type_traits_test.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libc/test/src/__support/CPP/type_traits_test.cpp b/libc/test/src/__support/CPP/type_traits_test.cpp index 849a35799e1c5..a48d646d29e5c 100644 --- a/libc/test/src/__support/CPP/type_traits_test.cpp +++ b/libc/test/src/__support/CPP/type_traits_test.cpp @@ -216,6 +216,9 @@ TEST(LlvmLibcTypeTraitsTest, is_class) { TYPED_TEST(LlvmLibcTypeTraitsTest, is_const, UnqualObjectTypes) { EXPECT_FALSE((is_const_v)); EXPECT_TRUE((is_const_v)); + + using Aliased = const T; + EXPECT_TRUE((is_const_v)); } // TODO is_convertible