Skip to content

Commit ddbbe97

Browse files
committed
Refactor the function to be easier to understand
1 parent ca8f571 commit ddbbe97

File tree

1 file changed

+48
-38
lines changed

1 file changed

+48
-38
lines changed

libcxx/include/__exception/exception_ptr.h

Lines changed: 48 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -93,51 +93,61 @@ class _LIBCPP_EXPORTED_FROM_ABI exception_ptr {
9393
};
9494

9595
template <class _Ep>
96-
_LIBCPP_HIDE_FROM_ABI exception_ptr make_exception_ptr(_Ep __e) _NOEXCEPT {
97-
# if _LIBCPP_HAS_EXCEPTIONS
98-
# if _LIBCPP_AVAILABILITY_HAS_INIT_PRIMARY_EXCEPTION && __cplusplus >= 201103L
99-
// Clang treats throwing ObjC types differently, and we have to preserve original throw-ing behavior
100-
// to not break some ObjC invariants. ObjC types are thrown by a pointer, hence the condition;
101-
// although it does also trigger for some valid c++ usages, this should be a case rare enough to
102-
// not complicate the condition any further
103-
if constexpr (is_pointer<_Ep>::value) {
104-
try {
105-
throw __e;
106-
} catch (...) {
107-
return current_exception();
108-
}
109-
} else {
110-
using _Ep2 = __decay_t<_Ep>;
111-
112-
void* __ex = __cxxabiv1::__cxa_allocate_exception(sizeof(_Ep));
113-
# ifdef __wasm__
114-
// In Wasm, a destructor returns its argument
115-
(void)__cxxabiv1::__cxa_init_primary_exception(
116-
__ex, const_cast<std::type_info*>(&typeid(_Ep)), [](void* __p) -> void* {
117-
# else
118-
(void)__cxxabiv1::__cxa_init_primary_exception(__ex, const_cast<std::type_info*>(&typeid(_Ep)), [](void* __p) {
119-
# endif
120-
std::__destroy_at(static_cast<_Ep2*>(__p));
121-
# ifdef __wasm__
122-
return __p;
123-
# endif
124-
});
125-
126-
try {
127-
::new (__ex) _Ep2(__e);
128-
return exception_ptr::__from_native_exception_pointer(__ex);
129-
} catch (...) {
130-
__cxxabiv1::__cxa_free_exception(__ex);
131-
return current_exception();
132-
}
96+
_LIBCPP_HIDE_FROM_ABI exception_ptr __make_exception_ptr_explicit(_Ep& __e) _NOEXCEPT {
97+
using _Ep2 = __decay_t<_Ep>;
98+
void* __ex = __cxxabiv1::__cxa_allocate_exception(sizeof(_Ep));
99+
# ifdef __wasm__
100+
auto __cleanup = [](void* __p) -> void* {
101+
std::__destroy_at(static_cast<_Ep2*>(__p));
102+
return __p;
103+
};
104+
# else
105+
auto __cleanup = [](void* __p) { std::__destroy_at(static_cast<_Ep2*>(__p)); };
106+
# endif
107+
(void)__cxxabiv1::__cxa_init_primary_exception(__ex, const_cast<std::type_info*>(&typeid(_Ep)), __cleanup);
108+
109+
try {
110+
::new (__ex) _Ep2(__e);
111+
return exception_ptr::__from_native_exception_pointer(__ex);
112+
} catch (...) {
113+
__cxxabiv1::__cxa_free_exception(__ex);
114+
return current_exception();
133115
}
134-
# else // !(_LIBCPP_AVAILABILITY_HAS_INIT_PRIMARY_EXCEPTION && __cplusplus >= 201103L)
116+
}
117+
118+
template <class _Ep>
119+
_LIBCPP_HIDE_FROM_ABI exception_ptr __make_exception_ptr_via_throw(_Ep& __e) _NOEXCEPT {
135120
try {
136121
throw __e;
137122
} catch (...) {
138123
return current_exception();
139124
}
125+
}
126+
127+
template <class _Ep>
128+
_LIBCPP_HIDE_FROM_ABI exception_ptr make_exception_ptr(_Ep __e) _NOEXCEPT {
129+
# if _LIBCPP_HAS_EXCEPTIONS
130+
// Objective-C exceptions are thrown via pointer. When throwing an Objective-C exception,
131+
// Clang generates a call to `objc_exception_throw` instead of the usual `__cxa_throw`.
132+
// That function creates an exception with a special Objective-C typeinfo instead of
133+
// the usual C++ typeinfo, since that is needed to implement the behavior documented
134+
// at [1]).
135+
//
136+
// Because of this special behavior, we can't create an exception via `__cxa_init_primary_exception`
137+
// for Objective-C exceptions, otherwise we'd bypass `objc_exception_throw`. See https://llvm.org/PR135089.
138+
//
139+
// [1]:
140+
// https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/Exceptions/Articles/Exceptions64Bit.html
141+
if constexpr (is_pointer<_Ep>::value) {
142+
return std::__make_exception_ptr_via_throw(__e);
143+
}
144+
145+
# if _LIBCPP_AVAILABILITY_HAS_INIT_PRIMARY_EXCEPTION && __cplusplus >= 201103L
146+
return std::__make_exception_ptr_explicit(__e);
147+
# else
148+
return std::__make_exception_ptr_via_throw(__e);
140149
# endif
150+
141151
# else // !LIBCPP_HAS_EXCEPTIONS
142152
((void)__e);
143153
std::abort();

0 commit comments

Comments
 (0)