1//===------------------------ exception.cpp -------------------------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is dual licensed under the MIT and the University of Illinois Open 6// Source Licenses. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9#include <stdlib.h> 10#include <stdio.h> 11 12#include "exception" 13#include "new" 14 15#ifndef __has_include 16#ifdef LIBCXXABI 17#define __has_include(inc) 1 18#else 19#define __has_include(inc) 0 20#endif 21#endif 22 23#ifdef __APPLE__ 24 #include <cxxabi.h> 25 26 using namespace __cxxabiv1; 27 #define HAVE_DEPENDENT_EH_ABI 1 28 #ifndef _LIBCPPABI_VERSION 29 using namespace __cxxabiapple; 30 // On Darwin, there are two STL shared libraries and a lower level ABI 31 // shared library. The globals holding the current terminate handler and 32 // current unexpected handler are in the ABI library. 33 #define __terminate_handler __cxxabiapple::__cxa_terminate_handler 34 #define __unexpected_handler __cxxabiapple::__cxa_unexpected_handler 35 #endif // _LIBCPPABI_VERSION 36#elif defined(LIBCXXRT) || __has_include(<cxxabi.h>) 37 #include <cxxabi.h> 38 using namespace __cxxabiv1; 39 #if defined(LIBCXXRT) || defined(_LIBCPPABI_VERSION) 40 #define HAVE_DEPENDENT_EH_ABI 1 41 #endif 42#elif !defined(__GLIBCXX__) // __has_include(<cxxabi.h>) 43 static std::terminate_handler __terminate_handler; 44 static std::unexpected_handler __unexpected_handler; 45#endif // __has_include(<cxxabi.h>) 46 47namespace std 48{ 49 50#if !defined(LIBCXXRT) && !defined(__GLIBCXX__) && !defined(__EMSCRIPTEN__) 51bool uncaught_exception() _NOEXCEPT 52{ 53#if defined(__APPLE__) || defined(_LIBCPPABI_VERSION) 54 // on Darwin, there is a helper function so __cxa_get_globals is private 55 return __cxa_uncaught_exception(); 56#else // __APPLE__ 57# if defined(_MSC_VER) && ! defined(__clang__) 58 _LIBCPP_WARNING("uncaught_exception not yet implemented") 59# else 60# warning uncaught_exception not yet implemented 61# endif 62 printf("uncaught_exception not yet implemented\n"); 63 ::abort(); 64#endif // __APPLE__ 65} 66 67 68#ifndef _LIBCPPABI_VERSION 69 70exception::~exception() _NOEXCEPT 71{ 72} 73 74const char* exception::what() const _NOEXCEPT 75{ 76 return "std::exception"; 77} 78 79#endif // _LIBCPPABI_VERSION 80#endif //LIBCXXRT 81#if !defined(_LIBCPPABI_VERSION) && !defined(__GLIBCXX__) 82 83bad_exception::~bad_exception() _NOEXCEPT 84{ 85} 86 87const char* bad_exception::what() const _NOEXCEPT 88{ 89 return "std::bad_exception"; 90} 91 92#endif 93 94#if defined(__GLIBCXX__) 95 96// libsupc++ does not implement the dependent EH ABI and the functionality 97// it uses to implement std::exception_ptr (which it declares as an alias of 98// std::__exception_ptr::exception_ptr) is not directly exported to clients. So 99// we have little choice but to hijack std::__exception_ptr::exception_ptr's 100// (which fortunately has the same layout as our std::exception_ptr) copy 101// constructor, assignment operator and destructor (which are part of its 102// stable ABI), and its rethrow_exception(std::__exception_ptr::exception_ptr) 103// function. 104 105namespace __exception_ptr 106{ 107 108struct exception_ptr 109{ 110 void* __ptr_; 111 112 exception_ptr(const exception_ptr&) _NOEXCEPT; 113 exception_ptr& operator=(const exception_ptr&) _NOEXCEPT; 114 ~exception_ptr() _NOEXCEPT; 115}; 116 117} 118 119_LIBCPP_NORETURN void rethrow_exception(__exception_ptr::exception_ptr); 120 121#endif 122 123exception_ptr::~exception_ptr() _NOEXCEPT 124{ 125#if HAVE_DEPENDENT_EH_ABI 126 __cxa_decrement_exception_refcount(__ptr_); 127#elif defined(__GLIBCXX__) 128 reinterpret_cast<__exception_ptr::exception_ptr*>(this)->~exception_ptr(); 129#else 130# if defined(_MSC_VER) && ! defined(__clang__) 131 _LIBCPP_WARNING("exception_ptr not yet implemented") 132# else 133# warning exception_ptr not yet implemented 134# endif 135 printf("exception_ptr not yet implemented\n"); 136 ::abort(); 137#endif 138} 139 140exception_ptr::exception_ptr(const exception_ptr& other) _NOEXCEPT 141 : __ptr_(other.__ptr_) 142{ 143#if HAVE_DEPENDENT_EH_ABI 144 __cxa_increment_exception_refcount(__ptr_); 145#elif defined(__GLIBCXX__) 146 new (reinterpret_cast<void*>(this)) __exception_ptr::exception_ptr( 147 reinterpret_cast<const __exception_ptr::exception_ptr&>(other)); 148#else 149# if defined(_MSC_VER) && ! defined(__clang__) 150 _LIBCPP_WARNING("exception_ptr not yet implemented") 151# else 152# warning exception_ptr not yet implemented 153# endif 154 printf("exception_ptr not yet implemented\n"); 155 ::abort(); 156#endif 157} 158 159exception_ptr& exception_ptr::operator=(const exception_ptr& other) _NOEXCEPT 160{ 161#if HAVE_DEPENDENT_EH_ABI 162 if (__ptr_ != other.__ptr_) 163 { 164 __cxa_increment_exception_refcount(other.__ptr_); 165 __cxa_decrement_exception_refcount(__ptr_); 166 __ptr_ = other.__ptr_; 167 } 168 return *this; 169#elif defined(__GLIBCXX__) 170 *reinterpret_cast<__exception_ptr::exception_ptr*>(this) = 171 reinterpret_cast<const __exception_ptr::exception_ptr&>(other); 172 return *this; 173#else 174# if defined(_MSC_VER) && ! defined(__clang__) 175 _LIBCPP_WARNING("exception_ptr not yet implemented") 176# else 177# warning exception_ptr not yet implemented 178# endif 179 printf("exception_ptr not yet implemented\n"); 180 ::abort(); 181#endif 182} 183 184nested_exception::nested_exception() _NOEXCEPT 185 : __ptr_(current_exception()) 186{ 187} 188 189#if !defined(__GLIBCXX__) 190 191nested_exception::~nested_exception() _NOEXCEPT 192{ 193} 194 195#endif 196 197_LIBCPP_NORETURN 198void 199nested_exception::rethrow_nested() const 200{ 201 if (__ptr_ == nullptr) 202 terminate(); 203 rethrow_exception(__ptr_); 204} 205 206#if !defined(__GLIBCXX__) 207 208exception_ptr current_exception() _NOEXCEPT 209{ 210#if HAVE_DEPENDENT_EH_ABI 211 // be nicer if there was a constructor that took a ptr, then 212 // this whole function would be just: 213 // return exception_ptr(__cxa_current_primary_exception()); 214 exception_ptr ptr; 215 ptr.__ptr_ = __cxa_current_primary_exception(); 216 return ptr; 217#else 218# if defined(_MSC_VER) && ! defined(__clang__) 219 _LIBCPP_WARNING( "exception_ptr not yet implemented" ) 220# else 221# warning exception_ptr not yet implemented 222# endif 223 printf("exception_ptr not yet implemented\n"); 224 ::abort(); 225#endif 226} 227 228#endif // !__GLIBCXX__ 229 230_LIBCPP_NORETURN 231void rethrow_exception(exception_ptr p) 232{ 233#if HAVE_DEPENDENT_EH_ABI 234 __cxa_rethrow_primary_exception(p.__ptr_); 235 // if p.__ptr_ is NULL, above returns so we terminate 236 terminate(); 237#elif defined(__GLIBCXX__) 238 rethrow_exception(reinterpret_cast<__exception_ptr::exception_ptr&>(p)); 239#else 240# if defined(_MSC_VER) && ! defined(__clang__) 241 _LIBCPP_WARNING("exception_ptr not yet implemented") 242# else 243# warning exception_ptr not yet implemented 244# endif 245 printf("exception_ptr not yet implemented\n"); 246 ::abort(); 247#endif 248} 249} // std 250