1*0b57cec5SDimitry Andric// -*- C++ -*- 2*0b57cec5SDimitry Andric//===-------------------------- exception ---------------------------------===// 3*0b57cec5SDimitry Andric// 4*0b57cec5SDimitry Andric// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5*0b57cec5SDimitry Andric// See https://llvm.org/LICENSE.txt for license information. 6*0b57cec5SDimitry Andric// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7*0b57cec5SDimitry Andric// 8*0b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 9*0b57cec5SDimitry Andric 10*0b57cec5SDimitry Andric#ifndef _LIBCPP_EXCEPTION 11*0b57cec5SDimitry Andric#define _LIBCPP_EXCEPTION 12*0b57cec5SDimitry Andric 13*0b57cec5SDimitry Andric/* 14*0b57cec5SDimitry Andric exception synopsis 15*0b57cec5SDimitry Andric 16*0b57cec5SDimitry Andricnamespace std 17*0b57cec5SDimitry Andric{ 18*0b57cec5SDimitry Andric 19*0b57cec5SDimitry Andricclass exception 20*0b57cec5SDimitry Andric{ 21*0b57cec5SDimitry Andricpublic: 22*0b57cec5SDimitry Andric exception() noexcept; 23*0b57cec5SDimitry Andric exception(const exception&) noexcept; 24*0b57cec5SDimitry Andric exception& operator=(const exception&) noexcept; 25*0b57cec5SDimitry Andric virtual ~exception() noexcept; 26*0b57cec5SDimitry Andric virtual const char* what() const noexcept; 27*0b57cec5SDimitry Andric}; 28*0b57cec5SDimitry Andric 29*0b57cec5SDimitry Andricclass bad_exception 30*0b57cec5SDimitry Andric : public exception 31*0b57cec5SDimitry Andric{ 32*0b57cec5SDimitry Andricpublic: 33*0b57cec5SDimitry Andric bad_exception() noexcept; 34*0b57cec5SDimitry Andric bad_exception(const bad_exception&) noexcept; 35*0b57cec5SDimitry Andric bad_exception& operator=(const bad_exception&) noexcept; 36*0b57cec5SDimitry Andric virtual ~bad_exception() noexcept; 37*0b57cec5SDimitry Andric virtual const char* what() const noexcept; 38*0b57cec5SDimitry Andric}; 39*0b57cec5SDimitry Andric 40*0b57cec5SDimitry Andrictypedef void (*unexpected_handler)(); 41*0b57cec5SDimitry Andricunexpected_handler set_unexpected(unexpected_handler f ) noexcept; 42*0b57cec5SDimitry Andricunexpected_handler get_unexpected() noexcept; 43*0b57cec5SDimitry Andric[[noreturn]] void unexpected(); 44*0b57cec5SDimitry Andric 45*0b57cec5SDimitry Andrictypedef void (*terminate_handler)(); 46*0b57cec5SDimitry Andricterminate_handler set_terminate(terminate_handler f ) noexcept; 47*0b57cec5SDimitry Andricterminate_handler get_terminate() noexcept; 48*0b57cec5SDimitry Andric[[noreturn]] void terminate() noexcept; 49*0b57cec5SDimitry Andric 50*0b57cec5SDimitry Andricbool uncaught_exception() noexcept; 51*0b57cec5SDimitry Andricint uncaught_exceptions() noexcept; // C++17 52*0b57cec5SDimitry Andric 53*0b57cec5SDimitry Andrictypedef unspecified exception_ptr; 54*0b57cec5SDimitry Andric 55*0b57cec5SDimitry Andricexception_ptr current_exception() noexcept; 56*0b57cec5SDimitry Andricvoid rethrow_exception [[noreturn]] (exception_ptr p); 57*0b57cec5SDimitry Andrictemplate<class E> exception_ptr make_exception_ptr(E e) noexcept; 58*0b57cec5SDimitry Andric 59*0b57cec5SDimitry Andricclass nested_exception 60*0b57cec5SDimitry Andric{ 61*0b57cec5SDimitry Andricpublic: 62*0b57cec5SDimitry Andric nested_exception() noexcept; 63*0b57cec5SDimitry Andric nested_exception(const nested_exception&) noexcept = default; 64*0b57cec5SDimitry Andric nested_exception& operator=(const nested_exception&) noexcept = default; 65*0b57cec5SDimitry Andric virtual ~nested_exception() = default; 66*0b57cec5SDimitry Andric 67*0b57cec5SDimitry Andric // access functions 68*0b57cec5SDimitry Andric [[noreturn]] void rethrow_nested() const; 69*0b57cec5SDimitry Andric exception_ptr nested_ptr() const noexcept; 70*0b57cec5SDimitry Andric}; 71*0b57cec5SDimitry Andric 72*0b57cec5SDimitry Andrictemplate <class T> [[noreturn]] void throw_with_nested(T&& t); 73*0b57cec5SDimitry Andrictemplate <class E> void rethrow_if_nested(const E& e); 74*0b57cec5SDimitry Andric 75*0b57cec5SDimitry Andric} // std 76*0b57cec5SDimitry Andric 77*0b57cec5SDimitry Andric*/ 78*0b57cec5SDimitry Andric 79*0b57cec5SDimitry Andric#include <__config> 80*0b57cec5SDimitry Andric#include <cstddef> 81*0b57cec5SDimitry Andric#include <cstdlib> 82*0b57cec5SDimitry Andric#include <type_traits> 83*0b57cec5SDimitry Andric#include <version> 84*0b57cec5SDimitry Andric 85*0b57cec5SDimitry Andric#if defined(_LIBCPP_ABI_VCRUNTIME) 86*0b57cec5SDimitry Andric#include <vcruntime_exception.h> 87*0b57cec5SDimitry Andric#endif 88*0b57cec5SDimitry Andric 89*0b57cec5SDimitry Andric#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 90*0b57cec5SDimitry Andric#pragma GCC system_header 91*0b57cec5SDimitry Andric#endif 92*0b57cec5SDimitry Andric 93*0b57cec5SDimitry Andricnamespace std // purposefully not using versioning namespace 94*0b57cec5SDimitry Andric{ 95*0b57cec5SDimitry Andric 96*0b57cec5SDimitry Andric#if !defined(_LIBCPP_ABI_VCRUNTIME) 97*0b57cec5SDimitry Andricclass _LIBCPP_EXCEPTION_ABI exception 98*0b57cec5SDimitry Andric{ 99*0b57cec5SDimitry Andricpublic: 100*0b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY exception() _NOEXCEPT {} 101*0b57cec5SDimitry Andric virtual ~exception() _NOEXCEPT; 102*0b57cec5SDimitry Andric virtual const char* what() const _NOEXCEPT; 103*0b57cec5SDimitry Andric}; 104*0b57cec5SDimitry Andric 105*0b57cec5SDimitry Andricclass _LIBCPP_EXCEPTION_ABI bad_exception 106*0b57cec5SDimitry Andric : public exception 107*0b57cec5SDimitry Andric{ 108*0b57cec5SDimitry Andricpublic: 109*0b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY bad_exception() _NOEXCEPT {} 110*0b57cec5SDimitry Andric virtual ~bad_exception() _NOEXCEPT; 111*0b57cec5SDimitry Andric virtual const char* what() const _NOEXCEPT; 112*0b57cec5SDimitry Andric}; 113*0b57cec5SDimitry Andric#endif // !_LIBCPP_ABI_VCRUNTIME 114*0b57cec5SDimitry Andric 115*0b57cec5SDimitry Andric#if _LIBCPP_STD_VER <= 14 \ 116*0b57cec5SDimitry Andric || defined(_LIBCPP_ENABLE_CXX17_REMOVED_UNEXPECTED_FUNCTIONS) \ 117*0b57cec5SDimitry Andric || defined(_LIBCPP_BUILDING_LIBRARY) 118*0b57cec5SDimitry Andrictypedef void (*unexpected_handler)(); 119*0b57cec5SDimitry Andric_LIBCPP_FUNC_VIS unexpected_handler set_unexpected(unexpected_handler) _NOEXCEPT; 120*0b57cec5SDimitry Andric_LIBCPP_FUNC_VIS unexpected_handler get_unexpected() _NOEXCEPT; 121*0b57cec5SDimitry Andric_LIBCPP_NORETURN _LIBCPP_FUNC_VIS void unexpected(); 122*0b57cec5SDimitry Andric#endif 123*0b57cec5SDimitry Andric 124*0b57cec5SDimitry Andrictypedef void (*terminate_handler)(); 125*0b57cec5SDimitry Andric_LIBCPP_FUNC_VIS terminate_handler set_terminate(terminate_handler) _NOEXCEPT; 126*0b57cec5SDimitry Andric_LIBCPP_FUNC_VIS terminate_handler get_terminate() _NOEXCEPT; 127*0b57cec5SDimitry Andric_LIBCPP_NORETURN _LIBCPP_FUNC_VIS void terminate() _NOEXCEPT; 128*0b57cec5SDimitry Andric 129*0b57cec5SDimitry Andric_LIBCPP_FUNC_VIS bool uncaught_exception() _NOEXCEPT; 130*0b57cec5SDimitry Andric_LIBCPP_FUNC_VIS _LIBCPP_AVAILABILITY_UNCAUGHT_EXCEPTIONS int uncaught_exceptions() _NOEXCEPT; 131*0b57cec5SDimitry Andric 132*0b57cec5SDimitry Andricclass _LIBCPP_TYPE_VIS exception_ptr; 133*0b57cec5SDimitry Andric 134*0b57cec5SDimitry Andric_LIBCPP_FUNC_VIS exception_ptr current_exception() _NOEXCEPT; 135*0b57cec5SDimitry Andric_LIBCPP_NORETURN _LIBCPP_FUNC_VIS void rethrow_exception(exception_ptr); 136*0b57cec5SDimitry Andric 137*0b57cec5SDimitry Andric#ifndef _LIBCPP_ABI_MICROSOFT 138*0b57cec5SDimitry Andric 139*0b57cec5SDimitry Andricclass _LIBCPP_TYPE_VIS exception_ptr 140*0b57cec5SDimitry Andric{ 141*0b57cec5SDimitry Andric void* __ptr_; 142*0b57cec5SDimitry Andricpublic: 143*0b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY exception_ptr() _NOEXCEPT : __ptr_() {} 144*0b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY exception_ptr(nullptr_t) _NOEXCEPT : __ptr_() {} 145*0b57cec5SDimitry Andric 146*0b57cec5SDimitry Andric exception_ptr(const exception_ptr&) _NOEXCEPT; 147*0b57cec5SDimitry Andric exception_ptr& operator=(const exception_ptr&) _NOEXCEPT; 148*0b57cec5SDimitry Andric ~exception_ptr() _NOEXCEPT; 149*0b57cec5SDimitry Andric 150*0b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY _LIBCPP_EXPLICIT operator bool() const _NOEXCEPT 151*0b57cec5SDimitry Andric {return __ptr_ != nullptr;} 152*0b57cec5SDimitry Andric 153*0b57cec5SDimitry Andric friend _LIBCPP_INLINE_VISIBILITY 154*0b57cec5SDimitry Andric bool operator==(const exception_ptr& __x, const exception_ptr& __y) _NOEXCEPT 155*0b57cec5SDimitry Andric {return __x.__ptr_ == __y.__ptr_;} 156*0b57cec5SDimitry Andric 157*0b57cec5SDimitry Andric friend _LIBCPP_INLINE_VISIBILITY 158*0b57cec5SDimitry Andric bool operator!=(const exception_ptr& __x, const exception_ptr& __y) _NOEXCEPT 159*0b57cec5SDimitry Andric {return !(__x == __y);} 160*0b57cec5SDimitry Andric 161*0b57cec5SDimitry Andric friend _LIBCPP_FUNC_VIS exception_ptr current_exception() _NOEXCEPT; 162*0b57cec5SDimitry Andric friend _LIBCPP_FUNC_VIS void rethrow_exception(exception_ptr); 163*0b57cec5SDimitry Andric}; 164*0b57cec5SDimitry Andric 165*0b57cec5SDimitry Andrictemplate<class _Ep> 166*0b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY exception_ptr 167*0b57cec5SDimitry Andricmake_exception_ptr(_Ep __e) _NOEXCEPT 168*0b57cec5SDimitry Andric{ 169*0b57cec5SDimitry Andric#ifndef _LIBCPP_NO_EXCEPTIONS 170*0b57cec5SDimitry Andric try 171*0b57cec5SDimitry Andric { 172*0b57cec5SDimitry Andric throw __e; 173*0b57cec5SDimitry Andric } 174*0b57cec5SDimitry Andric catch (...) 175*0b57cec5SDimitry Andric { 176*0b57cec5SDimitry Andric return current_exception(); 177*0b57cec5SDimitry Andric } 178*0b57cec5SDimitry Andric#else 179*0b57cec5SDimitry Andric ((void)__e); 180*0b57cec5SDimitry Andric _VSTD::abort(); 181*0b57cec5SDimitry Andric#endif 182*0b57cec5SDimitry Andric} 183*0b57cec5SDimitry Andric 184*0b57cec5SDimitry Andric#else // _LIBCPP_ABI_MICROSOFT 185*0b57cec5SDimitry Andric 186*0b57cec5SDimitry Andricclass _LIBCPP_TYPE_VIS exception_ptr 187*0b57cec5SDimitry Andric{ 188*0b57cec5SDimitry Andric#if defined(__clang__) 189*0b57cec5SDimitry Andric#pragma clang diagnostic push 190*0b57cec5SDimitry Andric#pragma clang diagnostic ignored "-Wunused-private-field" 191*0b57cec5SDimitry Andric#endif 192*0b57cec5SDimitry Andric void* __ptr1_; 193*0b57cec5SDimitry Andric void* __ptr2_; 194*0b57cec5SDimitry Andric#if defined(__clang__) 195*0b57cec5SDimitry Andric#pragma clang diagnostic pop 196*0b57cec5SDimitry Andric#endif 197*0b57cec5SDimitry Andricpublic: 198*0b57cec5SDimitry Andric exception_ptr() _NOEXCEPT; 199*0b57cec5SDimitry Andric exception_ptr(nullptr_t) _NOEXCEPT; 200*0b57cec5SDimitry Andric exception_ptr(const exception_ptr& __other) _NOEXCEPT; 201*0b57cec5SDimitry Andric exception_ptr& operator=(const exception_ptr& __other) _NOEXCEPT; 202*0b57cec5SDimitry Andric exception_ptr& operator=(nullptr_t) _NOEXCEPT; 203*0b57cec5SDimitry Andric ~exception_ptr() _NOEXCEPT; 204*0b57cec5SDimitry Andric _LIBCPP_EXPLICIT operator bool() const _NOEXCEPT; 205*0b57cec5SDimitry Andric}; 206*0b57cec5SDimitry Andric 207*0b57cec5SDimitry Andric_LIBCPP_FUNC_VIS 208*0b57cec5SDimitry Andricbool operator==(const exception_ptr& __x, const exception_ptr& __y) _NOEXCEPT; 209*0b57cec5SDimitry Andric 210*0b57cec5SDimitry Andricinline _LIBCPP_INLINE_VISIBILITY 211*0b57cec5SDimitry Andricbool operator!=(const exception_ptr& __x, const exception_ptr& __y) _NOEXCEPT 212*0b57cec5SDimitry Andric {return !(__x == __y);} 213*0b57cec5SDimitry Andric 214*0b57cec5SDimitry Andric_LIBCPP_FUNC_VIS void swap(exception_ptr&, exception_ptr&) _NOEXCEPT; 215*0b57cec5SDimitry Andric 216*0b57cec5SDimitry Andric_LIBCPP_FUNC_VIS exception_ptr __copy_exception_ptr(void *__except, const void* __ptr); 217*0b57cec5SDimitry Andric_LIBCPP_FUNC_VIS exception_ptr current_exception() _NOEXCEPT; 218*0b57cec5SDimitry Andric_LIBCPP_NORETURN _LIBCPP_FUNC_VIS void rethrow_exception(exception_ptr p); 219*0b57cec5SDimitry Andric 220*0b57cec5SDimitry Andric// This is a built-in template function which automagically extracts the required 221*0b57cec5SDimitry Andric// information. 222*0b57cec5SDimitry Andrictemplate <class _E> void *__GetExceptionInfo(_E); 223*0b57cec5SDimitry Andric 224*0b57cec5SDimitry Andrictemplate<class _Ep> 225*0b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY exception_ptr 226*0b57cec5SDimitry Andricmake_exception_ptr(_Ep __e) _NOEXCEPT 227*0b57cec5SDimitry Andric{ 228*0b57cec5SDimitry Andric return __copy_exception_ptr(_VSTD::addressof(__e), __GetExceptionInfo(__e)); 229*0b57cec5SDimitry Andric} 230*0b57cec5SDimitry Andric 231*0b57cec5SDimitry Andric#endif // _LIBCPP_ABI_MICROSOFT 232*0b57cec5SDimitry Andric// nested_exception 233*0b57cec5SDimitry Andric 234*0b57cec5SDimitry Andricclass _LIBCPP_EXCEPTION_ABI nested_exception 235*0b57cec5SDimitry Andric{ 236*0b57cec5SDimitry Andric exception_ptr __ptr_; 237*0b57cec5SDimitry Andricpublic: 238*0b57cec5SDimitry Andric nested_exception() _NOEXCEPT; 239*0b57cec5SDimitry Andric// nested_exception(const nested_exception&) noexcept = default; 240*0b57cec5SDimitry Andric// nested_exception& operator=(const nested_exception&) noexcept = default; 241*0b57cec5SDimitry Andric virtual ~nested_exception() _NOEXCEPT; 242*0b57cec5SDimitry Andric 243*0b57cec5SDimitry Andric // access functions 244*0b57cec5SDimitry Andric _LIBCPP_NORETURN void rethrow_nested() const; 245*0b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY exception_ptr nested_ptr() const _NOEXCEPT {return __ptr_;} 246*0b57cec5SDimitry Andric}; 247*0b57cec5SDimitry Andric 248*0b57cec5SDimitry Andrictemplate <class _Tp> 249*0b57cec5SDimitry Andricstruct __nested 250*0b57cec5SDimitry Andric : public _Tp, 251*0b57cec5SDimitry Andric public nested_exception 252*0b57cec5SDimitry Andric{ 253*0b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY explicit __nested(const _Tp& __t) : _Tp(__t) {} 254*0b57cec5SDimitry Andric}; 255*0b57cec5SDimitry Andric 256*0b57cec5SDimitry Andric#ifndef _LIBCPP_NO_EXCEPTIONS 257*0b57cec5SDimitry Andrictemplate <class _Tp, class _Up, bool> 258*0b57cec5SDimitry Andricstruct __throw_with_nested; 259*0b57cec5SDimitry Andric 260*0b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 261*0b57cec5SDimitry Andricstruct __throw_with_nested<_Tp, _Up, true> { 262*0b57cec5SDimitry Andric _LIBCPP_NORETURN static inline _LIBCPP_INLINE_VISIBILITY void 263*0b57cec5SDimitry Andric __do_throw(_Tp&& __t) 264*0b57cec5SDimitry Andric { 265*0b57cec5SDimitry Andric throw __nested<_Up>(_VSTD::forward<_Tp>(__t)); 266*0b57cec5SDimitry Andric } 267*0b57cec5SDimitry Andric}; 268*0b57cec5SDimitry Andric 269*0b57cec5SDimitry Andrictemplate <class _Tp, class _Up> 270*0b57cec5SDimitry Andricstruct __throw_with_nested<_Tp, _Up, false> { 271*0b57cec5SDimitry Andric _LIBCPP_NORETURN static inline _LIBCPP_INLINE_VISIBILITY void 272*0b57cec5SDimitry Andric#ifndef _LIBCPP_CXX03_LANG 273*0b57cec5SDimitry Andric __do_throw(_Tp&& __t) 274*0b57cec5SDimitry Andric#else 275*0b57cec5SDimitry Andric __do_throw (_Tp& __t) 276*0b57cec5SDimitry Andric#endif // _LIBCPP_CXX03_LANG 277*0b57cec5SDimitry Andric { 278*0b57cec5SDimitry Andric throw _VSTD::forward<_Tp>(__t); 279*0b57cec5SDimitry Andric } 280*0b57cec5SDimitry Andric}; 281*0b57cec5SDimitry Andric#endif 282*0b57cec5SDimitry Andric 283*0b57cec5SDimitry Andrictemplate <class _Tp> 284*0b57cec5SDimitry Andric_LIBCPP_NORETURN 285*0b57cec5SDimitry Andricvoid 286*0b57cec5SDimitry Andricthrow_with_nested(_Tp&& __t) 287*0b57cec5SDimitry Andric{ 288*0b57cec5SDimitry Andric#ifndef _LIBCPP_NO_EXCEPTIONS 289*0b57cec5SDimitry Andric typedef typename decay<_Tp>::type _Up; 290*0b57cec5SDimitry Andric static_assert( is_copy_constructible<_Up>::value, "type thrown must be CopyConstructible"); 291*0b57cec5SDimitry Andric __throw_with_nested<_Tp, _Up, 292*0b57cec5SDimitry Andric is_class<_Up>::value && 293*0b57cec5SDimitry Andric !is_base_of<nested_exception, _Up>::value && 294*0b57cec5SDimitry Andric !__libcpp_is_final<_Up>::value>:: 295*0b57cec5SDimitry Andric __do_throw(_VSTD::forward<_Tp>(__t)); 296*0b57cec5SDimitry Andric#else 297*0b57cec5SDimitry Andric ((void)__t); 298*0b57cec5SDimitry Andric // FIXME: Make this abort 299*0b57cec5SDimitry Andric#endif 300*0b57cec5SDimitry Andric} 301*0b57cec5SDimitry Andric 302*0b57cec5SDimitry Andrictemplate <class _From, class _To> 303*0b57cec5SDimitry Andricstruct __can_dynamic_cast : public _LIBCPP_BOOL_CONSTANT( 304*0b57cec5SDimitry Andric is_polymorphic<_From>::value && 305*0b57cec5SDimitry Andric (!is_base_of<_To, _From>::value || 306*0b57cec5SDimitry Andric is_convertible<const _From*, const _To*>::value)) {}; 307*0b57cec5SDimitry Andric 308*0b57cec5SDimitry Andrictemplate <class _Ep> 309*0b57cec5SDimitry Andricinline _LIBCPP_INLINE_VISIBILITY 310*0b57cec5SDimitry Andricvoid 311*0b57cec5SDimitry Andricrethrow_if_nested(const _Ep& __e, 312*0b57cec5SDimitry Andric typename enable_if< __can_dynamic_cast<_Ep, nested_exception>::value>::type* = 0) 313*0b57cec5SDimitry Andric{ 314*0b57cec5SDimitry Andric const nested_exception* __nep = dynamic_cast<const nested_exception*>(_VSTD::addressof(__e)); 315*0b57cec5SDimitry Andric if (__nep) 316*0b57cec5SDimitry Andric __nep->rethrow_nested(); 317*0b57cec5SDimitry Andric} 318*0b57cec5SDimitry Andric 319*0b57cec5SDimitry Andrictemplate <class _Ep> 320*0b57cec5SDimitry Andricinline _LIBCPP_INLINE_VISIBILITY 321*0b57cec5SDimitry Andricvoid 322*0b57cec5SDimitry Andricrethrow_if_nested(const _Ep&, 323*0b57cec5SDimitry Andric typename enable_if<!__can_dynamic_cast<_Ep, nested_exception>::value>::type* = 0) 324*0b57cec5SDimitry Andric{ 325*0b57cec5SDimitry Andric} 326*0b57cec5SDimitry Andric 327*0b57cec5SDimitry Andric} // std 328*0b57cec5SDimitry Andric 329*0b57cec5SDimitry Andric#endif // _LIBCPP_EXCEPTION 330