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 14 #ifndef __has_include 15 #define __has_include(inc) 0 16 #endif 17 18 #ifdef __APPLE__ 19 #include <cxxabi.h> 20 21 using namespace __cxxabiv1; 22 #define HAVE_DEPENDENT_EH_ABI 1 23 #ifndef _LIBCPPABI_VERSION 24 using namespace __cxxabiapple; 25 // On Darwin, there are two STL shared libraries and a lower level ABI 26 // shared libray. The globals holding the current terminate handler and 27 // current unexpected handler are in the ABI library. 28 #define __terminate_handler __cxxabiapple::__cxa_terminate_handler 29 #define __unexpected_handler __cxxabiapple::__cxa_unexpected_handler 30 #endif // _LIBCPPABI_VERSION 31 #elif defined(LIBCXXRT) || __has_include(<cxxabi.h>) 32 #include <cxxabi.h> 33 using namespace __cxxabiv1; 34 #if defined(LIBCXXRT) || defined(_LIBCPPABI_VERSION) 35 #define HAVE_DEPENDENT_EH_ABI 1 36 #endif 37 #elif !defined(__GLIBCXX__) // __has_include(<cxxabi.h>) 38 static std::terminate_handler __terminate_handler; 39 static std::unexpected_handler __unexpected_handler; 40 #endif // __has_include(<cxxabi.h>) 41 42 namespace std 43 { 44 45 #if !defined(LIBCXXRT) && !defined(_LIBCPPABI_VERSION) && !defined(__GLIBCXX__) 46 47 // libcxxrt provides implementations of these functions itself. 48 unexpected_handler 49 set_unexpected(unexpected_handler func) _NOEXCEPT 50 { 51 return __sync_lock_test_and_set(&__unexpected_handler, func); 52 } 53 54 unexpected_handler 55 get_unexpected() _NOEXCEPT 56 { 57 return __sync_fetch_and_add(&__unexpected_handler, (unexpected_handler)0); 58 } 59 60 _LIBCPP_NORETURN 61 void 62 unexpected() 63 { 64 (*get_unexpected())(); 65 // unexpected handler should not return 66 terminate(); 67 } 68 69 terminate_handler 70 set_terminate(terminate_handler func) _NOEXCEPT 71 { 72 return __sync_lock_test_and_set(&__terminate_handler, func); 73 } 74 75 terminate_handler 76 get_terminate() _NOEXCEPT 77 { 78 return __sync_fetch_and_add(&__terminate_handler, (terminate_handler)0); 79 } 80 81 #ifndef EMSCRIPTEN // We provide this in JS 82 _LIBCPP_NORETURN 83 void 84 terminate() _NOEXCEPT 85 { 86 #ifndef _LIBCPP_NO_EXCEPTIONS 87 try 88 { 89 #endif // _LIBCPP_NO_EXCEPTIONS 90 (*get_terminate())(); 91 // handler should not return 92 printf("terminate_handler unexpectedly returned\n"); 93 ::abort (); 94 #ifndef _LIBCPP_NO_EXCEPTIONS 95 } 96 catch (...) 97 { 98 // handler should not throw exception 99 printf("terminate_handler unexpectedly threw an exception\n"); 100 ::abort (); 101 } 102 #endif // _LIBCPP_NO_EXCEPTIONS 103 } 104 #endif // !EMSCRIPTEN 105 #endif // !defined(LIBCXXRT) && !defined(_LIBCPPABI_VERSION) 106 107 #if !defined(LIBCXXRT) && !defined(__GLIBCXX__) && !defined(EMSCRIPTEN) 108 bool uncaught_exception() _NOEXCEPT 109 { 110 #if defined(__APPLE__) || defined(_LIBCPPABI_VERSION) 111 // on Darwin, there is a helper function so __cxa_get_globals is private 112 return __cxa_uncaught_exception(); 113 #else // __APPLE__ 114 #warning uncaught_exception not yet implemented 115 printf("uncaught_exception not yet implemented\n"); 116 ::abort(); 117 #endif // __APPLE__ 118 } 119 120 #ifndef _LIBCPPABI_VERSION 121 122 exception::~exception() _NOEXCEPT 123 { 124 } 125 126 const char* exception::what() const _NOEXCEPT 127 { 128 return "std::exception"; 129 } 130 131 #endif // _LIBCPPABI_VERSION 132 #endif //LIBCXXRT 133 #if !defined(_LIBCPPABI_VERSION) && !defined(__GLIBCXX__) 134 135 bad_exception::~bad_exception() _NOEXCEPT 136 { 137 } 138 139 const char* bad_exception::what() const _NOEXCEPT 140 { 141 return "std::bad_exception"; 142 } 143 144 #endif 145 146 147 exception_ptr::~exception_ptr() _NOEXCEPT 148 { 149 #if HAVE_DEPENDENT_EH_ABI 150 __cxa_decrement_exception_refcount(__ptr_); 151 #else 152 #warning exception_ptr not yet implemented 153 printf("exception_ptr not yet implemented\n"); 154 ::abort(); 155 #endif // __APPLE__ 156 } 157 158 exception_ptr::exception_ptr(const exception_ptr& other) _NOEXCEPT 159 : __ptr_(other.__ptr_) 160 { 161 #if HAVE_DEPENDENT_EH_ABI 162 __cxa_increment_exception_refcount(__ptr_); 163 #else 164 #warning exception_ptr not yet implemented 165 printf("exception_ptr not yet implemented\n"); 166 ::abort(); 167 #endif // __APPLE__ 168 } 169 170 exception_ptr& exception_ptr::operator=(const exception_ptr& other) _NOEXCEPT 171 { 172 #if HAVE_DEPENDENT_EH_ABI 173 if (__ptr_ != other.__ptr_) 174 { 175 __cxa_increment_exception_refcount(other.__ptr_); 176 __cxa_decrement_exception_refcount(__ptr_); 177 __ptr_ = other.__ptr_; 178 } 179 return *this; 180 #else // __APPLE__ 181 #warning exception_ptr not yet implemented 182 printf("exception_ptr not yet implemented\n"); 183 ::abort(); 184 #endif // __APPLE__ 185 } 186 187 nested_exception::nested_exception() _NOEXCEPT 188 : __ptr_(current_exception()) 189 { 190 } 191 192 nested_exception::~nested_exception() _NOEXCEPT 193 { 194 } 195 196 _LIBCPP_NORETURN 197 void 198 nested_exception::rethrow_nested() const 199 { 200 if (__ptr_ == nullptr) 201 terminate(); 202 rethrow_exception(__ptr_); 203 } 204 205 206 exception_ptr current_exception() _NOEXCEPT 207 { 208 #if HAVE_DEPENDENT_EH_ABI 209 // be nicer if there was a constructor that took a ptr, then 210 // this whole function would be just: 211 // return exception_ptr(__cxa_current_primary_exception()); 212 exception_ptr ptr; 213 ptr.__ptr_ = __cxa_current_primary_exception(); 214 return ptr; 215 #else // __APPLE__ 216 #warning exception_ptr not yet implemented 217 printf("exception_ptr not yet implemented\n"); 218 ::abort(); 219 #endif // __APPLE__ 220 } 221 222 _LIBCPP_NORETURN 223 void rethrow_exception(exception_ptr p) 224 { 225 #if HAVE_DEPENDENT_EH_ABI 226 __cxa_rethrow_primary_exception(p.__ptr_); 227 // if p.__ptr_ is NULL, above returns so we terminate 228 terminate(); 229 #else // __APPLE__ 230 #warning exception_ptr not yet implemented 231 printf("exception_ptr not yet implemented\n"); 232 ::abort(); 233 #endif // __APPLE__ 234 } 235 } // std 236