From 3ab691253d62985f86e20c8780ea29b5bbec3c20 Mon Sep 17 00:00:00 2001 From: Guillaume Chatelet Date: Fri, 8 Sep 2023 11:26:07 +0000 Subject: [PATCH 1/3] [libc] Add is_object --- libc/src/__support/CPP/type_traits.h | 1 + .../src/__support/CPP/type_traits/is_object.h | 30 +++++++++++++++++++ .../llvm-project-overlay/libc/BUILD.bazel | 1 + 3 files changed, 32 insertions(+) create mode 100644 libc/src/__support/CPP/type_traits/is_object.h diff --git a/libc/src/__support/CPP/type_traits.h b/libc/src/__support/CPP/type_traits.h index c0d3591f8d37e..9deb08b221593 100644 --- a/libc/src/__support/CPP/type_traits.h +++ b/libc/src/__support/CPP/type_traits.h @@ -32,6 +32,7 @@ #include "src/__support/CPP/type_traits/is_lvalue_reference.h" #include "src/__support/CPP/type_traits/is_member_pointer.h" #include "src/__support/CPP/type_traits/is_null_pointer.h" +#include "src/__support/CPP/type_traits/is_object.h" #include "src/__support/CPP/type_traits/is_pointer.h" #include "src/__support/CPP/type_traits/is_reference.h" #include "src/__support/CPP/type_traits/is_rvalue_reference.h" diff --git a/libc/src/__support/CPP/type_traits/is_object.h b/libc/src/__support/CPP/type_traits/is_object.h new file mode 100644 index 0000000000000..9928fb7b85e3d --- /dev/null +++ b/libc/src/__support/CPP/type_traits/is_object.h @@ -0,0 +1,30 @@ +//===-- is_object type_traits -----------------------------------*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_LIBC_SRC_SUPPORT_CPP_TYPE_TRAITS_IS_OBJECT_H +#define LLVM_LIBC_SRC_SUPPORT_CPP_TYPE_TRAITS_IS_OBJECT_H + +#include "src/__support/CPP/type_traits/bool_constant.h" +#include "src/__support/CPP/type_traits/is_array.h" +#include "src/__support/CPP/type_traits/is_class.h" +#include "src/__support/CPP/type_traits/is_scalar.h" +#include "src/__support/CPP/type_traits/is_union.h" +#include "src/__support/macros/attributes.h" + +namespace __llvm_libc::cpp { + +// is_object +template +struct is_object + : cpp::bool_constant || cpp::is_array_v || + cpp::is_union_v || cpp::is_class_v> {}; +template +LIBC_INLINE_VAR constexpr bool is_object_v = is_object::value; + +} // namespace __llvm_libc::cpp + +#endif // LLVM_LIBC_SRC_SUPPORT_CPP_TYPE_TRAITS_IS_OBJECT_H diff --git a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel index 3680ee730e72d..17e4913749d51 100644 --- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel @@ -309,6 +309,7 @@ libc_support_library( "src/__support/CPP/type_traits/is_lvalue_reference.h", "src/__support/CPP/type_traits/is_member_pointer.h", "src/__support/CPP/type_traits/is_null_pointer.h", + "src/__support/CPP/type_traits/is_object.h", "src/__support/CPP/type_traits/is_pointer.h", "src/__support/CPP/type_traits/is_reference.h", "src/__support/CPP/type_traits/is_rvalue_reference.h", From 07281d72cd500c2cfb55a4c008357ef914f539d5 Mon Sep 17 00:00:00 2001 From: Guillaume Chatelet Date: Fri, 8 Sep 2023 13:10:05 +0000 Subject: [PATCH 2/3] [libc] add invoke_result type traits --- libc/src/__support/CPP/type_traits.h | 1 + .../__support/CPP/type_traits/invoke_result.h | 90 +++++++++++++++++++ .../llvm-project-overlay/libc/BUILD.bazel | 2 + 3 files changed, 93 insertions(+) create mode 100644 libc/src/__support/CPP/type_traits/invoke_result.h diff --git a/libc/src/__support/CPP/type_traits.h b/libc/src/__support/CPP/type_traits.h index 9deb08b221593..cec5de1198c96 100644 --- a/libc/src/__support/CPP/type_traits.h +++ b/libc/src/__support/CPP/type_traits.h @@ -18,6 +18,7 @@ #include "src/__support/CPP/type_traits/enable_if.h" #include "src/__support/CPP/type_traits/false_type.h" #include "src/__support/CPP/type_traits/integral_constant.h" +#include "src/__support/CPP/type_traits/invoke_result.h" #include "src/__support/CPP/type_traits/is_arithmetic.h" #include "src/__support/CPP/type_traits/is_array.h" #include "src/__support/CPP/type_traits/is_base_of.h" diff --git a/libc/src/__support/CPP/type_traits/invoke_result.h b/libc/src/__support/CPP/type_traits/invoke_result.h new file mode 100644 index 0000000000000..47b0ffb88e573 --- /dev/null +++ b/libc/src/__support/CPP/type_traits/invoke_result.h @@ -0,0 +1,90 @@ +//===-- invoke_result type_traits -------------------------------*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_LIBC_SRC_SUPPORT_CPP_TYPE_TRAITS_INVOKE_RESULT_H +#define LLVM_LIBC_SRC_SUPPORT_CPP_TYPE_TRAITS_INVOKE_RESULT_H + +#include "src/__support/CPP/type_traits/decay.h" +#include "src/__support/CPP/type_traits/enable_if.h" +#include "src/__support/CPP/type_traits/false_type.h" +#include "src/__support/CPP/type_traits/is_base_of.h" +#include "src/__support/CPP/type_traits/is_function.h" +#include "src/__support/CPP/type_traits/true_type.h" +#include "src/__support/CPP/utility/declval.h" +#include "src/__support/CPP/utility/forward.h" + +// BEWARE : this implementation is not fully conformant as it doesn't take +// `cpp::reference_wrapper` into account. + +namespace __llvm_libc::cpp { + +// invoke_result + +namespace detail { +template struct is_reference_wrapper : cpp::false_type {}; + +// Disable specialization on `cpp::reference_wrapper` as it is not yet +// implemented. + +// template struct +// is_reference_wrapper> : cpp::true_type {}; + +template struct invoke_impl { + template + static auto call(F &&f, Args &&...args) + -> decltype(cpp::forward(f)(cpp::forward(args)...)); +}; + +template struct invoke_impl { + template , + class = cpp::enable_if_t>> + static auto get(T &&t) -> T &&; + + template , + class = cpp::enable_if_t::value>> + static auto get(T &&t) -> decltype(t.get()); + + template , + class = cpp::enable_if_t>, + class = cpp::enable_if_t::value>> + static auto get(T &&t) -> decltype(*cpp::forward(t)); + + template >> + static auto call(MT1 B::*pmf, T &&t, Args &&...args) + -> decltype((invoke_impl::get(cpp::forward(t)).* + pmf)(cpp::forward(args)...)); + + template + static auto call(MT B::*pmd, T &&t) + -> decltype(invoke_impl::get(cpp::forward(t)).*pmd); +}; + +template > +auto INVOKE(F &&f, Args &&...args) + -> decltype(invoke_impl::call(cpp::forward(f), + cpp::forward(args)...)); + +template struct invoke_result {}; +template +struct invoke_result(), + cpp::declval()...))), + F, Args...> { + using type = + decltype(detail::INVOKE(cpp::declval(), cpp::declval()...)); +}; +} // namespace detail + +template +struct invoke_result : detail::invoke_result {}; + +template +using invoke_result_t = typename invoke_result::type; + +} // namespace __llvm_libc::cpp + +#endif // LLVM_LIBC_SRC_SUPPORT_CPP_TYPE_TRAITS_INVOKE_RESULT_H diff --git a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel index 17e4913749d51..da9bdc64fb781 100644 --- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel @@ -295,6 +295,7 @@ libc_support_library( "src/__support/CPP/type_traits/enable_if.h", "src/__support/CPP/type_traits/false_type.h", "src/__support/CPP/type_traits/integral_constant.h", + "src/__support/CPP/type_traits/invoke_result.h", "src/__support/CPP/type_traits/is_arithmetic.h", "src/__support/CPP/type_traits/is_array.h", "src/__support/CPP/type_traits/is_base_of.h", @@ -333,6 +334,7 @@ libc_support_library( "src/__support/CPP/type_traits/type_identity.h", "src/__support/CPP/type_traits/void_t.h", "src/__support/CPP/utility/declval.h", + "src/__support/CPP/utility/forward.h", ], deps = [ ":__support_macros_attributes", From 2b4edbb4fd79b9b08365e1bf47a4657bb970bae3 Mon Sep 17 00:00:00 2001 From: Guillaume Chatelet Date: Fri, 8 Sep 2023 13:17:37 +0000 Subject: [PATCH 3/3] [libc] add invoke type traits --- libc/src/__support/CPP/type_traits.h | 1 + libc/src/__support/CPP/type_traits/invoke.h | 64 +++++++++++++++++++ .../llvm-project-overlay/libc/BUILD.bazel | 1 + 3 files changed, 66 insertions(+) create mode 100644 libc/src/__support/CPP/type_traits/invoke.h diff --git a/libc/src/__support/CPP/type_traits.h b/libc/src/__support/CPP/type_traits.h index cec5de1198c96..3de2ca5890318 100644 --- a/libc/src/__support/CPP/type_traits.h +++ b/libc/src/__support/CPP/type_traits.h @@ -18,6 +18,7 @@ #include "src/__support/CPP/type_traits/enable_if.h" #include "src/__support/CPP/type_traits/false_type.h" #include "src/__support/CPP/type_traits/integral_constant.h" +#include "src/__support/CPP/type_traits/invoke.h" #include "src/__support/CPP/type_traits/invoke_result.h" #include "src/__support/CPP/type_traits/is_arithmetic.h" #include "src/__support/CPP/type_traits/is_array.h" diff --git a/libc/src/__support/CPP/type_traits/invoke.h b/libc/src/__support/CPP/type_traits/invoke.h new file mode 100644 index 0000000000000..b31c93de97607 --- /dev/null +++ b/libc/src/__support/CPP/type_traits/invoke.h @@ -0,0 +1,64 @@ +//===-- invoke type_traits --------------------------------------*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_LIBC_SRC_SUPPORT_CPP_TYPE_TRAITS_INVOKE_H +#define LLVM_LIBC_SRC_SUPPORT_CPP_TYPE_TRAITS_INVOKE_H + +#include "src/__support/CPP/type_traits/decay.h" +#include "src/__support/CPP/type_traits/invoke_result.h" +#include "src/__support/CPP/type_traits/is_base_of.h" +#include "src/__support/CPP/type_traits/is_function.h" +#include "src/__support/CPP/type_traits/is_member_pointer.h" +#include "src/__support/CPP/type_traits/is_object.h" +#include "src/__support/CPP/utility/forward.h" + +// BEWARE : this implementation is not fully conformant as it doesn't take +// `cpp::reference_wrapper` into account. It also bypasses noexcept detection. + +namespace __llvm_libc::cpp { + +// invoke +namespace detail { +template constexpr bool is_reference_wrapper_v = false; + +// Disable specialization on `cpp::reference_wrapper` as it is not yet +// implemented. + +// template +// constexpr bool is_reference_wrapper_v> = true; + +template +constexpr decltype(auto) invoke_memptr(Pointed C::*f, T1 &&t1, Args &&...args) { + if constexpr (cpp::is_function_v) { + if constexpr (cpp::is_base_of_v>) + return (cpp::forward(t1).*f)(cpp::forward(args)...); + else if constexpr (is_reference_wrapper_v>) + return (t1.get().*f)(cpp::forward(args)...); + else + return ((*cpp::forward(t1)).*f)(cpp::forward(args)...); + } else { + static_assert(cpp::is_object_v && sizeof...(args) == 0); + if constexpr (cpp::is_base_of_v>) + return cpp::forward(t1).*f; + else if constexpr (is_reference_wrapper_v>) + return t1.get().*f; + else + return (*cpp::forward(t1)).*f; + } +} +} // namespace detail + +template +constexpr cpp::invoke_result_t invoke(F &&f, Args &&...args) { + if constexpr (cpp::is_member_pointer_v>) + return detail::invoke_memptr(f, cpp::forward(args)...); + else + return cpp::forward(f)(cpp::forward(args)...); +} +} // namespace __llvm_libc::cpp + +#endif // LLVM_LIBC_SRC_SUPPORT_CPP_TYPE_TRAITS_INVOKE_H diff --git a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel index da9bdc64fb781..06cabc015decf 100644 --- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel @@ -295,6 +295,7 @@ libc_support_library( "src/__support/CPP/type_traits/enable_if.h", "src/__support/CPP/type_traits/false_type.h", "src/__support/CPP/type_traits/integral_constant.h", + "src/__support/CPP/type_traits/invoke.h", "src/__support/CPP/type_traits/invoke_result.h", "src/__support/CPP/type_traits/is_arithmetic.h", "src/__support/CPP/type_traits/is_array.h",