106c3fb27SDimitry Andric //===----------------------------------------------------------------------===// 206c3fb27SDimitry Andric // 306c3fb27SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 406c3fb27SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 506c3fb27SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 606c3fb27SDimitry Andric // 706c3fb27SDimitry Andric //===----------------------------------------------------------------------===// 806c3fb27SDimitry Andric 906c3fb27SDimitry Andric #ifndef _LIBCPP___EXCEPTION_EXCEPTION_PTR_H 1006c3fb27SDimitry Andric #define _LIBCPP___EXCEPTION_EXCEPTION_PTR_H 1106c3fb27SDimitry Andric 1206c3fb27SDimitry Andric #include <__config> 1306c3fb27SDimitry Andric #include <__exception/operations.h> 1406c3fb27SDimitry Andric #include <__memory/addressof.h> 157a6dacacSDimitry Andric #include <__memory/construct_at.h> 167a6dacacSDimitry Andric #include <__type_traits/decay.h> 1706c3fb27SDimitry Andric #include <cstddef> 1806c3fb27SDimitry Andric #include <cstdlib> 197a6dacacSDimitry Andric #include <new> 207a6dacacSDimitry Andric #include <typeinfo> 2106c3fb27SDimitry Andric 2206c3fb27SDimitry Andric #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 2306c3fb27SDimitry Andric # pragma GCC system_header 2406c3fb27SDimitry Andric #endif 2506c3fb27SDimitry Andric 267a6dacacSDimitry Andric #ifndef _LIBCPP_ABI_MICROSOFT 277a6dacacSDimitry Andric 28*0fca6ea1SDimitry Andric # if _LIBCPP_AVAILABILITY_HAS_INIT_PRIMARY_EXCEPTION 29*0fca6ea1SDimitry Andric 307a6dacacSDimitry Andric namespace __cxxabiv1 { 317a6dacacSDimitry Andric 327a6dacacSDimitry Andric extern "C" { 337a6dacacSDimitry Andric _LIBCPP_OVERRIDABLE_FUNC_VIS void* __cxa_allocate_exception(size_t) throw(); 347a6dacacSDimitry Andric _LIBCPP_OVERRIDABLE_FUNC_VIS void __cxa_free_exception(void*) throw(); 357a6dacacSDimitry Andric 367a6dacacSDimitry Andric struct __cxa_exception; 377a6dacacSDimitry Andric _LIBCPP_OVERRIDABLE_FUNC_VIS __cxa_exception* __cxa_init_primary_exception( 387a6dacacSDimitry Andric void*, 397a6dacacSDimitry Andric std::type_info*, 407a6dacacSDimitry Andric # if defined(_WIN32) 41*0fca6ea1SDimitry Andric void(__thiscall*)(void*)) throw(); 42*0fca6ea1SDimitry Andric # elif defined(__wasm__) 43*0fca6ea1SDimitry Andric // In Wasm, a destructor returns its argument 44*0fca6ea1SDimitry Andric void* (*)(void*)) throw(); 45*0fca6ea1SDimitry Andric # else 46*0fca6ea1SDimitry Andric void (*)(void*)) throw(); 477a6dacacSDimitry Andric # endif 487a6dacacSDimitry Andric } 497a6dacacSDimitry Andric 507a6dacacSDimitry Andric } // namespace __cxxabiv1 517a6dacacSDimitry Andric 527a6dacacSDimitry Andric # endif 537a6dacacSDimitry Andric 54*0fca6ea1SDimitry Andric #endif 55*0fca6ea1SDimitry Andric 5606c3fb27SDimitry Andric namespace std { // purposefully not using versioning namespace 5706c3fb27SDimitry Andric 5806c3fb27SDimitry Andric #ifndef _LIBCPP_ABI_MICROSOFT 5906c3fb27SDimitry Andric 6006c3fb27SDimitry Andric class _LIBCPP_EXPORTED_FROM_ABI exception_ptr { 6106c3fb27SDimitry Andric void* __ptr_; 6206c3fb27SDimitry Andric 637a6dacacSDimitry Andric static exception_ptr __from_native_exception_pointer(void*) _NOEXCEPT; 647a6dacacSDimitry Andric 657a6dacacSDimitry Andric template <class _Ep> 667a6dacacSDimitry Andric friend _LIBCPP_HIDE_FROM_ABI exception_ptr make_exception_ptr(_Ep) _NOEXCEPT; 677a6dacacSDimitry Andric 6806c3fb27SDimitry Andric public: 69*0fca6ea1SDimitry Andric // exception_ptr is basically a COW string. 70*0fca6ea1SDimitry Andric using __trivially_relocatable = exception_ptr; 71*0fca6ea1SDimitry Andric 7206c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI exception_ptr() _NOEXCEPT : __ptr_() {} 7306c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI exception_ptr(nullptr_t) _NOEXCEPT : __ptr_() {} 7406c3fb27SDimitry Andric 7506c3fb27SDimitry Andric exception_ptr(const exception_ptr&) _NOEXCEPT; 7606c3fb27SDimitry Andric exception_ptr& operator=(const exception_ptr&) _NOEXCEPT; 7706c3fb27SDimitry Andric ~exception_ptr() _NOEXCEPT; 7806c3fb27SDimitry Andric 7906c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI explicit operator bool() const _NOEXCEPT { return __ptr_ != nullptr; } 8006c3fb27SDimitry Andric 8106c3fb27SDimitry Andric friend _LIBCPP_HIDE_FROM_ABI bool operator==(const exception_ptr& __x, const exception_ptr& __y) _NOEXCEPT { 8206c3fb27SDimitry Andric return __x.__ptr_ == __y.__ptr_; 8306c3fb27SDimitry Andric } 8406c3fb27SDimitry Andric 8506c3fb27SDimitry Andric friend _LIBCPP_HIDE_FROM_ABI bool operator!=(const exception_ptr& __x, const exception_ptr& __y) _NOEXCEPT { 8606c3fb27SDimitry Andric return !(__x == __y); 8706c3fb27SDimitry Andric } 8806c3fb27SDimitry Andric 8906c3fb27SDimitry Andric friend _LIBCPP_EXPORTED_FROM_ABI exception_ptr current_exception() _NOEXCEPT; 9006c3fb27SDimitry Andric friend _LIBCPP_EXPORTED_FROM_ABI void rethrow_exception(exception_ptr); 9106c3fb27SDimitry Andric }; 9206c3fb27SDimitry Andric 9306c3fb27SDimitry Andric template <class _Ep> 9406c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI exception_ptr make_exception_ptr(_Ep __e) _NOEXCEPT { 9506c3fb27SDimitry Andric # ifndef _LIBCPP_HAS_NO_EXCEPTIONS 967a6dacacSDimitry Andric # if _LIBCPP_AVAILABILITY_HAS_INIT_PRIMARY_EXCEPTION && __cplusplus >= 201103L 977a6dacacSDimitry Andric using _Ep2 = __decay_t<_Ep>; 987a6dacacSDimitry Andric 997a6dacacSDimitry Andric void* __ex = __cxxabiv1::__cxa_allocate_exception(sizeof(_Ep)); 100*0fca6ea1SDimitry Andric # ifdef __wasm__ 101*0fca6ea1SDimitry Andric // In Wasm, a destructor returns its argument 102*0fca6ea1SDimitry Andric (void)__cxxabiv1::__cxa_init_primary_exception( 103*0fca6ea1SDimitry Andric __ex, const_cast<std::type_info*>(&typeid(_Ep)), [](void* __p) -> void* { 104*0fca6ea1SDimitry Andric # else 1057a6dacacSDimitry Andric (void)__cxxabiv1::__cxa_init_primary_exception(__ex, const_cast<std::type_info*>(&typeid(_Ep)), [](void* __p) { 106*0fca6ea1SDimitry Andric # endif 1077a6dacacSDimitry Andric std::__destroy_at(static_cast<_Ep2*>(__p)); 108*0fca6ea1SDimitry Andric # ifdef __wasm__ 109*0fca6ea1SDimitry Andric return __p; 110*0fca6ea1SDimitry Andric # endif 1117a6dacacSDimitry Andric }); 1127a6dacacSDimitry Andric 1137a6dacacSDimitry Andric try { 1147a6dacacSDimitry Andric ::new (__ex) _Ep2(__e); 1157a6dacacSDimitry Andric return exception_ptr::__from_native_exception_pointer(__ex); 1167a6dacacSDimitry Andric } catch (...) { 1177a6dacacSDimitry Andric __cxxabiv1::__cxa_free_exception(__ex); 1187a6dacacSDimitry Andric return current_exception(); 1197a6dacacSDimitry Andric } 1207a6dacacSDimitry Andric # else 12106c3fb27SDimitry Andric try { 12206c3fb27SDimitry Andric throw __e; 12306c3fb27SDimitry Andric } catch (...) { 12406c3fb27SDimitry Andric return current_exception(); 12506c3fb27SDimitry Andric } 1267a6dacacSDimitry Andric # endif 12706c3fb27SDimitry Andric # else 12806c3fb27SDimitry Andric ((void)__e); 12906c3fb27SDimitry Andric std::abort(); 13006c3fb27SDimitry Andric # endif 13106c3fb27SDimitry Andric } 13206c3fb27SDimitry Andric 13306c3fb27SDimitry Andric #else // _LIBCPP_ABI_MICROSOFT 13406c3fb27SDimitry Andric 13506c3fb27SDimitry Andric class _LIBCPP_EXPORTED_FROM_ABI exception_ptr { 13606c3fb27SDimitry Andric _LIBCPP_DIAGNOSTIC_PUSH 13706c3fb27SDimitry Andric _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wunused-private-field") 13806c3fb27SDimitry Andric void* __ptr1_; 13906c3fb27SDimitry Andric void* __ptr2_; 14006c3fb27SDimitry Andric _LIBCPP_DIAGNOSTIC_POP 14106c3fb27SDimitry Andric 14206c3fb27SDimitry Andric public: 14306c3fb27SDimitry Andric exception_ptr() _NOEXCEPT; 14406c3fb27SDimitry Andric exception_ptr(nullptr_t) _NOEXCEPT; 14506c3fb27SDimitry Andric exception_ptr(const exception_ptr& __other) _NOEXCEPT; 14606c3fb27SDimitry Andric exception_ptr& operator=(const exception_ptr& __other) _NOEXCEPT; 14706c3fb27SDimitry Andric exception_ptr& operator=(nullptr_t) _NOEXCEPT; 14806c3fb27SDimitry Andric ~exception_ptr() _NOEXCEPT; 14906c3fb27SDimitry Andric explicit operator bool() const _NOEXCEPT; 15006c3fb27SDimitry Andric }; 15106c3fb27SDimitry Andric 15206c3fb27SDimitry Andric _LIBCPP_EXPORTED_FROM_ABI bool operator==(const exception_ptr& __x, const exception_ptr& __y) _NOEXCEPT; 15306c3fb27SDimitry Andric 15406c3fb27SDimitry Andric inline _LIBCPP_HIDE_FROM_ABI bool operator!=(const exception_ptr& __x, const exception_ptr& __y) _NOEXCEPT { 15506c3fb27SDimitry Andric return !(__x == __y); 15606c3fb27SDimitry Andric } 15706c3fb27SDimitry Andric 15806c3fb27SDimitry Andric _LIBCPP_EXPORTED_FROM_ABI void swap(exception_ptr&, exception_ptr&) _NOEXCEPT; 15906c3fb27SDimitry Andric 16006c3fb27SDimitry Andric _LIBCPP_EXPORTED_FROM_ABI exception_ptr __copy_exception_ptr(void* __except, const void* __ptr); 16106c3fb27SDimitry Andric _LIBCPP_EXPORTED_FROM_ABI exception_ptr current_exception() _NOEXCEPT; 16206c3fb27SDimitry Andric _LIBCPP_NORETURN _LIBCPP_EXPORTED_FROM_ABI void rethrow_exception(exception_ptr); 16306c3fb27SDimitry Andric 16406c3fb27SDimitry Andric // This is a built-in template function which automagically extracts the required 16506c3fb27SDimitry Andric // information. 16606c3fb27SDimitry Andric template <class _E> 16706c3fb27SDimitry Andric void* __GetExceptionInfo(_E); 16806c3fb27SDimitry Andric 16906c3fb27SDimitry Andric template <class _Ep> 17006c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI exception_ptr make_exception_ptr(_Ep __e) _NOEXCEPT { 17106c3fb27SDimitry Andric return __copy_exception_ptr(std::addressof(__e), __GetExceptionInfo(__e)); 17206c3fb27SDimitry Andric } 17306c3fb27SDimitry Andric 17406c3fb27SDimitry Andric #endif // _LIBCPP_ABI_MICROSOFT 17506c3fb27SDimitry Andric } // namespace std 17606c3fb27SDimitry Andric 17706c3fb27SDimitry Andric #endif // _LIBCPP___EXCEPTION_EXCEPTION_PTR_H 178