Skip to content

Commit e479b95

Browse files
var-consttru
authored andcommitted
[libc++] Temporarily not use compiler intrinsics for some type traits 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)
1 parent 37e7b7d commit e479b95

File tree

4 files changed

+116
-4
lines changed

4 files changed

+116
-4
lines changed

libcxx/include/__config

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1259,6 +1259,12 @@ _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
12591259
# define _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(_ClassName) static_assert(true, "")
12601260
#endif
12611261

1262+
// TODO(varconst): currently, there are bugs in Clang's intrinsics when handling Objective-C++ `id`, so don't use
1263+
// compiler intrinsics in the Objective-C++ mode.
1264+
# ifdef __OBJC__
1265+
# define _LIBCPP_WORKAROUND_OBJCXX_COMPILER_INTRINSICS
1266+
# endif
1267+
12621268
#endif // __cplusplus
12631269

12641270
#endif // _LIBCPP___CONFIG

libcxx/include/__type_traits/add_pointer.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222

2323
_LIBCPP_BEGIN_NAMESPACE_STD
2424

25-
#if __has_builtin(__add_pointer)
25+
#if !defined(_LIBCPP_WORKAROUND_OBJCXX_COMPILER_INTRINSICS) && __has_builtin(__add_pointer)
2626

2727
template <class _Tp>
2828
using __add_pointer_t = __add_pointer(_Tp);
@@ -39,7 +39,7 @@ template <class _Tp> struct __add_pointer_impl<_Tp, false>
3939
template <class _Tp>
4040
using __add_pointer_t = typename __add_pointer_impl<_Tp>::type;
4141

42-
#endif // __has_builtin(__add_pointer)
42+
#endif // !defined(_LIBCPP_WORKAROUND_OBJCXX_COMPILER_INTRINSICS) && __has_builtin(__add_pointer)
4343

4444
template <class _Tp>
4545
struct add_pointer {

libcxx/include/__type_traits/remove_pointer.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717

1818
_LIBCPP_BEGIN_NAMESPACE_STD
1919

20-
#if __has_builtin(__remove_pointer)
20+
#if !defined(_LIBCPP_WORKAROUND_OBJCXX_COMPILER_INTRINSICS) && __has_builtin(__remove_pointer)
2121
template <class _Tp>
2222
struct remove_pointer {
2323
using type _LIBCPP_NODEBUG = __remove_pointer(_Tp);
@@ -34,7 +34,7 @@ template <class _Tp> struct _LIBCPP_TEMPLATE_VIS remove_pointer<_Tp* const volat
3434

3535
template <class _Tp>
3636
using __remove_pointer_t = typename remove_pointer<_Tp>::type;
37-
#endif // __has_builtin(__remove_pointer)
37+
#endif // !defined(_LIBCPP_WORKAROUND_OBJCXX_COMPILER_INTRINSICS) && __has_builtin(__remove_pointer)
3838

3939
#if _LIBCPP_STD_VER > 11
4040
template <class _Tp> using remove_pointer_t = __remove_pointer_t<_Tp>;
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
// REQUIRES: objective-c++
10+
11+
// Simple test to check that type traits support Objective-C types.
12+
13+
#include <type_traits>
14+
#include "test_macros.h"
15+
16+
@interface I;
17+
@end
18+
19+
// add_pointer
20+
static_assert(std::is_same<std::add_pointer<id>::type, id*>::value, "");
21+
static_assert(std::is_same<std::add_pointer<I>::type, I*>::value, "");
22+
23+
// add_lvalue_reference
24+
static_assert(std::is_same<std::add_lvalue_reference<id>::type, id&>::value, "");
25+
static_assert(std::is_same<std::add_lvalue_reference<I>::type, I&>::value, "");
26+
27+
// add_rvalue_reference
28+
static_assert(std::is_same<std::add_rvalue_reference<id>::type, id&&>::value, "");
29+
static_assert(std::is_same<std::add_rvalue_reference<I>::type, I&&>::value, "");
30+
31+
// decay
32+
static_assert(std::is_same<std::decay<id>::type, id>::value, "");
33+
static_assert(std::is_same<std::decay<I>::type, I>::value, "");
34+
static_assert(std::is_same<std::decay<id(&)[5]>::type, id*>::value, "");
35+
36+
// __libcpp_is_referenceable
37+
LIBCPP_STATIC_ASSERT(std::__libcpp_is_referenceable<id>::value, "");
38+
LIBCPP_STATIC_ASSERT(std::__libcpp_is_referenceable<id*>::value, "");
39+
LIBCPP_STATIC_ASSERT(std::__libcpp_is_referenceable<id&>::value, "");
40+
LIBCPP_STATIC_ASSERT(std::__libcpp_is_referenceable<id&&>::value, "");
41+
LIBCPP_STATIC_ASSERT(std::__libcpp_is_referenceable<I>::value, "");
42+
LIBCPP_STATIC_ASSERT(std::__libcpp_is_referenceable<I*>::value, "");
43+
LIBCPP_STATIC_ASSERT(std::__libcpp_is_referenceable<I&>::value, "");
44+
LIBCPP_STATIC_ASSERT(std::__libcpp_is_referenceable<I&&>::value, "");
45+
46+
// remove_all_extents
47+
static_assert(std::is_same<std::remove_all_extents<id>::type, id>::value, "");
48+
static_assert(std::is_same<std::remove_all_extents<id[5]>::type, id>::value, "");
49+
static_assert(std::is_same<std::remove_all_extents<id[5][10]>::type, id>::value, "");
50+
static_assert(std::is_same<std::remove_all_extents<I>::type, I>::value, "");
51+
52+
// remove_const
53+
static_assert(std::is_same<std::remove_const<id>::type, id>::value, "");
54+
static_assert(std::is_same<std::remove_const<const id>::type, id>::value, "");
55+
static_assert(std::is_same<std::remove_const<I>::type, I>::value, "");
56+
static_assert(std::is_same<std::remove_const<const I>::type, I>::value, "");
57+
58+
// remove_cv
59+
static_assert(std::is_same<std::remove_cv<id>::type, id>::value, "");
60+
static_assert(std::is_same<std::remove_cv<const volatile id>::type, id>::value, "");
61+
static_assert(std::is_same<std::remove_cv<I>::type, I>::value, "");
62+
static_assert(std::is_same<std::remove_cv<const volatile I>::type, I>::value, "");
63+
64+
#if TEST_STD_VER >= 20
65+
// remove_cvref
66+
static_assert(std::is_same<std::remove_cvref<id>::type, id>::value, "");
67+
static_assert(std::is_same<std::remove_cvref<const volatile id&>::type, id>::value, "");
68+
static_assert(std::is_same<std::remove_cvref<const volatile id&&>::type, id>::value, "");
69+
static_assert(std::is_same<std::remove_cvref<I>::type, I>::value, "");
70+
static_assert(std::is_same<std::remove_cvref<const volatile I&>::type, I>::value, "");
71+
static_assert(std::is_same<std::remove_cvref<const volatile I&&>::type, I>::value, "");
72+
#endif
73+
74+
// remove_extent
75+
static_assert(std::is_same<std::remove_all_extents<id>::type, id>::value, "");
76+
static_assert(std::is_same<std::remove_all_extents<id[5]>::type, id>::value, "");
77+
static_assert(std::is_same<std::remove_all_extents<I>::type, I>::value, "");
78+
79+
// remove_pointer
80+
static_assert(!std::is_same<std::remove_pointer<id>::type, id>::value, "");
81+
// The result of removing and re-adding pointer to `id` should be still `id`.
82+
static_assert(std::is_same<std::remove_pointer<id>::type*, id>::value, "");
83+
static_assert(std::is_same<std::add_pointer<std::remove_pointer<id>::type>::type, id>::value, "");
84+
static_assert(std::is_same<std::remove_pointer<std::add_pointer<id>::type>::type, id>::value, "");
85+
86+
// remove_reference
87+
static_assert(std::is_same<std::remove_reference<id>::type, id>::value, "");
88+
static_assert(std::is_same<std::remove_reference<id&>::type, id>::value, "");
89+
static_assert(std::is_same<std::remove_reference<const id&>::type, const id>::value, "");
90+
static_assert(std::is_same<std::remove_reference<id&&>::type, id>::value, "");
91+
static_assert(std::is_same<std::remove_reference<const id&&>::type, const id>::value, "");
92+
static_assert(std::is_same<std::remove_reference<I>::type, I>::value, "");
93+
static_assert(std::is_same<std::remove_reference<I&>::type, I>::value, "");
94+
static_assert(std::is_same<std::remove_reference<const I&>::type, const I>::value, "");
95+
static_assert(std::is_same<std::remove_reference<I&&>::type, I>::value, "");
96+
static_assert(std::is_same<std::remove_reference<const I&&>::type, const I>::value, "");
97+
98+
// remove_volatile
99+
static_assert(std::is_same<std::remove_volatile<id>::type, id>::value, "");
100+
static_assert(std::is_same<std::remove_volatile<volatile id>::type, id>::value, "");
101+
static_assert(std::is_same<std::remove_volatile<I>::type, I>::value, "");
102+
static_assert(std::is_same<std::remove_volatile<volatile I>::type, I>::value, "");
103+
104+
int main(int, char**) {
105+
return 0;
106+
}

0 commit comments

Comments
 (0)