[libcxx-commits] [libcxx] 87cf39a - [libc++] Temporarily not use compiler intrinsics for some type traits in Objective-C++ mode.

Konstantin Varlamov via libcxx-commits libcxx-commits at lists.llvm.org
Thu Mar 2 17:35:33 PST 2023


Author: Konstantin Varlamov
Date: 2023-03-02T17:35:12-08:00
New Revision: 87cf39aa349b83ae3b7d16c30ac7a8ffa0ad098c

URL: https://github.com/llvm/llvm-project/commit/87cf39aa349b83ae3b7d16c30ac7a8ffa0ad098c
DIFF: https://github.com/llvm/llvm-project/commit/87cf39aa349b83ae3b7d16c30ac7a8ffa0ad098c.diff

LOG: [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

Added: 
    libcxx/test/std/utilities/meta/meta.trans/objc_support.pass.mm

Modified: 
    libcxx/include/__config
    libcxx/include/__type_traits/add_pointer.h
    libcxx/include/__type_traits/remove_pointer.h

Removed: 
    


################################################################################
diff  --git a/libcxx/include/__config b/libcxx/include/__config
index 6790fb3c7ec2e..f531b1c057f84 100644
--- a/libcxx/include/__config
+++ b/libcxx/include/__config
@@ -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

diff  --git a/libcxx/include/__type_traits/add_pointer.h b/libcxx/include/__type_traits/add_pointer.h
index 9f01086d3c642..1e74dafaf0e8b 100644
--- 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 <class _Tp>
 using __add_pointer_t = __add_pointer(_Tp);
@@ -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 {

diff  --git a/libcxx/include/__type_traits/remove_pointer.h b/libcxx/include/__type_traits/remove_pointer.h
index 6c02d254013c9..8b3a9c7c039f4 100644
--- 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 <class _Tp>
 struct remove_pointer {
   using type _LIBCPP_NODEBUG = __remove_pointer(_Tp);
@@ -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 >= 14
 template <class _Tp> 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
index 0000000000000..e1fb119e190c3
--- /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 <type_traits>
+#include "test_macros.h"
+
+ at interface I;
+ at 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;
+}


        


More information about the libcxx-commits mailing list