diff --git a/libcxx/include/__config b/libcxx/include/__config --- a/libcxx/include/__config +++ b/libcxx/include/__config @@ -1259,6 +1259,12 @@ # define _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(_ClassName) static_assert(true, "") #endif +// TODO(varconst): currently, there are bugs in Clang's intrinsics when handling Objective-C++ `id`, so don't use +// compiler intrinsics in the Objective-C++ mode. +# ifdef __OBJC__ +# define _LIBCPP_WORKAROUND_OBJCXX_COMPILER_INTRINSICS +# endif + #endif // __cplusplus #endif // _LIBCPP___CONFIG diff --git a/libcxx/include/__type_traits/add_pointer.h b/libcxx/include/__type_traits/add_pointer.h --- a/libcxx/include/__type_traits/add_pointer.h +++ b/libcxx/include/__type_traits/add_pointer.h @@ -22,7 +22,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if __has_builtin(__add_pointer) +#if !defined(_LIBCPP_WORKAROUND_OBJCXX_COMPILER_INTRINSICS) && __has_builtin(__add_pointer) template using __add_pointer_t = __add_pointer(_Tp); @@ -39,7 +39,7 @@ template using __add_pointer_t = typename __add_pointer_impl<_Tp>::type; -#endif // __has_builtin(__add_pointer) +#endif // !defined(_LIBCPP_WORKAROUND_OBJCXX_COMPILER_INTRINSICS) && __has_builtin(__add_pointer) template struct add_pointer { diff --git a/libcxx/include/__type_traits/remove_pointer.h b/libcxx/include/__type_traits/remove_pointer.h --- a/libcxx/include/__type_traits/remove_pointer.h +++ b/libcxx/include/__type_traits/remove_pointer.h @@ -17,7 +17,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if __has_builtin(__remove_pointer) +#if !defined(_LIBCPP_WORKAROUND_OBJCXX_COMPILER_INTRINSICS) && __has_builtin(__remove_pointer) template struct remove_pointer { using type _LIBCPP_NODEBUG = __remove_pointer(_Tp); @@ -34,7 +34,7 @@ template using __remove_pointer_t = typename remove_pointer<_Tp>::type; -#endif // __has_builtin(__remove_pointer) +#endif // !defined(_LIBCPP_WORKAROUND_OBJCXX_COMPILER_INTRINSICS) && __has_builtin(__remove_pointer) #if _LIBCPP_STD_VER >= 14 template using remove_pointer_t = __remove_pointer_t<_Tp>; diff --git a/libcxx/test/std/utilities/meta/meta.trans/objc_support.pass.mm b/libcxx/test/std/utilities/meta/meta.trans/objc_support.pass.mm new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/meta/meta.trans/objc_support.pass.mm @@ -0,0 +1,106 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: objective-c++ + +// Simple test to check that type traits support Objective-C types. + +#include +#include "test_macros.h" + +@interface I; +@end + +// add_pointer +static_assert(std::is_same::type, id*>::value, ""); +static_assert(std::is_same::type, I*>::value, ""); + +// add_lvalue_reference +static_assert(std::is_same::type, id&>::value, ""); +static_assert(std::is_same::type, I&>::value, ""); + +// add_rvalue_reference +static_assert(std::is_same::type, id&&>::value, ""); +static_assert(std::is_same::type, I&&>::value, ""); + +// decay +static_assert(std::is_same::type, id>::value, ""); +static_assert(std::is_same::type, I>::value, ""); +static_assert(std::is_same::type, id*>::value, ""); + +// __libcpp_is_referenceable +LIBCPP_STATIC_ASSERT(std::__libcpp_is_referenceable::value, ""); +LIBCPP_STATIC_ASSERT(std::__libcpp_is_referenceable::value, ""); +LIBCPP_STATIC_ASSERT(std::__libcpp_is_referenceable::value, ""); +LIBCPP_STATIC_ASSERT(std::__libcpp_is_referenceable::value, ""); +LIBCPP_STATIC_ASSERT(std::__libcpp_is_referenceable::value, ""); +LIBCPP_STATIC_ASSERT(std::__libcpp_is_referenceable::value, ""); +LIBCPP_STATIC_ASSERT(std::__libcpp_is_referenceable::value, ""); +LIBCPP_STATIC_ASSERT(std::__libcpp_is_referenceable::value, ""); + +// remove_all_extents +static_assert(std::is_same::type, id>::value, ""); +static_assert(std::is_same::type, id>::value, ""); +static_assert(std::is_same::type, id>::value, ""); +static_assert(std::is_same::type, I>::value, ""); + +// remove_const +static_assert(std::is_same::type, id>::value, ""); +static_assert(std::is_same::type, id>::value, ""); +static_assert(std::is_same::type, I>::value, ""); +static_assert(std::is_same::type, I>::value, ""); + +// remove_cv +static_assert(std::is_same::type, id>::value, ""); +static_assert(std::is_same::type, id>::value, ""); +static_assert(std::is_same::type, I>::value, ""); +static_assert(std::is_same::type, I>::value, ""); + +#if TEST_STD_VER >= 20 +// remove_cvref +static_assert(std::is_same::type, id>::value, ""); +static_assert(std::is_same::type, id>::value, ""); +static_assert(std::is_same::type, id>::value, ""); +static_assert(std::is_same::type, I>::value, ""); +static_assert(std::is_same::type, I>::value, ""); +static_assert(std::is_same::type, I>::value, ""); +#endif + +// remove_extent +static_assert(std::is_same::type, id>::value, ""); +static_assert(std::is_same::type, id>::value, ""); +static_assert(std::is_same::type, I>::value, ""); + +// remove_pointer +static_assert(!std::is_same::type, id>::value, ""); +// The result of removing and re-adding pointer to `id` should be still `id`. +static_assert(std::is_same::type*, id>::value, ""); +static_assert(std::is_same::type>::type, id>::value, ""); +static_assert(std::is_same::type>::type, id>::value, ""); + +// remove_reference +static_assert(std::is_same::type, id>::value, ""); +static_assert(std::is_same::type, id>::value, ""); +static_assert(std::is_same::type, const id>::value, ""); +static_assert(std::is_same::type, id>::value, ""); +static_assert(std::is_same::type, const id>::value, ""); +static_assert(std::is_same::type, I>::value, ""); +static_assert(std::is_same::type, I>::value, ""); +static_assert(std::is_same::type, const I>::value, ""); +static_assert(std::is_same::type, I>::value, ""); +static_assert(std::is_same::type, const I>::value, ""); + +// remove_volatile +static_assert(std::is_same::type, id>::value, ""); +static_assert(std::is_same::type, id>::value, ""); +static_assert(std::is_same::type, I>::value, ""); +static_assert(std::is_same::type, I>::value, ""); + +int main(int, char**) { + return 0; +}