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 #if defined(_LIBCPP_ABI_MICROSOFT) 16 #include <eh.h> 17 #include <corecrt_terminate.h> 18 #elif defined(__APPLE__) && !defined(LIBCXXRT) && \ 19 !defined(_LIBCPP_BUILDING_HAS_NO_ABI_LIBRARY) 20 #include <cxxabi.h> 21 22 using namespace __cxxabiv1; 23 #define HAVE_DEPENDENT_EH_ABI 1 24 #ifndef _LIBCPPABI_VERSION 25 using namespace __cxxabiapple; 26 // On Darwin, there are two STL shared libraries and a lower level ABI 27 // shared library. The globals holding the current terminate handler and 28 // current unexpected handler are in the ABI library. 29 #define __terminate_handler __cxxabiapple::__cxa_terminate_handler 30 #define __unexpected_handler __cxxabiapple::__cxa_unexpected_handler 31 #endif // _LIBCPPABI_VERSION 32 #elif defined(LIBCXXRT) || defined(LIBCXX_BUILDING_LIBCXXABI) 33 #include <cxxabi.h> 34 using namespace __cxxabiv1; 35 #if defined(LIBCXXRT) || defined(_LIBCPPABI_VERSION) 36 #define HAVE_DEPENDENT_EH_ABI 1 37 #endif 38 #elif !defined(__GLIBCXX__) // defined(LIBCXX_BUILDING_LIBCXXABI) 39 _LIBCPP_SAFE_STATIC static std::terminate_handler __terminate_handler; 40 _LIBCPP_SAFE_STATIC static std::unexpected_handler __unexpected_handler; 41 #endif // defined(LIBCXX_BUILDING_LIBCXXABI) 42 43 namespace std 44 { 45 46 #if !defined(LIBCXXRT) && !defined(_LIBCPPABI_VERSION) && !defined(__GLIBCXX__) 47 48 // libcxxrt provides implementations of these functions itself. 49 unexpected_handler 50 set_unexpected(unexpected_handler func) _NOEXCEPT 51 { 52 #if defined(_LIBCPP_ABI_MICROSOFT) 53 return ::set_unexpected(func); 54 #else 55 return __sync_lock_test_and_set(&__unexpected_handler, func); 56 #endif 57 } 58 59 unexpected_handler 60 get_unexpected() _NOEXCEPT 61 { 62 #if defined(_LIBCPP_ABI_MICROSOFT) 63 return ::_get_unexpected(); 64 #else 65 return __sync_fetch_and_add(&__unexpected_handler, (unexpected_handler)0); 66 #endif 67 } 68 69 _LIBCPP_NORETURN 70 void 71 unexpected() 72 { 73 (*get_unexpected())(); 74 // unexpected handler should not return 75 terminate(); 76 } 77 78 terminate_handler 79 set_terminate(terminate_handler func) _NOEXCEPT 80 { 81 #if defined(_LIBCPP_ABI_MICROSOFT) 82 return ::set_terminate(func); 83 #else 84 return __sync_lock_test_and_set(&__terminate_handler, func); 85 #endif 86 } 87 88 terminate_handler 89 get_terminate() _NOEXCEPT 90 { 91 #if defined(_LIBCPP_ABI_MICROSOFT) 92 return ::_get_terminate(); 93 #else 94 return __sync_fetch_and_add(&__terminate_handler, (terminate_handler)0); 95 #endif 96 } 97 98 #ifndef __EMSCRIPTEN__ // We provide this in JS 99 _LIBCPP_NORETURN 100 void 101 terminate() _NOEXCEPT 102 { 103 #ifndef _LIBCPP_NO_EXCEPTIONS 104 try 105 { 106 #endif // _LIBCPP_NO_EXCEPTIONS 107 (*get_terminate())(); 108 // handler should not return 109 fprintf(stderr, "terminate_handler unexpectedly returned\n"); 110 ::abort(); 111 #ifndef _LIBCPP_NO_EXCEPTIONS 112 } 113 catch (...) 114 { 115 // handler should not throw exception 116 fprintf(stderr, "terminate_handler unexpectedly threw an exception\n"); 117 ::abort(); 118 } 119 #endif // _LIBCPP_NO_EXCEPTIONS 120 } 121 #endif // !__EMSCRIPTEN__ 122 #endif // !defined(LIBCXXRT) && !defined(_LIBCPPABI_VERSION) 123 124 #if !defined(LIBCXXRT) && !defined(__GLIBCXX__) && !defined(__EMSCRIPTEN__) 125 126 bool uncaught_exception() _NOEXCEPT { return uncaught_exceptions() > 0; } 127 128 int uncaught_exceptions() _NOEXCEPT 129 { 130 #if !defined(_LIBCPP_BUILDING_HAS_NO_ABI_LIBRARY) && \ 131 (defined(__APPLE__) || defined(_LIBCPPABI_VERSION)) 132 // on Darwin, there is a helper function so __cxa_get_globals is private 133 # if _LIBCPPABI_VERSION > 1101 134 return __cxa_uncaught_exceptions(); 135 # else 136 return __cxa_uncaught_exception() ? 1 : 0; 137 # endif 138 #elif defined(_LIBCPP_ABI_MICROSOFT) 139 return __uncaught_exceptions(); 140 #else 141 # if defined(_MSC_VER) && ! defined(__clang__) 142 _LIBCPP_WARNING("uncaught_exceptions not yet implemented") 143 # else 144 # warning uncaught_exception not yet implemented 145 # endif 146 fprintf(stderr, "uncaught_exceptions not yet implemented\n"); 147 ::abort(); 148 #endif // __APPLE__ 149 } 150 151 152 #ifndef _LIBCPPABI_VERSION 153 154 exception::~exception() _NOEXCEPT 155 { 156 } 157 158 const char* exception::what() const _NOEXCEPT 159 { 160 return "std::exception"; 161 } 162 163 #endif // _LIBCPPABI_VERSION 164 #endif //LIBCXXRT 165 #if !defined(_LIBCPPABI_VERSION) && !defined(__GLIBCXX__) 166 167 bad_exception::~bad_exception() _NOEXCEPT 168 { 169 } 170 171 const char* bad_exception::what() const _NOEXCEPT 172 { 173 return "std::bad_exception"; 174 } 175 176 #endif 177 178 #if defined(__GLIBCXX__) 179 180 // libsupc++ does not implement the dependent EH ABI and the functionality 181 // it uses to implement std::exception_ptr (which it declares as an alias of 182 // std::__exception_ptr::exception_ptr) is not directly exported to clients. So 183 // we have little choice but to hijack std::__exception_ptr::exception_ptr's 184 // (which fortunately has the same layout as our std::exception_ptr) copy 185 // constructor, assignment operator and destructor (which are part of its 186 // stable ABI), and its rethrow_exception(std::__exception_ptr::exception_ptr) 187 // function. 188 189 namespace __exception_ptr 190 { 191 192 struct exception_ptr 193 { 194 void* __ptr_; 195 196 exception_ptr(const exception_ptr&) _NOEXCEPT; 197 exception_ptr& operator=(const exception_ptr&) _NOEXCEPT; 198 ~exception_ptr() _NOEXCEPT; 199 }; 200 201 } 202 203 _LIBCPP_NORETURN void rethrow_exception(__exception_ptr::exception_ptr); 204 205 #endif 206 207 exception_ptr::~exception_ptr() _NOEXCEPT 208 { 209 #if HAVE_DEPENDENT_EH_ABI 210 __cxa_decrement_exception_refcount(__ptr_); 211 #elif defined(__GLIBCXX__) 212 reinterpret_cast<__exception_ptr::exception_ptr*>(this)->~exception_ptr(); 213 #else 214 # if defined(_MSC_VER) && ! defined(__clang__) 215 _LIBCPP_WARNING("exception_ptr not yet implemented") 216 # else 217 # warning exception_ptr not yet implemented 218 # endif 219 fprintf(stderr, "exception_ptr not yet implemented\n"); 220 ::abort(); 221 #endif 222 } 223 224 exception_ptr::exception_ptr(const exception_ptr& other) _NOEXCEPT 225 : __ptr_(other.__ptr_) 226 { 227 #if HAVE_DEPENDENT_EH_ABI 228 __cxa_increment_exception_refcount(__ptr_); 229 #elif defined(__GLIBCXX__) 230 new (reinterpret_cast<void*>(this)) __exception_ptr::exception_ptr( 231 reinterpret_cast<const __exception_ptr::exception_ptr&>(other)); 232 #else 233 # if defined(_MSC_VER) && ! defined(__clang__) 234 _LIBCPP_WARNING("exception_ptr not yet implemented") 235 # else 236 # warning exception_ptr not yet implemented 237 # endif 238 fprintf(stderr, "exception_ptr not yet implemented\n"); 239 ::abort(); 240 #endif 241 } 242 243 exception_ptr& exception_ptr::operator=(const exception_ptr& other) _NOEXCEPT 244 { 245 #if HAVE_DEPENDENT_EH_ABI 246 if (__ptr_ != other.__ptr_) 247 { 248 __cxa_increment_exception_refcount(other.__ptr_); 249 __cxa_decrement_exception_refcount(__ptr_); 250 __ptr_ = other.__ptr_; 251 } 252 return *this; 253 #elif defined(__GLIBCXX__) 254 *reinterpret_cast<__exception_ptr::exception_ptr*>(this) = 255 reinterpret_cast<const __exception_ptr::exception_ptr&>(other); 256 return *this; 257 #else 258 # if defined(_MSC_VER) && ! defined(__clang__) 259 _LIBCPP_WARNING("exception_ptr not yet implemented") 260 # else 261 # warning exception_ptr not yet implemented 262 # endif 263 fprintf(stderr, "exception_ptr not yet implemented\n"); 264 ::abort(); 265 #endif 266 } 267 268 nested_exception::nested_exception() _NOEXCEPT 269 : __ptr_(current_exception()) 270 { 271 } 272 273 #if !defined(__GLIBCXX__) 274 275 nested_exception::~nested_exception() _NOEXCEPT 276 { 277 } 278 279 #endif 280 281 _LIBCPP_NORETURN 282 void 283 nested_exception::rethrow_nested() const 284 { 285 if (__ptr_ == nullptr) 286 terminate(); 287 rethrow_exception(__ptr_); 288 } 289 290 #if !defined(__GLIBCXX__) 291 292 exception_ptr current_exception() _NOEXCEPT 293 { 294 #if HAVE_DEPENDENT_EH_ABI 295 // be nicer if there was a constructor that took a ptr, then 296 // this whole function would be just: 297 // return exception_ptr(__cxa_current_primary_exception()); 298 exception_ptr ptr; 299 ptr.__ptr_ = __cxa_current_primary_exception(); 300 return ptr; 301 #else 302 # if defined(_MSC_VER) && ! defined(__clang__) 303 _LIBCPP_WARNING( "exception_ptr not yet implemented" ) 304 # else 305 # warning exception_ptr not yet implemented 306 # endif 307 fprintf(stderr, "exception_ptr not yet implemented\n"); 308 ::abort(); 309 #endif 310 } 311 312 #endif // !__GLIBCXX__ 313 314 _LIBCPP_NORETURN 315 void rethrow_exception(exception_ptr p) 316 { 317 #if HAVE_DEPENDENT_EH_ABI 318 __cxa_rethrow_primary_exception(p.__ptr_); 319 // if p.__ptr_ is NULL, above returns so we terminate 320 terminate(); 321 #elif defined(__GLIBCXX__) 322 rethrow_exception(reinterpret_cast<__exception_ptr::exception_ptr&>(p)); 323 #else 324 # if defined(_MSC_VER) && ! defined(__clang__) 325 _LIBCPP_WARNING("exception_ptr not yet implemented") 326 # else 327 # warning exception_ptr not yet implemented 328 # endif 329 fprintf(stderr, "exception_ptr not yet implemented\n"); 330 ::abort(); 331 #endif 332 } 333 } // std 334