146035553Spatrick// -*- C++ -*- 2*4bdff4beSrobert//===----------------------------------------------------------------------===// 346035553Spatrick// 446035553Spatrick// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 546035553Spatrick// See https://llvm.org/LICENSE.txt for license information. 646035553Spatrick// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 746035553Spatrick// 846035553Spatrick//===----------------------------------------------------------------------===// 946035553Spatrick 1046035553Spatrick#ifndef _LIBCPP_EXCEPTION 1146035553Spatrick#define _LIBCPP_EXCEPTION 1246035553Spatrick 1346035553Spatrick/* 1446035553Spatrick exception synopsis 1546035553Spatrick 1646035553Spatricknamespace std 1746035553Spatrick{ 1846035553Spatrick 1946035553Spatrickclass exception 2046035553Spatrick{ 2146035553Spatrickpublic: 2246035553Spatrick exception() noexcept; 2346035553Spatrick exception(const exception&) noexcept; 2446035553Spatrick exception& operator=(const exception&) noexcept; 2546035553Spatrick virtual ~exception() noexcept; 2646035553Spatrick virtual const char* what() const noexcept; 2746035553Spatrick}; 2846035553Spatrick 2946035553Spatrickclass bad_exception 3046035553Spatrick : public exception 3146035553Spatrick{ 3246035553Spatrickpublic: 3346035553Spatrick bad_exception() noexcept; 3446035553Spatrick bad_exception(const bad_exception&) noexcept; 3546035553Spatrick bad_exception& operator=(const bad_exception&) noexcept; 3646035553Spatrick virtual ~bad_exception() noexcept; 3746035553Spatrick virtual const char* what() const noexcept; 3846035553Spatrick}; 3946035553Spatrick 4046035553Spatricktypedef void (*unexpected_handler)(); 4146035553Spatrickunexpected_handler set_unexpected(unexpected_handler f ) noexcept; 4246035553Spatrickunexpected_handler get_unexpected() noexcept; 4346035553Spatrick[[noreturn]] void unexpected(); 4446035553Spatrick 4546035553Spatricktypedef void (*terminate_handler)(); 4646035553Spatrickterminate_handler set_terminate(terminate_handler f ) noexcept; 4746035553Spatrickterminate_handler get_terminate() noexcept; 4846035553Spatrick[[noreturn]] void terminate() noexcept; 4946035553Spatrick 5046035553Spatrickbool uncaught_exception() noexcept; 5146035553Spatrickint uncaught_exceptions() noexcept; // C++17 5246035553Spatrick 5346035553Spatricktypedef unspecified exception_ptr; 5446035553Spatrick 5546035553Spatrickexception_ptr current_exception() noexcept; 5646035553Spatrickvoid rethrow_exception [[noreturn]] (exception_ptr p); 5746035553Spatricktemplate<class E> exception_ptr make_exception_ptr(E e) noexcept; 5846035553Spatrick 5946035553Spatrickclass nested_exception 6046035553Spatrick{ 6146035553Spatrickpublic: 6246035553Spatrick nested_exception() noexcept; 6346035553Spatrick nested_exception(const nested_exception&) noexcept = default; 6446035553Spatrick nested_exception& operator=(const nested_exception&) noexcept = default; 6546035553Spatrick virtual ~nested_exception() = default; 6646035553Spatrick 6746035553Spatrick // access functions 6846035553Spatrick [[noreturn]] void rethrow_nested() const; 6946035553Spatrick exception_ptr nested_ptr() const noexcept; 7046035553Spatrick}; 7146035553Spatrick 7246035553Spatricktemplate <class T> [[noreturn]] void throw_with_nested(T&& t); 7346035553Spatricktemplate <class E> void rethrow_if_nested(const E& e); 7446035553Spatrick 7546035553Spatrick} // std 7646035553Spatrick 7746035553Spatrick*/ 7846035553Spatrick 79*4bdff4beSrobert#include <__assert> // all public C++ headers provide the assertion handler 8076d0caaeSpatrick#include <__availability> 8146035553Spatrick#include <__config> 8276d0caaeSpatrick#include <__memory/addressof.h> 83*4bdff4beSrobert#include <__type_traits/decay.h> 84*4bdff4beSrobert#include <__type_traits/is_base_of.h> 85*4bdff4beSrobert#include <__type_traits/is_class.h> 86*4bdff4beSrobert#include <__type_traits/is_convertible.h> 87*4bdff4beSrobert#include <__type_traits/is_copy_constructible.h> 88*4bdff4beSrobert#include <__type_traits/is_final.h> 89*4bdff4beSrobert#include <__type_traits/is_polymorphic.h> 9046035553Spatrick#include <cstddef> 9146035553Spatrick#include <cstdlib> 9246035553Spatrick#include <version> 9346035553Spatrick 94*4bdff4beSrobert// <vcruntime_exception.h> defines its own std::exception and std::bad_exception types, 95*4bdff4beSrobert// which we use in order to be ABI-compatible with other STLs on Windows. 9646035553Spatrick#if defined(_LIBCPP_ABI_VCRUNTIME) 9746035553Spatrick# include <vcruntime_exception.h> 9846035553Spatrick#endif 9946035553Spatrick 10046035553Spatrick#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 10146035553Spatrick# pragma GCC system_header 10246035553Spatrick#endif 10346035553Spatrick 10446035553Spatricknamespace std // purposefully not using versioning namespace 10546035553Spatrick{ 10646035553Spatrick 107*4bdff4beSrobert#if defined(_LIBCPP_ABI_VCRUNTIME) && (!defined(_HAS_EXCEPTIONS) || _HAS_EXCEPTIONS != 0) 108*4bdff4beSrobert// The std::exception class was already included above, but we're explicit about this condition here for clarity. 109*4bdff4beSrobert 110*4bdff4beSrobert#elif defined(_LIBCPP_ABI_VCRUNTIME) && _HAS_EXCEPTIONS == 0 111*4bdff4beSrobert// However, <vcruntime_exception.h> does not define std::exception and std::bad_exception 112*4bdff4beSrobert// when _HAS_EXCEPTIONS == 0. 113*4bdff4beSrobert// 114*4bdff4beSrobert// Since libc++ still wants to provide the std::exception hierarchy even when _HAS_EXCEPTIONS == 0 115*4bdff4beSrobert// (after all those are simply types like any other), we define an ABI-compatible version 116*4bdff4beSrobert// of the VCRuntime std::exception and std::bad_exception types in that mode. 117*4bdff4beSrobert 118*4bdff4beSrobertstruct __std_exception_data { 119*4bdff4beSrobert char const* _What; 120*4bdff4beSrobert bool _DoFree; 121*4bdff4beSrobert}; 122*4bdff4beSrobert 123*4bdff4beSrobertclass exception { // base of all library exceptions 124*4bdff4beSrobertpublic: 125*4bdff4beSrobert exception() _NOEXCEPT : __data_() {} 126*4bdff4beSrobert 127*4bdff4beSrobert explicit exception(char const* __message) _NOEXCEPT : __data_() { 128*4bdff4beSrobert __data_._What = __message; 129*4bdff4beSrobert __data_._DoFree = true; 130*4bdff4beSrobert } 131*4bdff4beSrobert 132*4bdff4beSrobert exception(exception const&) _NOEXCEPT {} 133*4bdff4beSrobert 134*4bdff4beSrobert exception& operator=(exception const&) _NOEXCEPT { return *this; } 135*4bdff4beSrobert 136*4bdff4beSrobert virtual ~exception() _NOEXCEPT {} 137*4bdff4beSrobert 138*4bdff4beSrobert virtual char const* what() const _NOEXCEPT { return __data_._What ? __data_._What : "Unknown exception"; } 139*4bdff4beSrobert 140*4bdff4beSrobertprivate: 141*4bdff4beSrobert __std_exception_data __data_; 142*4bdff4beSrobert}; 143*4bdff4beSrobert 144*4bdff4beSrobertclass bad_exception : public exception { 145*4bdff4beSrobertpublic: 146*4bdff4beSrobert bad_exception() _NOEXCEPT : exception("bad exception") {} 147*4bdff4beSrobert}; 148*4bdff4beSrobert 149*4bdff4beSrobert#else // !defined(_LIBCPP_ABI_VCRUNTIME) 150*4bdff4beSrobert// On all other platforms, we define our own std::exception and std::bad_exception types 151*4bdff4beSrobert// regardless of whether exceptions are turned on as a language feature. 152*4bdff4beSrobert 153*4bdff4beSrobertclass _LIBCPP_EXCEPTION_ABI exception { 15446035553Spatrickpublic: 15546035553Spatrick _LIBCPP_INLINE_VISIBILITY exception() _NOEXCEPT {} 156037e7968Spatrick _LIBCPP_INLINE_VISIBILITY exception(const exception&) _NOEXCEPT = default; 157037e7968Spatrick 15846035553Spatrick virtual ~exception() _NOEXCEPT; 15946035553Spatrick virtual const char* what() const _NOEXCEPT; 16046035553Spatrick}; 16146035553Spatrick 162*4bdff4beSrobertclass _LIBCPP_EXCEPTION_ABI bad_exception : public exception { 16346035553Spatrickpublic: 16446035553Spatrick _LIBCPP_INLINE_VISIBILITY bad_exception() _NOEXCEPT {} 165*4bdff4beSrobert ~bad_exception() _NOEXCEPT override; 166*4bdff4beSrobert const char* what() const _NOEXCEPT override; 16746035553Spatrick}; 16846035553Spatrick#endif // !_LIBCPP_ABI_VCRUNTIME 16946035553Spatrick 17046035553Spatrick#if _LIBCPP_STD_VER <= 14 \ 17146035553Spatrick || defined(_LIBCPP_ENABLE_CXX17_REMOVED_UNEXPECTED_FUNCTIONS) \ 17246035553Spatrick || defined(_LIBCPP_BUILDING_LIBRARY) 17346035553Spatricktypedef void (*unexpected_handler)(); 17446035553Spatrick_LIBCPP_FUNC_VIS unexpected_handler set_unexpected(unexpected_handler) _NOEXCEPT; 17546035553Spatrick_LIBCPP_FUNC_VIS unexpected_handler get_unexpected() _NOEXCEPT; 17646035553Spatrick_LIBCPP_NORETURN _LIBCPP_FUNC_VIS void unexpected(); 17746035553Spatrick#endif 17846035553Spatrick 17946035553Spatricktypedef void (*terminate_handler)(); 18046035553Spatrick_LIBCPP_FUNC_VIS terminate_handler set_terminate(terminate_handler) _NOEXCEPT; 18146035553Spatrick_LIBCPP_FUNC_VIS terminate_handler get_terminate() _NOEXCEPT; 18246035553Spatrick_LIBCPP_NORETURN _LIBCPP_FUNC_VIS void terminate() _NOEXCEPT; 18346035553Spatrick 18446035553Spatrick_LIBCPP_FUNC_VIS bool uncaught_exception() _NOEXCEPT; 18546035553Spatrick_LIBCPP_FUNC_VIS _LIBCPP_AVAILABILITY_UNCAUGHT_EXCEPTIONS int uncaught_exceptions() _NOEXCEPT; 18646035553Spatrick 18746035553Spatrickclass _LIBCPP_TYPE_VIS exception_ptr; 18846035553Spatrick 18946035553Spatrick_LIBCPP_FUNC_VIS exception_ptr current_exception() _NOEXCEPT; 19046035553Spatrick_LIBCPP_NORETURN _LIBCPP_FUNC_VIS void rethrow_exception(exception_ptr); 19146035553Spatrick 19246035553Spatrick#ifndef _LIBCPP_ABI_MICROSOFT 19346035553Spatrick 19446035553Spatrickclass _LIBCPP_TYPE_VIS exception_ptr 19546035553Spatrick{ 19646035553Spatrick void* __ptr_; 19746035553Spatrickpublic: 19846035553Spatrick _LIBCPP_INLINE_VISIBILITY exception_ptr() _NOEXCEPT : __ptr_() {} 19946035553Spatrick _LIBCPP_INLINE_VISIBILITY exception_ptr(nullptr_t) _NOEXCEPT : __ptr_() {} 20046035553Spatrick 20146035553Spatrick exception_ptr(const exception_ptr&) _NOEXCEPT; 20246035553Spatrick exception_ptr& operator=(const exception_ptr&) _NOEXCEPT; 20346035553Spatrick ~exception_ptr() _NOEXCEPT; 20446035553Spatrick 20576d0caaeSpatrick _LIBCPP_INLINE_VISIBILITY explicit operator bool() const _NOEXCEPT 20646035553Spatrick {return __ptr_ != nullptr;} 20746035553Spatrick 20846035553Spatrick friend _LIBCPP_INLINE_VISIBILITY 20946035553Spatrick bool operator==(const exception_ptr& __x, const exception_ptr& __y) _NOEXCEPT 21046035553Spatrick {return __x.__ptr_ == __y.__ptr_;} 21146035553Spatrick 21246035553Spatrick friend _LIBCPP_INLINE_VISIBILITY 21346035553Spatrick bool operator!=(const exception_ptr& __x, const exception_ptr& __y) _NOEXCEPT 21446035553Spatrick {return !(__x == __y);} 21546035553Spatrick 21646035553Spatrick friend _LIBCPP_FUNC_VIS exception_ptr current_exception() _NOEXCEPT; 21746035553Spatrick friend _LIBCPP_FUNC_VIS void rethrow_exception(exception_ptr); 21846035553Spatrick}; 21946035553Spatrick 22046035553Spatricktemplate<class _Ep> 22146035553Spatrick_LIBCPP_INLINE_VISIBILITY exception_ptr 22246035553Spatrickmake_exception_ptr(_Ep __e) _NOEXCEPT 22346035553Spatrick{ 22446035553Spatrick#ifndef _LIBCPP_NO_EXCEPTIONS 22546035553Spatrick try 22646035553Spatrick { 22746035553Spatrick throw __e; 22846035553Spatrick } 22946035553Spatrick catch (...) 23046035553Spatrick { 23146035553Spatrick return current_exception(); 23246035553Spatrick } 23346035553Spatrick#else 23446035553Spatrick ((void)__e); 23546035553Spatrick _VSTD::abort(); 23646035553Spatrick#endif 23746035553Spatrick} 23846035553Spatrick 23946035553Spatrick#else // _LIBCPP_ABI_MICROSOFT 24046035553Spatrick 24146035553Spatrickclass _LIBCPP_TYPE_VIS exception_ptr 24246035553Spatrick{ 243*4bdff4beSrobert_LIBCPP_DIAGNOSTIC_PUSH 244*4bdff4beSrobert_LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wunused-private-field") 24546035553Spatrick void* __ptr1_; 24646035553Spatrick void* __ptr2_; 247*4bdff4beSrobert_LIBCPP_DIAGNOSTIC_POP 24846035553Spatrickpublic: 24946035553Spatrick exception_ptr() _NOEXCEPT; 25046035553Spatrick exception_ptr(nullptr_t) _NOEXCEPT; 25146035553Spatrick exception_ptr(const exception_ptr& __other) _NOEXCEPT; 25246035553Spatrick exception_ptr& operator=(const exception_ptr& __other) _NOEXCEPT; 25346035553Spatrick exception_ptr& operator=(nullptr_t) _NOEXCEPT; 25446035553Spatrick ~exception_ptr() _NOEXCEPT; 25576d0caaeSpatrick explicit operator bool() const _NOEXCEPT; 25646035553Spatrick}; 25746035553Spatrick 25846035553Spatrick_LIBCPP_FUNC_VIS 25946035553Spatrickbool operator==(const exception_ptr& __x, const exception_ptr& __y) _NOEXCEPT; 26046035553Spatrick 26146035553Spatrickinline _LIBCPP_INLINE_VISIBILITY 26246035553Spatrickbool operator!=(const exception_ptr& __x, const exception_ptr& __y) _NOEXCEPT 26346035553Spatrick {return !(__x == __y);} 26446035553Spatrick 26546035553Spatrick_LIBCPP_FUNC_VIS void swap(exception_ptr&, exception_ptr&) _NOEXCEPT; 26646035553Spatrick 26746035553Spatrick_LIBCPP_FUNC_VIS exception_ptr __copy_exception_ptr(void *__except, const void* __ptr); 26846035553Spatrick_LIBCPP_FUNC_VIS exception_ptr current_exception() _NOEXCEPT; 269*4bdff4beSrobert_LIBCPP_NORETURN _LIBCPP_FUNC_VIS void rethrow_exception(exception_ptr); 27046035553Spatrick 27146035553Spatrick// This is a built-in template function which automagically extracts the required 27246035553Spatrick// information. 27346035553Spatricktemplate <class _E> void *__GetExceptionInfo(_E); 27446035553Spatrick 27546035553Spatricktemplate<class _Ep> 27646035553Spatrick_LIBCPP_INLINE_VISIBILITY exception_ptr 27746035553Spatrickmake_exception_ptr(_Ep __e) _NOEXCEPT 27846035553Spatrick{ 27946035553Spatrick return __copy_exception_ptr(_VSTD::addressof(__e), __GetExceptionInfo(__e)); 28046035553Spatrick} 28146035553Spatrick 28246035553Spatrick#endif // _LIBCPP_ABI_MICROSOFT 28346035553Spatrick// nested_exception 28446035553Spatrick 28546035553Spatrickclass _LIBCPP_EXCEPTION_ABI nested_exception 28646035553Spatrick{ 28746035553Spatrick exception_ptr __ptr_; 28846035553Spatrickpublic: 28946035553Spatrick nested_exception() _NOEXCEPT; 29046035553Spatrick// nested_exception(const nested_exception&) noexcept = default; 29146035553Spatrick// nested_exception& operator=(const nested_exception&) noexcept = default; 29246035553Spatrick virtual ~nested_exception() _NOEXCEPT; 29346035553Spatrick 29446035553Spatrick // access functions 29546035553Spatrick _LIBCPP_NORETURN void rethrow_nested() const; 29646035553Spatrick _LIBCPP_INLINE_VISIBILITY exception_ptr nested_ptr() const _NOEXCEPT {return __ptr_;} 29746035553Spatrick}; 29846035553Spatrick 29946035553Spatricktemplate <class _Tp> 30046035553Spatrickstruct __nested 30146035553Spatrick : public _Tp, 30246035553Spatrick public nested_exception 30346035553Spatrick{ 30446035553Spatrick _LIBCPP_INLINE_VISIBILITY explicit __nested(const _Tp& __t) : _Tp(__t) {} 30546035553Spatrick}; 30646035553Spatrick 30746035553Spatrick#ifndef _LIBCPP_NO_EXCEPTIONS 30846035553Spatricktemplate <class _Tp, class _Up, bool> 30946035553Spatrickstruct __throw_with_nested; 31046035553Spatrick 31146035553Spatricktemplate <class _Tp, class _Up> 31246035553Spatrickstruct __throw_with_nested<_Tp, _Up, true> { 31346035553Spatrick _LIBCPP_NORETURN static inline _LIBCPP_INLINE_VISIBILITY void 31446035553Spatrick __do_throw(_Tp&& __t) 31546035553Spatrick { 31676d0caaeSpatrick throw __nested<_Up>(static_cast<_Tp&&>(__t)); 31746035553Spatrick } 31846035553Spatrick}; 31946035553Spatrick 32046035553Spatricktemplate <class _Tp, class _Up> 32146035553Spatrickstruct __throw_with_nested<_Tp, _Up, false> { 32246035553Spatrick _LIBCPP_NORETURN static inline _LIBCPP_INLINE_VISIBILITY void 32346035553Spatrick#ifndef _LIBCPP_CXX03_LANG 32446035553Spatrick __do_throw(_Tp&& __t) 32546035553Spatrick#else 32646035553Spatrick __do_throw (_Tp& __t) 32746035553Spatrick#endif // _LIBCPP_CXX03_LANG 32846035553Spatrick { 32976d0caaeSpatrick throw static_cast<_Tp&&>(__t); 33046035553Spatrick } 33146035553Spatrick}; 33246035553Spatrick#endif 33346035553Spatrick 33446035553Spatricktemplate <class _Tp> 335*4bdff4beSrobert_LIBCPP_NORETURN _LIBCPP_HIDE_FROM_ABI 33646035553Spatrickvoid 33746035553Spatrickthrow_with_nested(_Tp&& __t) 33846035553Spatrick{ 33946035553Spatrick#ifndef _LIBCPP_NO_EXCEPTIONS 34046035553Spatrick typedef typename decay<_Tp>::type _Up; 34146035553Spatrick static_assert( is_copy_constructible<_Up>::value, "type thrown must be CopyConstructible"); 34246035553Spatrick __throw_with_nested<_Tp, _Up, 34346035553Spatrick is_class<_Up>::value && 34446035553Spatrick !is_base_of<nested_exception, _Up>::value && 34546035553Spatrick !__libcpp_is_final<_Up>::value>:: 34676d0caaeSpatrick __do_throw(static_cast<_Tp&&>(__t)); 34746035553Spatrick#else 34846035553Spatrick ((void)__t); 34946035553Spatrick // FIXME: Make this abort 35046035553Spatrick#endif 35146035553Spatrick} 35246035553Spatrick 35346035553Spatricktemplate <class _From, class _To> 354*4bdff4beSrobertstruct __can_dynamic_cast : _BoolConstant< 35546035553Spatrick is_polymorphic<_From>::value && 35646035553Spatrick (!is_base_of<_To, _From>::value || 357*4bdff4beSrobert is_convertible<const _From*, const _To*>::value)> {}; 35846035553Spatrick 35946035553Spatricktemplate <class _Ep> 36046035553Spatrickinline _LIBCPP_INLINE_VISIBILITY 36146035553Spatrickvoid 36246035553Spatrickrethrow_if_nested(const _Ep& __e, 363*4bdff4beSrobert __enable_if_t< __can_dynamic_cast<_Ep, nested_exception>::value>* = 0) 36446035553Spatrick{ 36546035553Spatrick const nested_exception* __nep = dynamic_cast<const nested_exception*>(_VSTD::addressof(__e)); 36646035553Spatrick if (__nep) 36746035553Spatrick __nep->rethrow_nested(); 36846035553Spatrick} 36946035553Spatrick 37046035553Spatricktemplate <class _Ep> 37146035553Spatrickinline _LIBCPP_INLINE_VISIBILITY 37246035553Spatrickvoid 37346035553Spatrickrethrow_if_nested(const _Ep&, 374*4bdff4beSrobert __enable_if_t<!__can_dynamic_cast<_Ep, nested_exception>::value>* = 0) 37546035553Spatrick{ 37646035553Spatrick} 37746035553Spatrick 378*4bdff4beSrobert} // namespace std 379*4bdff4beSrobert 380*4bdff4beSrobert#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 381*4bdff4beSrobert# include <type_traits> 382*4bdff4beSrobert#endif 38346035553Spatrick 38446035553Spatrick#endif // _LIBCPP_EXCEPTION 385