From 9f88c67d226864bd7df99a3e55d4a4790a8d69fa Mon Sep 17 00:00:00 2001 From: Ivan Trofimov Date: Fri, 11 Apr 2025 18:23:30 +0300 Subject: [PATCH 1/4] fix std::make_exception_ptr interaction with ObjC --- libcxx/include/__exception/exception_ptr.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcxx/include/__exception/exception_ptr.h b/libcxx/include/__exception/exception_ptr.h index dac5b00b57fe3..8b90a6569d136 100644 --- a/libcxx/include/__exception/exception_ptr.h +++ b/libcxx/include/__exception/exception_ptr.h @@ -92,7 +92,7 @@ class _LIBCPP_EXPORTED_FROM_ABI exception_ptr { template _LIBCPP_HIDE_FROM_ABI exception_ptr make_exception_ptr(_Ep __e) _NOEXCEPT { # if _LIBCPP_HAS_EXCEPTIONS -# if _LIBCPP_AVAILABILITY_HAS_INIT_PRIMARY_EXCEPTION && __cplusplus >= 201103L +# if !defined(__OBJC__) && _LIBCPP_AVAILABILITY_HAS_INIT_PRIMARY_EXCEPTION && __cplusplus >= 201103L using _Ep2 = __decay_t<_Ep>; void* __ex = __cxxabiv1::__cxa_allocate_exception(sizeof(_Ep)); From 764caba12345ab1bc626758d5052c4597cbade62 Mon Sep 17 00:00:00 2001 From: Ivan Trofimov Date: Mon, 14 Apr 2025 17:17:37 +0300 Subject: [PATCH 2/4] add a comment about __OBJC__ define --- libcxx/include/__exception/exception_ptr.h | 1 + 1 file changed, 1 insertion(+) diff --git a/libcxx/include/__exception/exception_ptr.h b/libcxx/include/__exception/exception_ptr.h index 8b90a6569d136..167aa4d9b367a 100644 --- a/libcxx/include/__exception/exception_ptr.h +++ b/libcxx/include/__exception/exception_ptr.h @@ -92,6 +92,7 @@ class _LIBCPP_EXPORTED_FROM_ABI exception_ptr { template _LIBCPP_HIDE_FROM_ABI exception_ptr make_exception_ptr(_Ep __e) _NOEXCEPT { # if _LIBCPP_HAS_EXCEPTIONS + // Clang treats throwing ObjC types differently, and we have to preserve original throw-ing behavior # if !defined(__OBJC__) && _LIBCPP_AVAILABILITY_HAS_INIT_PRIMARY_EXCEPTION && __cplusplus >= 201103L using _Ep2 = __decay_t<_Ep>; From 6e108eb698cccec4202d711ae9795fffb53d5ec8 Mon Sep 17 00:00:00 2001 From: Ivan Trofimov Date: Wed, 14 May 2025 01:11:01 +0300 Subject: [PATCH 3/4] remove the __OBJC__ usage in favor of checking whether the type thrown is a pointer --- libcxx/include/__exception/exception_ptr.h | 52 +++++++++++++--------- 1 file changed, 32 insertions(+), 20 deletions(-) diff --git a/libcxx/include/__exception/exception_ptr.h b/libcxx/include/__exception/exception_ptr.h index 167aa4d9b367a..e0c6fc48b1333 100644 --- a/libcxx/include/__exception/exception_ptr.h +++ b/libcxx/include/__exception/exception_ptr.h @@ -15,6 +15,7 @@ #include <__memory/addressof.h> #include <__memory/construct_at.h> #include <__type_traits/decay.h> +#include <__type_traits/is_pointer.h> #include #include @@ -92,39 +93,50 @@ class _LIBCPP_EXPORTED_FROM_ABI exception_ptr { template _LIBCPP_HIDE_FROM_ABI exception_ptr make_exception_ptr(_Ep __e) _NOEXCEPT { # if _LIBCPP_HAS_EXCEPTIONS +# if _LIBCPP_AVAILABILITY_HAS_INIT_PRIMARY_EXCEPTION && __cplusplus >= 201703L // Clang treats throwing ObjC types differently, and we have to preserve original throw-ing behavior -# if !defined(__OBJC__) && _LIBCPP_AVAILABILITY_HAS_INIT_PRIMARY_EXCEPTION && __cplusplus >= 201103L - using _Ep2 = __decay_t<_Ep>; - - void* __ex = __cxxabiv1::__cxa_allocate_exception(sizeof(_Ep)); + // to not break some ObjC invariants. ObjC types are thrown by a pointer, hence the condition; + // although it does also trigger for some valid c++ usages, this should be a case rare enough to + // not complicate the condition any further + if constexpr (std::is_pointer_v<_Ep>) { + try { + throw __e; + } catch (...) { + return current_exception(); + } + } else { + using _Ep2 = __decay_t<_Ep>; + + void* __ex = __cxxabiv1::__cxa_allocate_exception(sizeof(_Ep)); # ifdef __wasm__ - // In Wasm, a destructor returns its argument - (void)__cxxabiv1::__cxa_init_primary_exception( - __ex, const_cast(&typeid(_Ep)), [](void* __p) -> void* { + // In Wasm, a destructor returns its argument + (void)__cxxabiv1::__cxa_init_primary_exception( + __ex, const_cast(&typeid(_Ep)), [](void* __p) -> void* { # else - (void)__cxxabiv1::__cxa_init_primary_exception(__ex, const_cast(&typeid(_Ep)), [](void* __p) { + (void)__cxxabiv1::__cxa_init_primary_exception(__ex, const_cast(&typeid(_Ep)), [](void* __p) { # endif - std::__destroy_at(static_cast<_Ep2*>(__p)); + std::__destroy_at(static_cast<_Ep2*>(__p)); # ifdef __wasm__ - return __p; + return __p; # endif - }); - - try { - ::new (__ex) _Ep2(__e); - return exception_ptr::__from_native_exception_pointer(__ex); - } catch (...) { - __cxxabiv1::__cxa_free_exception(__ex); - return current_exception(); + }); + + try { + ::new (__ex) _Ep2(__e); + return exception_ptr::__from_native_exception_pointer(__ex); + } catch (...) { + __cxxabiv1::__cxa_free_exception(__ex); + return current_exception(); + } } -# else +# else // !(_LIBCPP_AVAILABILITY_HAS_INIT_PRIMARY_EXCEPTION && __cplusplus >= 201703L) try { throw __e; } catch (...) { return current_exception(); } # endif -# else +# else // !LIBCPP_HAS_EXCEPTIONS ((void)__e); std::abort(); # endif From a1e858653db7c21dc3ff5ff5ba887d72c6dc1942 Mon Sep 17 00:00:00 2001 From: Ivan Trofimov Date: Tue, 20 May 2025 14:23:10 +0300 Subject: [PATCH 4/4] relax the c++-standard requirement --- libcxx/include/__exception/exception_ptr.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcxx/include/__exception/exception_ptr.h b/libcxx/include/__exception/exception_ptr.h index eb791d739e4b6..d38bec7720a5f 100644 --- a/libcxx/include/__exception/exception_ptr.h +++ b/libcxx/include/__exception/exception_ptr.h @@ -96,7 +96,7 @@ class _LIBCPP_EXPORTED_FROM_ABI exception_ptr { template _LIBCPP_HIDE_FROM_ABI exception_ptr make_exception_ptr(_Ep __e) _NOEXCEPT { # if _LIBCPP_HAS_EXCEPTIONS -# if _LIBCPP_AVAILABILITY_HAS_INIT_PRIMARY_EXCEPTION && __cplusplus >= 201703L +# if _LIBCPP_AVAILABILITY_HAS_INIT_PRIMARY_EXCEPTION && __cplusplus >= 201103L // Clang treats throwing ObjC types differently, and we have to preserve original throw-ing behavior // to not break some ObjC invariants. ObjC types are thrown by a pointer, hence the condition; // although it does also trigger for some valid c++ usages, this should be a case rare enough to