10b57cec5SDimitry Andric// -*- C++ -*- 2*349cc55cSDimitry Andric//===----------------------------------------------------------------------===// 30b57cec5SDimitry Andric// 40b57cec5SDimitry Andric// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 50b57cec5SDimitry Andric// See https://llvm.org/LICENSE.txt for license information. 60b57cec5SDimitry Andric// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 70b57cec5SDimitry Andric// 80b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 90b57cec5SDimitry Andric 100b57cec5SDimitry Andric#ifndef _LIBCPP_EXCEPTION 110b57cec5SDimitry Andric#define _LIBCPP_EXCEPTION 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric/* 140b57cec5SDimitry Andric exception synopsis 150b57cec5SDimitry Andric 160b57cec5SDimitry Andricnamespace std 170b57cec5SDimitry Andric{ 180b57cec5SDimitry Andric 190b57cec5SDimitry Andricclass exception 200b57cec5SDimitry Andric{ 210b57cec5SDimitry Andricpublic: 220b57cec5SDimitry Andric exception() noexcept; 230b57cec5SDimitry Andric exception(const exception&) noexcept; 240b57cec5SDimitry Andric exception& operator=(const exception&) noexcept; 250b57cec5SDimitry Andric virtual ~exception() noexcept; 260b57cec5SDimitry Andric virtual const char* what() const noexcept; 270b57cec5SDimitry Andric}; 280b57cec5SDimitry Andric 290b57cec5SDimitry Andricclass bad_exception 300b57cec5SDimitry Andric : public exception 310b57cec5SDimitry Andric{ 320b57cec5SDimitry Andricpublic: 330b57cec5SDimitry Andric bad_exception() noexcept; 340b57cec5SDimitry Andric bad_exception(const bad_exception&) noexcept; 350b57cec5SDimitry Andric bad_exception& operator=(const bad_exception&) noexcept; 360b57cec5SDimitry Andric virtual ~bad_exception() noexcept; 370b57cec5SDimitry Andric virtual const char* what() const noexcept; 380b57cec5SDimitry Andric}; 390b57cec5SDimitry Andric 400b57cec5SDimitry Andrictypedef void (*unexpected_handler)(); 410b57cec5SDimitry Andricunexpected_handler set_unexpected(unexpected_handler f ) noexcept; 420b57cec5SDimitry Andricunexpected_handler get_unexpected() noexcept; 430b57cec5SDimitry Andric[[noreturn]] void unexpected(); 440b57cec5SDimitry Andric 450b57cec5SDimitry Andrictypedef void (*terminate_handler)(); 460b57cec5SDimitry Andricterminate_handler set_terminate(terminate_handler f ) noexcept; 470b57cec5SDimitry Andricterminate_handler get_terminate() noexcept; 480b57cec5SDimitry Andric[[noreturn]] void terminate() noexcept; 490b57cec5SDimitry Andric 500b57cec5SDimitry Andricbool uncaught_exception() noexcept; 510b57cec5SDimitry Andricint uncaught_exceptions() noexcept; // C++17 520b57cec5SDimitry Andric 530b57cec5SDimitry Andrictypedef unspecified exception_ptr; 540b57cec5SDimitry Andric 550b57cec5SDimitry Andricexception_ptr current_exception() noexcept; 560b57cec5SDimitry Andricvoid rethrow_exception [[noreturn]] (exception_ptr p); 570b57cec5SDimitry Andrictemplate<class E> exception_ptr make_exception_ptr(E e) noexcept; 580b57cec5SDimitry Andric 590b57cec5SDimitry Andricclass nested_exception 600b57cec5SDimitry Andric{ 610b57cec5SDimitry Andricpublic: 620b57cec5SDimitry Andric nested_exception() noexcept; 630b57cec5SDimitry Andric nested_exception(const nested_exception&) noexcept = default; 640b57cec5SDimitry Andric nested_exception& operator=(const nested_exception&) noexcept = default; 650b57cec5SDimitry Andric virtual ~nested_exception() = default; 660b57cec5SDimitry Andric 670b57cec5SDimitry Andric // access functions 680b57cec5SDimitry Andric [[noreturn]] void rethrow_nested() const; 690b57cec5SDimitry Andric exception_ptr nested_ptr() const noexcept; 700b57cec5SDimitry Andric}; 710b57cec5SDimitry Andric 720b57cec5SDimitry Andrictemplate <class T> [[noreturn]] void throw_with_nested(T&& t); 730b57cec5SDimitry Andrictemplate <class E> void rethrow_if_nested(const E& e); 740b57cec5SDimitry Andric 750b57cec5SDimitry Andric} // std 760b57cec5SDimitry Andric 770b57cec5SDimitry Andric*/ 780b57cec5SDimitry Andric 79e8d8bef9SDimitry Andric#include <__availability> 80fe6060f1SDimitry Andric#include <__config> 81fe6060f1SDimitry Andric#include <__memory/addressof.h> 820b57cec5SDimitry Andric#include <cstddef> 830b57cec5SDimitry Andric#include <cstdlib> 840b57cec5SDimitry Andric#include <type_traits> 850b57cec5SDimitry Andric#include <version> 860b57cec5SDimitry Andric 870b57cec5SDimitry Andric#if defined(_LIBCPP_ABI_VCRUNTIME) 880b57cec5SDimitry Andric#include <vcruntime_exception.h> 890b57cec5SDimitry Andric#endif 900b57cec5SDimitry Andric 910b57cec5SDimitry Andric#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 920b57cec5SDimitry Andric#pragma GCC system_header 930b57cec5SDimitry Andric#endif 940b57cec5SDimitry Andric 950b57cec5SDimitry Andricnamespace std // purposefully not using versioning namespace 960b57cec5SDimitry Andric{ 970b57cec5SDimitry Andric 980b57cec5SDimitry Andric#if !defined(_LIBCPP_ABI_VCRUNTIME) 990b57cec5SDimitry Andricclass _LIBCPP_EXCEPTION_ABI exception 1000b57cec5SDimitry Andric{ 1010b57cec5SDimitry Andricpublic: 1020b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY exception() _NOEXCEPT {} 1039ec406dcSDimitry Andric _LIBCPP_INLINE_VISIBILITY exception(const exception&) _NOEXCEPT = default; 1049ec406dcSDimitry Andric 1050b57cec5SDimitry Andric virtual ~exception() _NOEXCEPT; 1060b57cec5SDimitry Andric virtual const char* what() const _NOEXCEPT; 1070b57cec5SDimitry Andric}; 1080b57cec5SDimitry Andric 1090b57cec5SDimitry Andricclass _LIBCPP_EXCEPTION_ABI bad_exception 1100b57cec5SDimitry Andric : public exception 1110b57cec5SDimitry Andric{ 1120b57cec5SDimitry Andricpublic: 1130b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY bad_exception() _NOEXCEPT {} 1140b57cec5SDimitry Andric virtual ~bad_exception() _NOEXCEPT; 1150b57cec5SDimitry Andric virtual const char* what() const _NOEXCEPT; 1160b57cec5SDimitry Andric}; 1170b57cec5SDimitry Andric#endif // !_LIBCPP_ABI_VCRUNTIME 1180b57cec5SDimitry Andric 1190b57cec5SDimitry Andric#if _LIBCPP_STD_VER <= 14 \ 1200b57cec5SDimitry Andric || defined(_LIBCPP_ENABLE_CXX17_REMOVED_UNEXPECTED_FUNCTIONS) \ 1210b57cec5SDimitry Andric || defined(_LIBCPP_BUILDING_LIBRARY) 1220b57cec5SDimitry Andrictypedef void (*unexpected_handler)(); 1230b57cec5SDimitry Andric_LIBCPP_FUNC_VIS unexpected_handler set_unexpected(unexpected_handler) _NOEXCEPT; 1240b57cec5SDimitry Andric_LIBCPP_FUNC_VIS unexpected_handler get_unexpected() _NOEXCEPT; 1250b57cec5SDimitry Andric_LIBCPP_NORETURN _LIBCPP_FUNC_VIS void unexpected(); 1260b57cec5SDimitry Andric#endif 1270b57cec5SDimitry Andric 1280b57cec5SDimitry Andrictypedef void (*terminate_handler)(); 1290b57cec5SDimitry Andric_LIBCPP_FUNC_VIS terminate_handler set_terminate(terminate_handler) _NOEXCEPT; 1300b57cec5SDimitry Andric_LIBCPP_FUNC_VIS terminate_handler get_terminate() _NOEXCEPT; 1310b57cec5SDimitry Andric_LIBCPP_NORETURN _LIBCPP_FUNC_VIS void terminate() _NOEXCEPT; 1320b57cec5SDimitry Andric 1330b57cec5SDimitry Andric_LIBCPP_FUNC_VIS bool uncaught_exception() _NOEXCEPT; 1340b57cec5SDimitry Andric_LIBCPP_FUNC_VIS _LIBCPP_AVAILABILITY_UNCAUGHT_EXCEPTIONS int uncaught_exceptions() _NOEXCEPT; 1350b57cec5SDimitry Andric 1360b57cec5SDimitry Andricclass _LIBCPP_TYPE_VIS exception_ptr; 1370b57cec5SDimitry Andric 1380b57cec5SDimitry Andric_LIBCPP_FUNC_VIS exception_ptr current_exception() _NOEXCEPT; 1390b57cec5SDimitry Andric_LIBCPP_NORETURN _LIBCPP_FUNC_VIS void rethrow_exception(exception_ptr); 1400b57cec5SDimitry Andric 1410b57cec5SDimitry Andric#ifndef _LIBCPP_ABI_MICROSOFT 1420b57cec5SDimitry Andric 1430b57cec5SDimitry Andricclass _LIBCPP_TYPE_VIS exception_ptr 1440b57cec5SDimitry Andric{ 1450b57cec5SDimitry Andric void* __ptr_; 1460b57cec5SDimitry Andricpublic: 1470b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY exception_ptr() _NOEXCEPT : __ptr_() {} 1480b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY exception_ptr(nullptr_t) _NOEXCEPT : __ptr_() {} 1490b57cec5SDimitry Andric 1500b57cec5SDimitry Andric exception_ptr(const exception_ptr&) _NOEXCEPT; 1510b57cec5SDimitry Andric exception_ptr& operator=(const exception_ptr&) _NOEXCEPT; 1520b57cec5SDimitry Andric ~exception_ptr() _NOEXCEPT; 1530b57cec5SDimitry Andric 154fe6060f1SDimitry Andric _LIBCPP_INLINE_VISIBILITY explicit operator bool() const _NOEXCEPT 1550b57cec5SDimitry Andric {return __ptr_ != nullptr;} 1560b57cec5SDimitry Andric 1570b57cec5SDimitry Andric friend _LIBCPP_INLINE_VISIBILITY 1580b57cec5SDimitry Andric bool operator==(const exception_ptr& __x, const exception_ptr& __y) _NOEXCEPT 1590b57cec5SDimitry Andric {return __x.__ptr_ == __y.__ptr_;} 1600b57cec5SDimitry Andric 1610b57cec5SDimitry Andric friend _LIBCPP_INLINE_VISIBILITY 1620b57cec5SDimitry Andric bool operator!=(const exception_ptr& __x, const exception_ptr& __y) _NOEXCEPT 1630b57cec5SDimitry Andric {return !(__x == __y);} 1640b57cec5SDimitry Andric 1650b57cec5SDimitry Andric friend _LIBCPP_FUNC_VIS exception_ptr current_exception() _NOEXCEPT; 1660b57cec5SDimitry Andric friend _LIBCPP_FUNC_VIS void rethrow_exception(exception_ptr); 1670b57cec5SDimitry Andric}; 1680b57cec5SDimitry Andric 1690b57cec5SDimitry Andrictemplate<class _Ep> 1700b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY exception_ptr 1710b57cec5SDimitry Andricmake_exception_ptr(_Ep __e) _NOEXCEPT 1720b57cec5SDimitry Andric{ 1730b57cec5SDimitry Andric#ifndef _LIBCPP_NO_EXCEPTIONS 1740b57cec5SDimitry Andric try 1750b57cec5SDimitry Andric { 1760b57cec5SDimitry Andric throw __e; 1770b57cec5SDimitry Andric } 1780b57cec5SDimitry Andric catch (...) 1790b57cec5SDimitry Andric { 1800b57cec5SDimitry Andric return current_exception(); 1810b57cec5SDimitry Andric } 1820b57cec5SDimitry Andric#else 1830b57cec5SDimitry Andric ((void)__e); 1840b57cec5SDimitry Andric _VSTD::abort(); 1850b57cec5SDimitry Andric#endif 1860b57cec5SDimitry Andric} 1870b57cec5SDimitry Andric 1880b57cec5SDimitry Andric#else // _LIBCPP_ABI_MICROSOFT 1890b57cec5SDimitry Andric 1900b57cec5SDimitry Andricclass _LIBCPP_TYPE_VIS exception_ptr 1910b57cec5SDimitry Andric{ 1920b57cec5SDimitry Andric#if defined(__clang__) 1930b57cec5SDimitry Andric#pragma clang diagnostic push 1940b57cec5SDimitry Andric#pragma clang diagnostic ignored "-Wunused-private-field" 1950b57cec5SDimitry Andric#endif 1960b57cec5SDimitry Andric void* __ptr1_; 1970b57cec5SDimitry Andric void* __ptr2_; 1980b57cec5SDimitry Andric#if defined(__clang__) 1990b57cec5SDimitry Andric#pragma clang diagnostic pop 2000b57cec5SDimitry Andric#endif 2010b57cec5SDimitry Andricpublic: 2020b57cec5SDimitry Andric exception_ptr() _NOEXCEPT; 2030b57cec5SDimitry Andric exception_ptr(nullptr_t) _NOEXCEPT; 2040b57cec5SDimitry Andric exception_ptr(const exception_ptr& __other) _NOEXCEPT; 2050b57cec5SDimitry Andric exception_ptr& operator=(const exception_ptr& __other) _NOEXCEPT; 2060b57cec5SDimitry Andric exception_ptr& operator=(nullptr_t) _NOEXCEPT; 2070b57cec5SDimitry Andric ~exception_ptr() _NOEXCEPT; 208fe6060f1SDimitry Andric explicit operator bool() const _NOEXCEPT; 2090b57cec5SDimitry Andric}; 2100b57cec5SDimitry Andric 2110b57cec5SDimitry Andric_LIBCPP_FUNC_VIS 2120b57cec5SDimitry Andricbool operator==(const exception_ptr& __x, const exception_ptr& __y) _NOEXCEPT; 2130b57cec5SDimitry Andric 2140b57cec5SDimitry Andricinline _LIBCPP_INLINE_VISIBILITY 2150b57cec5SDimitry Andricbool operator!=(const exception_ptr& __x, const exception_ptr& __y) _NOEXCEPT 2160b57cec5SDimitry Andric {return !(__x == __y);} 2170b57cec5SDimitry Andric 2180b57cec5SDimitry Andric_LIBCPP_FUNC_VIS void swap(exception_ptr&, exception_ptr&) _NOEXCEPT; 2190b57cec5SDimitry Andric 2200b57cec5SDimitry Andric_LIBCPP_FUNC_VIS exception_ptr __copy_exception_ptr(void *__except, const void* __ptr); 2210b57cec5SDimitry Andric_LIBCPP_FUNC_VIS exception_ptr current_exception() _NOEXCEPT; 2220b57cec5SDimitry Andric_LIBCPP_NORETURN _LIBCPP_FUNC_VIS void rethrow_exception(exception_ptr p); 2230b57cec5SDimitry Andric 2240b57cec5SDimitry Andric// This is a built-in template function which automagically extracts the required 2250b57cec5SDimitry Andric// information. 2260b57cec5SDimitry Andrictemplate <class _E> void *__GetExceptionInfo(_E); 2270b57cec5SDimitry Andric 2280b57cec5SDimitry Andrictemplate<class _Ep> 2290b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY exception_ptr 2300b57cec5SDimitry Andricmake_exception_ptr(_Ep __e) _NOEXCEPT 2310b57cec5SDimitry Andric{ 2320b57cec5SDimitry Andric return __copy_exception_ptr(_VSTD::addressof(__e), __GetExceptionInfo(__e)); 2330b57cec5SDimitry Andric} 2340b57cec5SDimitry Andric 2350b57cec5SDimitry Andric#endif // _LIBCPP_ABI_MICROSOFT 2360b57cec5SDimitry Andric// nested_exception 2370b57cec5SDimitry Andric 2380b57cec5SDimitry Andricclass _LIBCPP_EXCEPTION_ABI nested_exception 2390b57cec5SDimitry Andric{ 2400b57cec5SDimitry Andric exception_ptr __ptr_; 2410b57cec5SDimitry Andricpublic: 2420b57cec5SDimitry Andric nested_exception() _NOEXCEPT; 2430b57cec5SDimitry Andric// nested_exception(const nested_exception&) noexcept = default; 2440b57cec5SDimitry Andric// nested_exception& operator=(const nested_exception&) noexcept = default; 2450b57cec5SDimitry Andric virtual ~nested_exception() _NOEXCEPT; 2460b57cec5SDimitry Andric 2470b57cec5SDimitry Andric // access functions 2480b57cec5SDimitry Andric _LIBCPP_NORETURN void rethrow_nested() const; 2490b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY exception_ptr nested_ptr() const _NOEXCEPT {return __ptr_;} 2500b57cec5SDimitry Andric}; 2510b57cec5SDimitry Andric 2520b57cec5SDimitry Andrictemplate <class _Tp> 2530b57cec5SDimitry Andricstruct __nested 2540b57cec5SDimitry Andric : public _Tp, 2550b57cec5SDimitry Andric public nested_exception 2560b57cec5SDimitry Andric{ 2570b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY explicit __nested(const _Tp& __t) : _Tp(__t) {} 2580b57cec5SDimitry Andric}; 2590b57cec5SDimitry Andric 2600b57cec5SDimitry Andric#ifndef _LIBCPP_NO_EXCEPTIONS 2610b57cec5SDimitry Andrictemplate <class _Tp, class _Up, bool> 2620b57cec5SDimitry Andricstruct __throw_with_nested; 2630b57cec5SDimitry Andric 2640b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 2650b57cec5SDimitry Andricstruct __throw_with_nested<_Tp, _Up, true> { 2660b57cec5SDimitry Andric _LIBCPP_NORETURN static inline _LIBCPP_INLINE_VISIBILITY void 2670b57cec5SDimitry Andric __do_throw(_Tp&& __t) 2680b57cec5SDimitry Andric { 269fe6060f1SDimitry Andric throw __nested<_Up>(static_cast<_Tp&&>(__t)); 2700b57cec5SDimitry Andric } 2710b57cec5SDimitry Andric}; 2720b57cec5SDimitry Andric 2730b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 2740b57cec5SDimitry Andricstruct __throw_with_nested<_Tp, _Up, false> { 2750b57cec5SDimitry Andric _LIBCPP_NORETURN static inline _LIBCPP_INLINE_VISIBILITY void 2760b57cec5SDimitry Andric#ifndef _LIBCPP_CXX03_LANG 2770b57cec5SDimitry Andric __do_throw(_Tp&& __t) 2780b57cec5SDimitry Andric#else 2790b57cec5SDimitry Andric __do_throw (_Tp& __t) 2800b57cec5SDimitry Andric#endif // _LIBCPP_CXX03_LANG 2810b57cec5SDimitry Andric { 282fe6060f1SDimitry Andric throw static_cast<_Tp&&>(__t); 2830b57cec5SDimitry Andric } 2840b57cec5SDimitry Andric}; 2850b57cec5SDimitry Andric#endif 2860b57cec5SDimitry Andric 2870b57cec5SDimitry Andrictemplate <class _Tp> 2880b57cec5SDimitry Andric_LIBCPP_NORETURN 2890b57cec5SDimitry Andricvoid 2900b57cec5SDimitry Andricthrow_with_nested(_Tp&& __t) 2910b57cec5SDimitry Andric{ 2920b57cec5SDimitry Andric#ifndef _LIBCPP_NO_EXCEPTIONS 2930b57cec5SDimitry Andric typedef typename decay<_Tp>::type _Up; 2940b57cec5SDimitry Andric static_assert( is_copy_constructible<_Up>::value, "type thrown must be CopyConstructible"); 2950b57cec5SDimitry Andric __throw_with_nested<_Tp, _Up, 2960b57cec5SDimitry Andric is_class<_Up>::value && 2970b57cec5SDimitry Andric !is_base_of<nested_exception, _Up>::value && 2980b57cec5SDimitry Andric !__libcpp_is_final<_Up>::value>:: 299fe6060f1SDimitry Andric __do_throw(static_cast<_Tp&&>(__t)); 3000b57cec5SDimitry Andric#else 3010b57cec5SDimitry Andric ((void)__t); 3020b57cec5SDimitry Andric // FIXME: Make this abort 3030b57cec5SDimitry Andric#endif 3040b57cec5SDimitry Andric} 3050b57cec5SDimitry Andric 3060b57cec5SDimitry Andrictemplate <class _From, class _To> 3070b57cec5SDimitry Andricstruct __can_dynamic_cast : public _LIBCPP_BOOL_CONSTANT( 3080b57cec5SDimitry Andric is_polymorphic<_From>::value && 3090b57cec5SDimitry Andric (!is_base_of<_To, _From>::value || 3100b57cec5SDimitry Andric is_convertible<const _From*, const _To*>::value)) {}; 3110b57cec5SDimitry Andric 3120b57cec5SDimitry Andrictemplate <class _Ep> 3130b57cec5SDimitry Andricinline _LIBCPP_INLINE_VISIBILITY 3140b57cec5SDimitry Andricvoid 3150b57cec5SDimitry Andricrethrow_if_nested(const _Ep& __e, 3160b57cec5SDimitry Andric typename enable_if< __can_dynamic_cast<_Ep, nested_exception>::value>::type* = 0) 3170b57cec5SDimitry Andric{ 3180b57cec5SDimitry Andric const nested_exception* __nep = dynamic_cast<const nested_exception*>(_VSTD::addressof(__e)); 3190b57cec5SDimitry Andric if (__nep) 3200b57cec5SDimitry Andric __nep->rethrow_nested(); 3210b57cec5SDimitry Andric} 3220b57cec5SDimitry Andric 3230b57cec5SDimitry Andrictemplate <class _Ep> 3240b57cec5SDimitry Andricinline _LIBCPP_INLINE_VISIBILITY 3250b57cec5SDimitry Andricvoid 3260b57cec5SDimitry Andricrethrow_if_nested(const _Ep&, 3270b57cec5SDimitry Andric typename enable_if<!__can_dynamic_cast<_Ep, nested_exception>::value>::type* = 0) 3280b57cec5SDimitry Andric{ 3290b57cec5SDimitry Andric} 3300b57cec5SDimitry Andric 3310b57cec5SDimitry Andric} // std 3320b57cec5SDimitry Andric 3330b57cec5SDimitry Andric#endif // _LIBCPP_EXCEPTION 334