Skip to content

Commit

Permalink
[libc++] Temporarily not use compiler intrinsics for some type traits…
Browse files Browse the repository at this point in the history
… in Objective-C++ mode.

Currently, there are bugs in Clang's intrinsics for type traits when
handling Objective-C++ `id` (e.g. in `add_pointer`). As a temporary
workaround, don't use these intrinsics in the Objective-C++ mode.

Differential Revision: https://reviews.llvm.org/D145186

(cherry picked from commit 87cf39a)
  • Loading branch information
var-const authored and tru committed Mar 6, 2023
1 parent 37e7b7d commit e479b95
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 4 deletions.
6 changes: 6 additions & 0 deletions libcxx/include/__config
Original file line number Diff line number Diff line change
Expand Up @@ -1259,6 +1259,12 @@ _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
# 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
4 changes: 2 additions & 2 deletions libcxx/include/__type_traits/add_pointer.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 <class _Tp>
using __add_pointer_t = __add_pointer(_Tp);
Expand All @@ -39,7 +39,7 @@ template <class _Tp> struct __add_pointer_impl<_Tp, false>
template <class _Tp>
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 <class _Tp>
struct add_pointer {
Expand Down
4 changes: 2 additions & 2 deletions libcxx/include/__type_traits/remove_pointer.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 <class _Tp>
struct remove_pointer {
using type _LIBCPP_NODEBUG = __remove_pointer(_Tp);
Expand All @@ -34,7 +34,7 @@ template <class _Tp> struct _LIBCPP_TEMPLATE_VIS remove_pointer<_Tp* const volat

template <class _Tp>
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 > 11
template <class _Tp> using remove_pointer_t = __remove_pointer_t<_Tp>;
Expand Down
106 changes: 106 additions & 0 deletions libcxx/test/std/utilities/meta/meta.trans/objc_support.pass.mm
Original file line number Diff line number Diff line change
@@ -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 <type_traits>
#include "test_macros.h"

@interface I;
@end

// add_pointer
static_assert(std::is_same<std::add_pointer<id>::type, id*>::value, "");
static_assert(std::is_same<std::add_pointer<I>::type, I*>::value, "");

// add_lvalue_reference
static_assert(std::is_same<std::add_lvalue_reference<id>::type, id&>::value, "");
static_assert(std::is_same<std::add_lvalue_reference<I>::type, I&>::value, "");

// add_rvalue_reference
static_assert(std::is_same<std::add_rvalue_reference<id>::type, id&&>::value, "");
static_assert(std::is_same<std::add_rvalue_reference<I>::type, I&&>::value, "");

// decay
static_assert(std::is_same<std::decay<id>::type, id>::value, "");
static_assert(std::is_same<std::decay<I>::type, I>::value, "");
static_assert(std::is_same<std::decay<id(&)[5]>::type, id*>::value, "");

// __libcpp_is_referenceable
LIBCPP_STATIC_ASSERT(std::__libcpp_is_referenceable<id>::value, "");
LIBCPP_STATIC_ASSERT(std::__libcpp_is_referenceable<id*>::value, "");
LIBCPP_STATIC_ASSERT(std::__libcpp_is_referenceable<id&>::value, "");
LIBCPP_STATIC_ASSERT(std::__libcpp_is_referenceable<id&&>::value, "");
LIBCPP_STATIC_ASSERT(std::__libcpp_is_referenceable<I>::value, "");
LIBCPP_STATIC_ASSERT(std::__libcpp_is_referenceable<I*>::value, "");
LIBCPP_STATIC_ASSERT(std::__libcpp_is_referenceable<I&>::value, "");
LIBCPP_STATIC_ASSERT(std::__libcpp_is_referenceable<I&&>::value, "");

// remove_all_extents
static_assert(std::is_same<std::remove_all_extents<id>::type, id>::value, "");
static_assert(std::is_same<std::remove_all_extents<id[5]>::type, id>::value, "");
static_assert(std::is_same<std::remove_all_extents<id[5][10]>::type, id>::value, "");
static_assert(std::is_same<std::remove_all_extents<I>::type, I>::value, "");

// remove_const
static_assert(std::is_same<std::remove_const<id>::type, id>::value, "");
static_assert(std::is_same<std::remove_const<const id>::type, id>::value, "");
static_assert(std::is_same<std::remove_const<I>::type, I>::value, "");
static_assert(std::is_same<std::remove_const<const I>::type, I>::value, "");

// remove_cv
static_assert(std::is_same<std::remove_cv<id>::type, id>::value, "");
static_assert(std::is_same<std::remove_cv<const volatile id>::type, id>::value, "");
static_assert(std::is_same<std::remove_cv<I>::type, I>::value, "");
static_assert(std::is_same<std::remove_cv<const volatile I>::type, I>::value, "");

#if TEST_STD_VER >= 20
// remove_cvref
static_assert(std::is_same<std::remove_cvref<id>::type, id>::value, "");
static_assert(std::is_same<std::remove_cvref<const volatile id&>::type, id>::value, "");
static_assert(std::is_same<std::remove_cvref<const volatile id&&>::type, id>::value, "");
static_assert(std::is_same<std::remove_cvref<I>::type, I>::value, "");
static_assert(std::is_same<std::remove_cvref<const volatile I&>::type, I>::value, "");
static_assert(std::is_same<std::remove_cvref<const volatile I&&>::type, I>::value, "");
#endif

// remove_extent
static_assert(std::is_same<std::remove_all_extents<id>::type, id>::value, "");
static_assert(std::is_same<std::remove_all_extents<id[5]>::type, id>::value, "");
static_assert(std::is_same<std::remove_all_extents<I>::type, I>::value, "");

// remove_pointer
static_assert(!std::is_same<std::remove_pointer<id>::type, id>::value, "");
// The result of removing and re-adding pointer to `id` should be still `id`.
static_assert(std::is_same<std::remove_pointer<id>::type*, id>::value, "");
static_assert(std::is_same<std::add_pointer<std::remove_pointer<id>::type>::type, id>::value, "");
static_assert(std::is_same<std::remove_pointer<std::add_pointer<id>::type>::type, id>::value, "");

// remove_reference
static_assert(std::is_same<std::remove_reference<id>::type, id>::value, "");
static_assert(std::is_same<std::remove_reference<id&>::type, id>::value, "");
static_assert(std::is_same<std::remove_reference<const id&>::type, const id>::value, "");
static_assert(std::is_same<std::remove_reference<id&&>::type, id>::value, "");
static_assert(std::is_same<std::remove_reference<const id&&>::type, const id>::value, "");
static_assert(std::is_same<std::remove_reference<I>::type, I>::value, "");
static_assert(std::is_same<std::remove_reference<I&>::type, I>::value, "");
static_assert(std::is_same<std::remove_reference<const I&>::type, const I>::value, "");
static_assert(std::is_same<std::remove_reference<I&&>::type, I>::value, "");
static_assert(std::is_same<std::remove_reference<const I&&>::type, const I>::value, "");

// remove_volatile
static_assert(std::is_same<std::remove_volatile<id>::type, id>::value, "");
static_assert(std::is_same<std::remove_volatile<volatile id>::type, id>::value, "");
static_assert(std::is_same<std::remove_volatile<I>::type, I>::value, "");
static_assert(std::is_same<std::remove_volatile<volatile I>::type, I>::value, "");

int main(int, char**) {
return 0;
}

0 comments on commit e479b95

Please sign in to comment.