diff --git a/libc/src/__support/CPP/type_traits.h b/libc/src/__support/CPP/type_traits.h --- a/libc/src/__support/CPP/type_traits.h +++ b/libc/src/__support/CPP/type_traits.h @@ -11,6 +11,8 @@ #include "src/__support/macros/attributes.h" +#include // For size_t. + namespace __llvm_libc { namespace cpp { @@ -30,6 +32,8 @@ using true_type = cpp::integral_constant; using false_type = cpp::integral_constant; +template using bool_constant = integral_constant; + template struct is_trivially_copyable : public integral_constant {}; @@ -214,6 +218,128 @@ details::void_t( declval()))>> = true; +#if __has_builtin(__is_lvalue_reference) && \ + __has_builtin(__is_rvalue_reference) && __has_builtin(__is_reference) + +template +struct is_lvalue_reference : bool_constant<__is_lvalue_reference(T)> {}; +template +struct is_rvalue_reference : bool_constant<__is_rvalue_reference(T)> {}; +template struct is_reference : bool_constant<__is_reference(T)> {}; + +#else // __has_builtin(__is_lvalue_reference) && etc... + +template struct is_lvalue_reference : public false_type {}; +template struct is_lvalue_reference : public true_type {}; + +template struct is_rvalue_reference : public false_type {}; +template struct is_rvalue_reference : public true_type {}; + +template struct is_reference : public false_type {}; +template struct is_reference : public true_type {}; +template struct is_reference : public true_type {}; + +#endif // __has_builtin(__is_lvalue_reference) && etc... + +#if __has_builtin(__remove_all_extents) +template using __remove_all_extents_t = __remove_all_extents(T); +#else +template struct remove_all_extents { + typedef T type; +}; +template struct remove_all_extents { + typedef typename remove_all_extents::type type; +}; +template struct remove_all_extents { + typedef typename remove_all_extents::type type; +}; + +template +using __remove_all_extents_t = typename remove_all_extents::type; +#endif // __has_builtin(__remove_all_extents) + +#if __has_builtin(__is_function) + +template +struct is_function : integral_constant {}; + +#else + +template +struct is_function + : public integral_constant::value || + is_const::value)> {}; + +#endif // __has_builtin(__is_function) + +#if __has_builtin(__is_destructible) + +template +struct is_destructible : bool_constant<__is_destructible(T)> {}; + +#else // __has_builtin(__is_destructible) + +// if it's a reference, return true +// if it's a function, return false +// if it's void, return false +// if it's an array of unknown bound, return false +// Otherwise, return "declval().~T()" is well-formed +// where T is remove_all_extents::type + +template struct __is_destructible_apply { + typedef int type; +}; + +template struct __is_destructor_wellformed { + template + static true_type __test( + typename __is_destructible_apply().~T1())>::type); + + template static false_type __test(...); + + static const bool value = decltype(__test(12))::value; +}; + +template struct __destructible_imp; + +template +struct __destructible_imp + : public integral_constant< + bool, __is_destructor_wellformed<__remove_all_extents_t>::value> { +}; + +template struct __destructible_imp : public true_type {}; + +template struct __destructible_false; +template +struct __destructible_false + : public __destructible_imp::value> {}; +template +struct __destructible_false : public false_type {}; + +template +struct is_destructible : public __destructible_false::value> { +}; +template struct is_destructible : public false_type {}; +template <> struct is_destructible : public false_type {}; + +#endif // __has_builtin(__is_destructible) + +#if __has_builtin(__is_trivially_destructible) + +template +struct is_trivially_destructible + : public integral_constant {}; + +#elif __has_builtin(__has_trivial_destructor) + +template +struct is_trivially_destructible + : public integral_constant< + bool, is_destructible::value &&__has_trivial_destructor(T)> {}; + +#endif // __has_builtin(__is_trivially_destructible) + } // namespace cpp } // namespace __llvm_libc