1// -*- C++ -*- 2//===----------------------------------------------------------------------===// 3// 4// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5// See https://llvm.org/LICENSE.txt for license information. 6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7// 8//===----------------------------------------------------------------------===// 9 10#ifndef _LIBCPP_EXCEPTION 11#define _LIBCPP_EXCEPTION 12 13/* 14 exception synopsis 15 16namespace std 17{ 18 19class exception 20{ 21public: 22 exception() noexcept; 23 exception(const exception&) noexcept; 24 exception& operator=(const exception&) noexcept; 25 virtual ~exception() noexcept; 26 virtual const char* what() const noexcept; 27}; 28 29class bad_exception 30 : public exception 31{ 32public: 33 bad_exception() noexcept; 34 bad_exception(const bad_exception&) noexcept; 35 bad_exception& operator=(const bad_exception&) noexcept; 36 virtual ~bad_exception() noexcept; 37 virtual const char* what() const noexcept; 38}; 39 40typedef void (*unexpected_handler)(); 41unexpected_handler set_unexpected(unexpected_handler f ) noexcept; 42unexpected_handler get_unexpected() noexcept; 43[[noreturn]] void unexpected(); 44 45typedef void (*terminate_handler)(); 46terminate_handler set_terminate(terminate_handler f ) noexcept; 47terminate_handler get_terminate() noexcept; 48[[noreturn]] void terminate() noexcept; 49 50bool uncaught_exception() noexcept; 51int uncaught_exceptions() noexcept; // C++17 52 53typedef unspecified exception_ptr; 54 55exception_ptr current_exception() noexcept; 56void rethrow_exception [[noreturn]] (exception_ptr p); 57template<class E> exception_ptr make_exception_ptr(E e) noexcept; 58 59class nested_exception 60{ 61public: 62 nested_exception() noexcept; 63 nested_exception(const nested_exception&) noexcept = default; 64 nested_exception& operator=(const nested_exception&) noexcept = default; 65 virtual ~nested_exception() = default; 66 67 // access functions 68 [[noreturn]] void rethrow_nested() const; 69 exception_ptr nested_ptr() const noexcept; 70}; 71 72template <class T> [[noreturn]] void throw_with_nested(T&& t); 73template <class E> void rethrow_if_nested(const E& e); 74 75} // std 76 77*/ 78 79#include <__assert> // all public C++ headers provide the assertion handler 80#include <__availability> 81#include <__config> 82#include <__memory/addressof.h> 83#include <__type_traits/decay.h> 84#include <__type_traits/is_base_of.h> 85#include <__type_traits/is_class.h> 86#include <__type_traits/is_convertible.h> 87#include <__type_traits/is_copy_constructible.h> 88#include <__type_traits/is_final.h> 89#include <__type_traits/is_polymorphic.h> 90#include <cstddef> 91#include <cstdlib> 92#include <version> 93 94// <vcruntime_exception.h> defines its own std::exception and std::bad_exception types, 95// which we use in order to be ABI-compatible with other STLs on Windows. 96#if defined(_LIBCPP_ABI_VCRUNTIME) 97# include <vcruntime_exception.h> 98#endif 99 100#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 101# pragma GCC system_header 102#endif 103 104namespace std // purposefully not using versioning namespace 105{ 106 107#if defined(_LIBCPP_ABI_VCRUNTIME) && (!defined(_HAS_EXCEPTIONS) || _HAS_EXCEPTIONS != 0) 108// The std::exception class was already included above, but we're explicit about this condition here for clarity. 109 110#elif defined(_LIBCPP_ABI_VCRUNTIME) && _HAS_EXCEPTIONS == 0 111// However, <vcruntime_exception.h> does not define std::exception and std::bad_exception 112// when _HAS_EXCEPTIONS == 0. 113// 114// Since libc++ still wants to provide the std::exception hierarchy even when _HAS_EXCEPTIONS == 0 115// (after all those are simply types like any other), we define an ABI-compatible version 116// of the VCRuntime std::exception and std::bad_exception types in that mode. 117 118struct __std_exception_data { 119 char const* _What; 120 bool _DoFree; 121}; 122 123class exception { // base of all library exceptions 124public: 125 exception() _NOEXCEPT : __data_() {} 126 127 explicit exception(char const* __message) _NOEXCEPT : __data_() { 128 __data_._What = __message; 129 __data_._DoFree = true; 130 } 131 132 exception(exception const&) _NOEXCEPT {} 133 134 exception& operator=(exception const&) _NOEXCEPT { return *this; } 135 136 virtual ~exception() _NOEXCEPT {} 137 138 virtual char const* what() const _NOEXCEPT { return __data_._What ? __data_._What : "Unknown exception"; } 139 140private: 141 __std_exception_data __data_; 142}; 143 144class bad_exception : public exception { 145public: 146 bad_exception() _NOEXCEPT : exception("bad exception") {} 147}; 148 149#else // !defined(_LIBCPP_ABI_VCRUNTIME) 150// On all other platforms, we define our own std::exception and std::bad_exception types 151// regardless of whether exceptions are turned on as a language feature. 152 153class _LIBCPP_EXCEPTION_ABI exception { 154public: 155 _LIBCPP_INLINE_VISIBILITY exception() _NOEXCEPT {} 156 _LIBCPP_INLINE_VISIBILITY exception(const exception&) _NOEXCEPT = default; 157 158 virtual ~exception() _NOEXCEPT; 159 virtual const char* what() const _NOEXCEPT; 160}; 161 162class _LIBCPP_EXCEPTION_ABI bad_exception : public exception { 163public: 164 _LIBCPP_INLINE_VISIBILITY bad_exception() _NOEXCEPT {} 165 ~bad_exception() _NOEXCEPT override; 166 const char* what() const _NOEXCEPT override; 167}; 168#endif // !_LIBCPP_ABI_VCRUNTIME 169 170#if _LIBCPP_STD_VER <= 14 \ 171 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_UNEXPECTED_FUNCTIONS) \ 172 || defined(_LIBCPP_BUILDING_LIBRARY) 173typedef void (*unexpected_handler)(); 174_LIBCPP_FUNC_VIS unexpected_handler set_unexpected(unexpected_handler) _NOEXCEPT; 175_LIBCPP_FUNC_VIS unexpected_handler get_unexpected() _NOEXCEPT; 176_LIBCPP_NORETURN _LIBCPP_FUNC_VIS void unexpected(); 177#endif 178 179typedef void (*terminate_handler)(); 180_LIBCPP_FUNC_VIS terminate_handler set_terminate(terminate_handler) _NOEXCEPT; 181_LIBCPP_FUNC_VIS terminate_handler get_terminate() _NOEXCEPT; 182_LIBCPP_NORETURN _LIBCPP_FUNC_VIS void terminate() _NOEXCEPT; 183 184_LIBCPP_FUNC_VIS bool uncaught_exception() _NOEXCEPT; 185_LIBCPP_FUNC_VIS _LIBCPP_AVAILABILITY_UNCAUGHT_EXCEPTIONS int uncaught_exceptions() _NOEXCEPT; 186 187class _LIBCPP_TYPE_VIS exception_ptr; 188 189_LIBCPP_FUNC_VIS exception_ptr current_exception() _NOEXCEPT; 190_LIBCPP_NORETURN _LIBCPP_FUNC_VIS void rethrow_exception(exception_ptr); 191 192#ifndef _LIBCPP_ABI_MICROSOFT 193 194class _LIBCPP_TYPE_VIS exception_ptr 195{ 196 void* __ptr_; 197public: 198 _LIBCPP_INLINE_VISIBILITY exception_ptr() _NOEXCEPT : __ptr_() {} 199 _LIBCPP_INLINE_VISIBILITY exception_ptr(nullptr_t) _NOEXCEPT : __ptr_() {} 200 201 exception_ptr(const exception_ptr&) _NOEXCEPT; 202 exception_ptr& operator=(const exception_ptr&) _NOEXCEPT; 203 ~exception_ptr() _NOEXCEPT; 204 205 _LIBCPP_INLINE_VISIBILITY explicit operator bool() const _NOEXCEPT 206 {return __ptr_ != nullptr;} 207 208 friend _LIBCPP_INLINE_VISIBILITY 209 bool operator==(const exception_ptr& __x, const exception_ptr& __y) _NOEXCEPT 210 {return __x.__ptr_ == __y.__ptr_;} 211 212 friend _LIBCPP_INLINE_VISIBILITY 213 bool operator!=(const exception_ptr& __x, const exception_ptr& __y) _NOEXCEPT 214 {return !(__x == __y);} 215 216 friend _LIBCPP_FUNC_VIS exception_ptr current_exception() _NOEXCEPT; 217 friend _LIBCPP_FUNC_VIS void rethrow_exception(exception_ptr); 218}; 219 220template<class _Ep> 221_LIBCPP_INLINE_VISIBILITY exception_ptr 222make_exception_ptr(_Ep __e) _NOEXCEPT 223{ 224#ifndef _LIBCPP_NO_EXCEPTIONS 225 try 226 { 227 throw __e; 228 } 229 catch (...) 230 { 231 return current_exception(); 232 } 233#else 234 ((void)__e); 235 _VSTD::abort(); 236#endif 237} 238 239#else // _LIBCPP_ABI_MICROSOFT 240 241class _LIBCPP_TYPE_VIS exception_ptr 242{ 243_LIBCPP_DIAGNOSTIC_PUSH 244_LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wunused-private-field") 245 void* __ptr1_; 246 void* __ptr2_; 247_LIBCPP_DIAGNOSTIC_POP 248public: 249 exception_ptr() _NOEXCEPT; 250 exception_ptr(nullptr_t) _NOEXCEPT; 251 exception_ptr(const exception_ptr& __other) _NOEXCEPT; 252 exception_ptr& operator=(const exception_ptr& __other) _NOEXCEPT; 253 exception_ptr& operator=(nullptr_t) _NOEXCEPT; 254 ~exception_ptr() _NOEXCEPT; 255 explicit operator bool() const _NOEXCEPT; 256}; 257 258_LIBCPP_FUNC_VIS 259bool operator==(const exception_ptr& __x, const exception_ptr& __y) _NOEXCEPT; 260 261inline _LIBCPP_INLINE_VISIBILITY 262bool operator!=(const exception_ptr& __x, const exception_ptr& __y) _NOEXCEPT 263 {return !(__x == __y);} 264 265_LIBCPP_FUNC_VIS void swap(exception_ptr&, exception_ptr&) _NOEXCEPT; 266 267_LIBCPP_FUNC_VIS exception_ptr __copy_exception_ptr(void *__except, const void* __ptr); 268_LIBCPP_FUNC_VIS exception_ptr current_exception() _NOEXCEPT; 269_LIBCPP_NORETURN _LIBCPP_FUNC_VIS void rethrow_exception(exception_ptr); 270 271// This is a built-in template function which automagically extracts the required 272// information. 273template <class _E> void *__GetExceptionInfo(_E); 274 275template<class _Ep> 276_LIBCPP_INLINE_VISIBILITY exception_ptr 277make_exception_ptr(_Ep __e) _NOEXCEPT 278{ 279 return __copy_exception_ptr(_VSTD::addressof(__e), __GetExceptionInfo(__e)); 280} 281 282#endif // _LIBCPP_ABI_MICROSOFT 283// nested_exception 284 285class _LIBCPP_EXCEPTION_ABI nested_exception 286{ 287 exception_ptr __ptr_; 288public: 289 nested_exception() _NOEXCEPT; 290// nested_exception(const nested_exception&) noexcept = default; 291// nested_exception& operator=(const nested_exception&) noexcept = default; 292 virtual ~nested_exception() _NOEXCEPT; 293 294 // access functions 295 _LIBCPP_NORETURN void rethrow_nested() const; 296 _LIBCPP_INLINE_VISIBILITY exception_ptr nested_ptr() const _NOEXCEPT {return __ptr_;} 297}; 298 299template <class _Tp> 300struct __nested 301 : public _Tp, 302 public nested_exception 303{ 304 _LIBCPP_INLINE_VISIBILITY explicit __nested(const _Tp& __t) : _Tp(__t) {} 305}; 306 307#ifndef _LIBCPP_NO_EXCEPTIONS 308template <class _Tp, class _Up, bool> 309struct __throw_with_nested; 310 311template <class _Tp, class _Up> 312struct __throw_with_nested<_Tp, _Up, true> { 313 _LIBCPP_NORETURN static inline _LIBCPP_INLINE_VISIBILITY void 314 __do_throw(_Tp&& __t) 315 { 316 throw __nested<_Up>(static_cast<_Tp&&>(__t)); 317 } 318}; 319 320template <class _Tp, class _Up> 321struct __throw_with_nested<_Tp, _Up, false> { 322 _LIBCPP_NORETURN static inline _LIBCPP_INLINE_VISIBILITY void 323#ifndef _LIBCPP_CXX03_LANG 324 __do_throw(_Tp&& __t) 325#else 326 __do_throw (_Tp& __t) 327#endif // _LIBCPP_CXX03_LANG 328 { 329 throw static_cast<_Tp&&>(__t); 330 } 331}; 332#endif 333 334template <class _Tp> 335_LIBCPP_NORETURN _LIBCPP_HIDE_FROM_ABI 336void 337throw_with_nested(_Tp&& __t) 338{ 339#ifndef _LIBCPP_NO_EXCEPTIONS 340 typedef typename decay<_Tp>::type _Up; 341 static_assert( is_copy_constructible<_Up>::value, "type thrown must be CopyConstructible"); 342 __throw_with_nested<_Tp, _Up, 343 is_class<_Up>::value && 344 !is_base_of<nested_exception, _Up>::value && 345 !__libcpp_is_final<_Up>::value>:: 346 __do_throw(static_cast<_Tp&&>(__t)); 347#else 348 ((void)__t); 349 // FIXME: Make this abort 350#endif 351} 352 353template <class _From, class _To> 354struct __can_dynamic_cast : _BoolConstant< 355 is_polymorphic<_From>::value && 356 (!is_base_of<_To, _From>::value || 357 is_convertible<const _From*, const _To*>::value)> {}; 358 359template <class _Ep> 360inline _LIBCPP_INLINE_VISIBILITY 361void 362rethrow_if_nested(const _Ep& __e, 363 __enable_if_t< __can_dynamic_cast<_Ep, nested_exception>::value>* = 0) 364{ 365 const nested_exception* __nep = dynamic_cast<const nested_exception*>(_VSTD::addressof(__e)); 366 if (__nep) 367 __nep->rethrow_nested(); 368} 369 370template <class _Ep> 371inline _LIBCPP_INLINE_VISIBILITY 372void 373rethrow_if_nested(const _Ep&, 374 __enable_if_t<!__can_dynamic_cast<_Ep, nested_exception>::value>* = 0) 375{ 376} 377 378} // namespace std 379 380#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 381# include <type_traits> 382#endif 383 384#endif // _LIBCPP_EXCEPTION 385