|
15 | 15 | #include <__memory/addressof.h> |
16 | 16 | #include <__memory/construct_at.h> |
17 | 17 | #include <__type_traits/decay.h> |
| 18 | +#include <__type_traits/is_pointer.h> |
18 | 19 | #include <cstdlib> |
19 | 20 | #include <typeinfo> |
20 | 21 |
|
@@ -92,39 +93,50 @@ class _LIBCPP_EXPORTED_FROM_ABI exception_ptr { |
92 | 93 | template <class _Ep> |
93 | 94 | _LIBCPP_HIDE_FROM_ABI exception_ptr make_exception_ptr(_Ep __e) _NOEXCEPT { |
94 | 95 | # if _LIBCPP_HAS_EXCEPTIONS |
| 96 | +# if _LIBCPP_AVAILABILITY_HAS_INIT_PRIMARY_EXCEPTION && __cplusplus >= 201703L |
95 | 97 | // Clang treats throwing ObjC types differently, and we have to preserve original throw-ing behavior |
96 | | -# if !defined(__OBJC__) && _LIBCPP_AVAILABILITY_HAS_INIT_PRIMARY_EXCEPTION && __cplusplus >= 201103L |
97 | | - using _Ep2 = __decay_t<_Ep>; |
98 | | - |
99 | | - void* __ex = __cxxabiv1::__cxa_allocate_exception(sizeof(_Ep)); |
| 98 | + // to not break some ObjC invariants. ObjC types are thrown by a pointer, hence the condition; |
| 99 | + // although it does also trigger for some valid c++ usages, this should be a case rare enough to |
| 100 | + // not complicate the condition any further |
| 101 | + if constexpr (std::is_pointer_v<_Ep>) { |
| 102 | + try { |
| 103 | + throw __e; |
| 104 | + } catch (...) { |
| 105 | + return current_exception(); |
| 106 | + } |
| 107 | + } else { |
| 108 | + using _Ep2 = __decay_t<_Ep>; |
| 109 | + |
| 110 | + void* __ex = __cxxabiv1::__cxa_allocate_exception(sizeof(_Ep)); |
100 | 111 | # ifdef __wasm__ |
101 | | - // In Wasm, a destructor returns its argument |
102 | | - (void)__cxxabiv1::__cxa_init_primary_exception( |
103 | | - __ex, const_cast<std::type_info*>(&typeid(_Ep)), [](void* __p) -> void* { |
| 112 | + // In Wasm, a destructor returns its argument |
| 113 | + (void)__cxxabiv1::__cxa_init_primary_exception( |
| 114 | + __ex, const_cast<std::type_info*>(&typeid(_Ep)), [](void* __p) -> void* { |
104 | 115 | # else |
105 | | - (void)__cxxabiv1::__cxa_init_primary_exception(__ex, const_cast<std::type_info*>(&typeid(_Ep)), [](void* __p) { |
| 116 | + (void)__cxxabiv1::__cxa_init_primary_exception(__ex, const_cast<std::type_info*>(&typeid(_Ep)), [](void* __p) { |
106 | 117 | # endif |
107 | | - std::__destroy_at(static_cast<_Ep2*>(__p)); |
| 118 | + std::__destroy_at(static_cast<_Ep2*>(__p)); |
108 | 119 | # ifdef __wasm__ |
109 | | - return __p; |
| 120 | + return __p; |
110 | 121 | # endif |
111 | | - }); |
112 | | - |
113 | | - try { |
114 | | - ::new (__ex) _Ep2(__e); |
115 | | - return exception_ptr::__from_native_exception_pointer(__ex); |
116 | | - } catch (...) { |
117 | | - __cxxabiv1::__cxa_free_exception(__ex); |
118 | | - return current_exception(); |
| 122 | + }); |
| 123 | + |
| 124 | + try { |
| 125 | + ::new (__ex) _Ep2(__e); |
| 126 | + return exception_ptr::__from_native_exception_pointer(__ex); |
| 127 | + } catch (...) { |
| 128 | + __cxxabiv1::__cxa_free_exception(__ex); |
| 129 | + return current_exception(); |
| 130 | + } |
119 | 131 | } |
120 | | -# else |
| 132 | +# else // !(_LIBCPP_AVAILABILITY_HAS_INIT_PRIMARY_EXCEPTION && __cplusplus >= 201703L) |
121 | 133 | try { |
122 | 134 | throw __e; |
123 | 135 | } catch (...) { |
124 | 136 | return current_exception(); |
125 | 137 | } |
126 | 138 | # endif |
127 | | -# else |
| 139 | +# else // !LIBCPP_HAS_EXCEPTIONS |
128 | 140 | ((void)__e); |
129 | 141 | std::abort(); |
130 | 142 | # endif |
|
0 commit comments