17a984708SDavid Chisnall// -*- C++ -*- 27a984708SDavid Chisnall//===-------------------------- exception ---------------------------------===// 37a984708SDavid Chisnall// 47a984708SDavid Chisnall// The LLVM Compiler Infrastructure 57a984708SDavid Chisnall// 67a984708SDavid Chisnall// This file is dual licensed under the MIT and the University of Illinois Open 77a984708SDavid Chisnall// Source Licenses. See LICENSE.TXT for details. 87a984708SDavid Chisnall// 97a984708SDavid Chisnall//===----------------------------------------------------------------------===// 107a984708SDavid Chisnall 117a984708SDavid Chisnall#ifndef _LIBCPP_EXCEPTION 127a984708SDavid Chisnall#define _LIBCPP_EXCEPTION 137a984708SDavid Chisnall 147a984708SDavid Chisnall/* 157a984708SDavid Chisnall exception synopsis 167a984708SDavid Chisnall 177a984708SDavid Chisnallnamespace std 187a984708SDavid Chisnall{ 197a984708SDavid Chisnall 207a984708SDavid Chisnallclass exception 217a984708SDavid Chisnall{ 227a984708SDavid Chisnallpublic: 237a984708SDavid Chisnall exception() noexcept; 247a984708SDavid Chisnall exception(const exception&) noexcept; 257a984708SDavid Chisnall exception& operator=(const exception&) noexcept; 267a984708SDavid Chisnall virtual ~exception() noexcept; 277a984708SDavid Chisnall virtual const char* what() const noexcept; 287a984708SDavid Chisnall}; 297a984708SDavid Chisnall 307a984708SDavid Chisnallclass bad_exception 317a984708SDavid Chisnall : public exception 327a984708SDavid Chisnall{ 337a984708SDavid Chisnallpublic: 347a984708SDavid Chisnall bad_exception() noexcept; 357a984708SDavid Chisnall bad_exception(const bad_exception&) noexcept; 367a984708SDavid Chisnall bad_exception& operator=(const bad_exception&) noexcept; 377a984708SDavid Chisnall virtual ~bad_exception() noexcept; 387a984708SDavid Chisnall virtual const char* what() const noexcept; 397a984708SDavid Chisnall}; 407a984708SDavid Chisnall 417a984708SDavid Chisnalltypedef void (*unexpected_handler)(); 427a984708SDavid Chisnallunexpected_handler set_unexpected(unexpected_handler f ) noexcept; 437a984708SDavid Chisnallunexpected_handler get_unexpected() noexcept; 447a984708SDavid Chisnall[[noreturn]] void unexpected(); 457a984708SDavid Chisnall 467a984708SDavid Chisnalltypedef void (*terminate_handler)(); 477a984708SDavid Chisnallterminate_handler set_terminate(terminate_handler f ) noexcept; 487a984708SDavid Chisnallterminate_handler get_terminate() noexcept; 497a984708SDavid Chisnall[[noreturn]] void terminate() noexcept; 507a984708SDavid Chisnall 517a984708SDavid Chisnallbool uncaught_exception() noexcept; 52854fa44bSDimitry Andricint uncaught_exceptions() noexcept; // C++17 537a984708SDavid Chisnall 547a984708SDavid Chisnalltypedef unspecified exception_ptr; 557a984708SDavid Chisnall 567a984708SDavid Chisnallexception_ptr current_exception() noexcept; 577a984708SDavid Chisnallvoid rethrow_exception [[noreturn]] (exception_ptr p); 587a984708SDavid Chisnalltemplate<class E> exception_ptr make_exception_ptr(E e) noexcept; 597a984708SDavid Chisnall 607a984708SDavid Chisnallclass nested_exception 617a984708SDavid Chisnall{ 627a984708SDavid Chisnallpublic: 637a984708SDavid Chisnall nested_exception() noexcept; 647a984708SDavid Chisnall nested_exception(const nested_exception&) noexcept = default; 657a984708SDavid Chisnall nested_exception& operator=(const nested_exception&) noexcept = default; 667a984708SDavid Chisnall virtual ~nested_exception() = default; 677a984708SDavid Chisnall 687a984708SDavid Chisnall // access functions 697a984708SDavid Chisnall [[noreturn]] void rethrow_nested() const; 707a984708SDavid Chisnall exception_ptr nested_ptr() const noexcept; 717a984708SDavid Chisnall}; 727a984708SDavid Chisnall 737a984708SDavid Chisnalltemplate <class T> [[noreturn]] void throw_with_nested(T&& t); 747a984708SDavid Chisnalltemplate <class E> void rethrow_if_nested(const E& e); 757a984708SDavid Chisnall 767a984708SDavid Chisnall} // std 777a984708SDavid Chisnall 787a984708SDavid Chisnall*/ 797a984708SDavid Chisnall 807a984708SDavid Chisnall#include <__config> 817a984708SDavid Chisnall#include <cstddef> 82067a6c9eSDimitry Andric#include <cstdlib> 83aed8d94eSDimitry Andric#include <type_traits> 84*b5893f02SDimitry Andric#include <version> 857a984708SDavid Chisnall 86b2c7081bSDimitry Andric#if defined(_LIBCPP_ABI_MICROSOFT) && !defined(_LIBCPP_NO_VCRUNTIME) 87540d2a8bSDimitry Andric#include <vcruntime_exception.h> 88540d2a8bSDimitry Andric#endif 89540d2a8bSDimitry Andric 907a984708SDavid Chisnall#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 917a984708SDavid Chisnall#pragma GCC system_header 927a984708SDavid Chisnall#endif 937a984708SDavid Chisnall 947a984708SDavid Chisnallnamespace std // purposefully not using versioning namespace 957a984708SDavid Chisnall{ 967a984708SDavid Chisnall 97b2c7081bSDimitry Andric#if !defined(_LIBCPP_ABI_MICROSOFT) || defined(_LIBCPP_NO_VCRUNTIME) 987a984708SDavid Chisnallclass _LIBCPP_EXCEPTION_ABI exception 997a984708SDavid Chisnall{ 1007a984708SDavid Chisnallpublic: 1017a984708SDavid Chisnall _LIBCPP_INLINE_VISIBILITY exception() _NOEXCEPT {} 1027a984708SDavid Chisnall virtual ~exception() _NOEXCEPT; 1037a984708SDavid Chisnall virtual const char* what() const _NOEXCEPT; 1047a984708SDavid Chisnall}; 1057a984708SDavid Chisnall 1067a984708SDavid Chisnallclass _LIBCPP_EXCEPTION_ABI bad_exception 1077a984708SDavid Chisnall : public exception 1087a984708SDavid Chisnall{ 1097a984708SDavid Chisnallpublic: 1107a984708SDavid Chisnall _LIBCPP_INLINE_VISIBILITY bad_exception() _NOEXCEPT {} 1117a984708SDavid Chisnall virtual ~bad_exception() _NOEXCEPT; 1127a984708SDavid Chisnall virtual const char* what() const _NOEXCEPT; 1137a984708SDavid Chisnall}; 114b2c7081bSDimitry Andric#endif // !_LIBCPP_ABI_MICROSOFT || _LIBCPP_NO_VCRUNTIME 1157a984708SDavid Chisnall 116540d2a8bSDimitry Andric#if _LIBCPP_STD_VER <= 14 \ 117540d2a8bSDimitry Andric || defined(_LIBCPP_ENABLE_CXX17_REMOVED_UNEXPECTED_FUNCTIONS) \ 118540d2a8bSDimitry Andric || defined(_LIBCPP_BUILDING_LIBRARY) 1197a984708SDavid Chisnalltypedef void (*unexpected_handler)(); 1201bf9f7c1SDimitry Andric_LIBCPP_FUNC_VIS unexpected_handler set_unexpected(unexpected_handler) _NOEXCEPT; 1211bf9f7c1SDimitry Andric_LIBCPP_FUNC_VIS unexpected_handler get_unexpected() _NOEXCEPT; 1221bf9f7c1SDimitry Andric_LIBCPP_NORETURN _LIBCPP_FUNC_VIS void unexpected(); 123540d2a8bSDimitry Andric#endif 1247a984708SDavid Chisnall 1257a984708SDavid Chisnalltypedef void (*terminate_handler)(); 1261bf9f7c1SDimitry Andric_LIBCPP_FUNC_VIS terminate_handler set_terminate(terminate_handler) _NOEXCEPT; 1271bf9f7c1SDimitry Andric_LIBCPP_FUNC_VIS terminate_handler get_terminate() _NOEXCEPT; 1281bf9f7c1SDimitry Andric_LIBCPP_NORETURN _LIBCPP_FUNC_VIS void terminate() _NOEXCEPT; 1297a984708SDavid Chisnall 1301bf9f7c1SDimitry Andric_LIBCPP_FUNC_VIS bool uncaught_exception() _NOEXCEPT; 1310f5676f4SDimitry Andric_LIBCPP_FUNC_VIS _LIBCPP_AVAILABILITY_UNCAUGHT_EXCEPTIONS int uncaught_exceptions() _NOEXCEPT; 1327a984708SDavid Chisnall 1331bf9f7c1SDimitry Andricclass _LIBCPP_TYPE_VIS exception_ptr; 1347a984708SDavid Chisnall 1354f7ab58eSDimitry Andric_LIBCPP_FUNC_VIS exception_ptr current_exception() _NOEXCEPT; 1364f7ab58eSDimitry Andric_LIBCPP_NORETURN _LIBCPP_FUNC_VIS void rethrow_exception(exception_ptr); 1377a984708SDavid Chisnall 1380f5676f4SDimitry Andric#ifndef _LIBCPP_ABI_MICROSOFT 1390f5676f4SDimitry Andric 1401bf9f7c1SDimitry Andricclass _LIBCPP_TYPE_VIS exception_ptr 1417a984708SDavid Chisnall{ 1427a984708SDavid Chisnall void* __ptr_; 1437a984708SDavid Chisnallpublic: 1447a984708SDavid Chisnall _LIBCPP_INLINE_VISIBILITY exception_ptr() _NOEXCEPT : __ptr_() {} 1457a984708SDavid Chisnall _LIBCPP_INLINE_VISIBILITY exception_ptr(nullptr_t) _NOEXCEPT : __ptr_() {} 1460f5676f4SDimitry Andric 1477a984708SDavid Chisnall exception_ptr(const exception_ptr&) _NOEXCEPT; 1487a984708SDavid Chisnall exception_ptr& operator=(const exception_ptr&) _NOEXCEPT; 1497a984708SDavid Chisnall ~exception_ptr() _NOEXCEPT; 1507a984708SDavid Chisnall 1510f5676f4SDimitry Andric _LIBCPP_INLINE_VISIBILITY _LIBCPP_EXPLICIT operator bool() const _NOEXCEPT 1520f5676f4SDimitry Andric {return __ptr_ != nullptr;} 1537a984708SDavid Chisnall 1547a984708SDavid Chisnall friend _LIBCPP_INLINE_VISIBILITY 1557a984708SDavid Chisnall bool operator==(const exception_ptr& __x, const exception_ptr& __y) _NOEXCEPT 1567a984708SDavid Chisnall {return __x.__ptr_ == __y.__ptr_;} 1570f5676f4SDimitry Andric 1587a984708SDavid Chisnall friend _LIBCPP_INLINE_VISIBILITY 1597a984708SDavid Chisnall bool operator!=(const exception_ptr& __x, const exception_ptr& __y) _NOEXCEPT 1607a984708SDavid Chisnall {return !(__x == __y);} 1617a984708SDavid Chisnall 1624f7ab58eSDimitry Andric friend _LIBCPP_FUNC_VIS exception_ptr current_exception() _NOEXCEPT; 1634f7ab58eSDimitry Andric friend _LIBCPP_FUNC_VIS void rethrow_exception(exception_ptr); 1647a984708SDavid Chisnall}; 1657a984708SDavid Chisnall 16694e3ee44SDavid Chisnalltemplate<class _Ep> 167*b5893f02SDimitry Andric_LIBCPP_INLINE_VISIBILITY exception_ptr 16894e3ee44SDavid Chisnallmake_exception_ptr(_Ep __e) _NOEXCEPT 1697a984708SDavid Chisnall{ 1707a984708SDavid Chisnall#ifndef _LIBCPP_NO_EXCEPTIONS 1717a984708SDavid Chisnall try 1727a984708SDavid Chisnall { 1737a984708SDavid Chisnall throw __e; 1747a984708SDavid Chisnall } 1757a984708SDavid Chisnall catch (...) 1767a984708SDavid Chisnall { 1777a984708SDavid Chisnall return current_exception(); 1787a984708SDavid Chisnall } 179aed8d94eSDimitry Andric#else 180aed8d94eSDimitry Andric ((void)__e); 181aed8d94eSDimitry Andric _VSTD::abort(); 182aed8d94eSDimitry Andric#endif 1837a984708SDavid Chisnall} 1847a984708SDavid Chisnall 1850f5676f4SDimitry Andric#else // _LIBCPP_ABI_MICROSOFT 1860f5676f4SDimitry Andric 1870f5676f4SDimitry Andricclass _LIBCPP_TYPE_VIS exception_ptr 1880f5676f4SDimitry Andric{ 1890f5676f4SDimitry Andric#if defined(__clang__) 1900f5676f4SDimitry Andric#pragma clang diagnostic push 1910f5676f4SDimitry Andric#pragma clang diagnostic ignored "-Wunused-private-field" 1920f5676f4SDimitry Andric#endif 1930f5676f4SDimitry Andric void* __ptr1_; 1940f5676f4SDimitry Andric void* __ptr2_; 1950f5676f4SDimitry Andric#if defined(__clang__) 1960f5676f4SDimitry Andric#pragma clang diagnostic pop 1970f5676f4SDimitry Andric#endif 1980f5676f4SDimitry Andricpublic: 1990f5676f4SDimitry Andric exception_ptr() _NOEXCEPT; 2000f5676f4SDimitry Andric exception_ptr(nullptr_t) _NOEXCEPT; 2010f5676f4SDimitry Andric exception_ptr(const exception_ptr& __other) _NOEXCEPT; 2020f5676f4SDimitry Andric exception_ptr& operator=(const exception_ptr& __other) _NOEXCEPT; 2030f5676f4SDimitry Andric exception_ptr& operator=(nullptr_t) _NOEXCEPT; 2040f5676f4SDimitry Andric ~exception_ptr() _NOEXCEPT; 2050f5676f4SDimitry Andric _LIBCPP_EXPLICIT operator bool() const _NOEXCEPT; 2060f5676f4SDimitry Andric}; 2070f5676f4SDimitry Andric 2080f5676f4SDimitry Andric_LIBCPP_FUNC_VIS 2090f5676f4SDimitry Andricbool operator==(const exception_ptr& __x, const exception_ptr& __y) _NOEXCEPT; 2100f5676f4SDimitry Andric 2110f5676f4SDimitry Andricinline _LIBCPP_INLINE_VISIBILITY 2120f5676f4SDimitry Andricbool operator!=(const exception_ptr& __x, const exception_ptr& __y) _NOEXCEPT 2130f5676f4SDimitry Andric {return !(__x == __y);} 2140f5676f4SDimitry Andric 2150f5676f4SDimitry Andric_LIBCPP_FUNC_VIS void swap(exception_ptr&, exception_ptr&) _NOEXCEPT; 2160f5676f4SDimitry Andric 2170f5676f4SDimitry Andric_LIBCPP_FUNC_VIS exception_ptr __copy_exception_ptr(void *__except, const void* __ptr); 2180f5676f4SDimitry Andric_LIBCPP_FUNC_VIS exception_ptr current_exception() _NOEXCEPT; 2190f5676f4SDimitry Andric_LIBCPP_NORETURN _LIBCPP_FUNC_VIS void rethrow_exception(exception_ptr p); 2200f5676f4SDimitry Andric 2210f5676f4SDimitry Andric// This is a built-in template function which automagically extracts the required 2220f5676f4SDimitry Andric// information. 2230f5676f4SDimitry Andrictemplate <class _E> void *__GetExceptionInfo(_E); 2240f5676f4SDimitry Andric 2250f5676f4SDimitry Andrictemplate<class _Ep> 226*b5893f02SDimitry Andric_LIBCPP_INLINE_VISIBILITY exception_ptr 2270f5676f4SDimitry Andricmake_exception_ptr(_Ep __e) _NOEXCEPT 2280f5676f4SDimitry Andric{ 2290f5676f4SDimitry Andric return __copy_exception_ptr(_VSTD::addressof(__e), __GetExceptionInfo(__e)); 2300f5676f4SDimitry Andric} 2310f5676f4SDimitry Andric 2320f5676f4SDimitry Andric#endif // _LIBCPP_ABI_MICROSOFT 2337a984708SDavid Chisnall// nested_exception 2347a984708SDavid Chisnall 2357a984708SDavid Chisnallclass _LIBCPP_EXCEPTION_ABI nested_exception 2367a984708SDavid Chisnall{ 2377a984708SDavid Chisnall exception_ptr __ptr_; 2387a984708SDavid Chisnallpublic: 2397a984708SDavid Chisnall nested_exception() _NOEXCEPT; 2407a984708SDavid Chisnall// nested_exception(const nested_exception&) noexcept = default; 2417a984708SDavid Chisnall// nested_exception& operator=(const nested_exception&) noexcept = default; 2427a984708SDavid Chisnall virtual ~nested_exception() _NOEXCEPT; 2437a984708SDavid Chisnall 2447a984708SDavid Chisnall // access functions 245936e9439SDimitry Andric _LIBCPP_NORETURN void rethrow_nested() const; 2467a984708SDavid Chisnall _LIBCPP_INLINE_VISIBILITY exception_ptr nested_ptr() const _NOEXCEPT {return __ptr_;} 2477a984708SDavid Chisnall}; 2487a984708SDavid Chisnall 2497a984708SDavid Chisnalltemplate <class _Tp> 2507a984708SDavid Chisnallstruct __nested 2517a984708SDavid Chisnall : public _Tp, 2527a984708SDavid Chisnall public nested_exception 2537a984708SDavid Chisnall{ 2547a984708SDavid Chisnall _LIBCPP_INLINE_VISIBILITY explicit __nested(const _Tp& __t) : _Tp(__t) {} 2557a984708SDavid Chisnall}; 2567a984708SDavid Chisnall 2577a984708SDavid Chisnall#ifndef _LIBCPP_NO_EXCEPTIONS 258540d2a8bSDimitry Andrictemplate <class _Tp, class _Up, bool> 259540d2a8bSDimitry Andricstruct __throw_with_nested; 260540d2a8bSDimitry Andric 261540d2a8bSDimitry Andrictemplate <class _Tp, class _Up> 262540d2a8bSDimitry Andricstruct __throw_with_nested<_Tp, _Up, true> { 2634ba319b5SDimitry Andric _LIBCPP_NORETURN static inline _LIBCPP_INLINE_VISIBILITY void 264540d2a8bSDimitry Andric#ifndef _LIBCPP_CXX03_LANG 265540d2a8bSDimitry Andric __do_throw(_Tp&& __t) 266aed8d94eSDimitry Andric#else 267540d2a8bSDimitry Andric __do_throw (_Tp& __t) 268540d2a8bSDimitry Andric#endif // _LIBCPP_CXX03_LANG 269540d2a8bSDimitry Andric { 270540d2a8bSDimitry Andric throw __nested<_Up>(_VSTD::forward<_Tp>(__t)); 2717a984708SDavid Chisnall } 272540d2a8bSDimitry Andric}; 273540d2a8bSDimitry Andric 274540d2a8bSDimitry Andrictemplate <class _Tp, class _Up> 275540d2a8bSDimitry Andricstruct __throw_with_nested<_Tp, _Up, false> { 2764ba319b5SDimitry Andric _LIBCPP_NORETURN static inline _LIBCPP_INLINE_VISIBILITY void 277540d2a8bSDimitry Andric#ifndef _LIBCPP_CXX03_LANG 278540d2a8bSDimitry Andric __do_throw(_Tp&& __t) 279540d2a8bSDimitry Andric#else 280540d2a8bSDimitry Andric __do_throw (_Tp& __t) 281540d2a8bSDimitry Andric#endif // _LIBCPP_CXX03_LANG 282540d2a8bSDimitry Andric { 283540d2a8bSDimitry Andric throw _VSTD::forward<_Tp>(__t); 284540d2a8bSDimitry Andric } 285540d2a8bSDimitry Andric}; 286540d2a8bSDimitry Andric#endif 2877a984708SDavid Chisnall 2887a984708SDavid Chisnalltemplate <class _Tp> 289936e9439SDimitry Andric_LIBCPP_NORETURN 2907a984708SDavid Chisnallvoid 291540d2a8bSDimitry Andric#ifndef _LIBCPP_CXX03_LANG 292540d2a8bSDimitry Andricthrow_with_nested(_Tp&& __t) 293540d2a8bSDimitry Andric#else 294540d2a8bSDimitry Andricthrow_with_nested (_Tp& __t) 295540d2a8bSDimitry Andric#endif // _LIBCPP_CXX03_LANG 2967a984708SDavid Chisnall{ 2977a984708SDavid Chisnall#ifndef _LIBCPP_NO_EXCEPTIONS 298540d2a8bSDimitry Andric typedef typename decay<_Tp>::type _Up; 299540d2a8bSDimitry Andric static_assert( is_copy_constructible<_Up>::value, "type thrown must be CopyConstructible"); 300540d2a8bSDimitry Andric __throw_with_nested<_Tp, _Up, 301540d2a8bSDimitry Andric is_class<_Up>::value && 302540d2a8bSDimitry Andric !is_base_of<nested_exception, _Up>::value && 303540d2a8bSDimitry Andric !__libcpp_is_final<_Up>::value>:: 304540d2a8bSDimitry Andric __do_throw(_VSTD::forward<_Tp>(__t)); 305aed8d94eSDimitry Andric#else 306aed8d94eSDimitry Andric ((void)__t); 307aed8d94eSDimitry Andric // FIXME: Make this abort 3087a984708SDavid Chisnall#endif 3097a984708SDavid Chisnall} 3107a984708SDavid Chisnall 311540d2a8bSDimitry Andrictemplate <class _From, class _To> 312540d2a8bSDimitry Andricstruct __can_dynamic_cast : public _LIBCPP_BOOL_CONSTANT( 313540d2a8bSDimitry Andric is_polymorphic<_From>::value && 314540d2a8bSDimitry Andric (!is_base_of<_To, _From>::value || 315540d2a8bSDimitry Andric is_convertible<const _From*, const _To*>::value)) {}; 316540d2a8bSDimitry Andric 31794e3ee44SDavid Chisnalltemplate <class _Ep> 3187a984708SDavid Chisnallinline _LIBCPP_INLINE_VISIBILITY 3197a984708SDavid Chisnallvoid 320540d2a8bSDimitry Andricrethrow_if_nested(const _Ep& __e, 321540d2a8bSDimitry Andric typename enable_if< __can_dynamic_cast<_Ep, nested_exception>::value>::type* = 0) 3227a984708SDavid Chisnall{ 3239729cf09SDimitry Andric const nested_exception* __nep = dynamic_cast<const nested_exception*>(_VSTD::addressof(__e)); 3247a984708SDavid Chisnall if (__nep) 3257a984708SDavid Chisnall __nep->rethrow_nested(); 3267a984708SDavid Chisnall} 3277a984708SDavid Chisnall 32894e3ee44SDavid Chisnalltemplate <class _Ep> 3297a984708SDavid Chisnallinline _LIBCPP_INLINE_VISIBILITY 3307a984708SDavid Chisnallvoid 331540d2a8bSDimitry Andricrethrow_if_nested(const _Ep&, 332540d2a8bSDimitry Andric typename enable_if<!__can_dynamic_cast<_Ep, nested_exception>::value>::type* = 0) 3337a984708SDavid Chisnall{ 3347a984708SDavid Chisnall} 3357a984708SDavid Chisnall 3367a984708SDavid Chisnall} // std 3377a984708SDavid Chisnall 3387a984708SDavid Chisnall#endif // _LIBCPP_EXCEPTION 339