exception.cpp revision 314564
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 43namespace std 44{ 45 46#if !defined(LIBCXXRT) && !defined(_LIBCPPABI_VERSION) && !defined(__GLIBCXX__) 47 48// libcxxrt provides implementations of these functions itself. 49unexpected_handler 50set_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 59unexpected_handler 60get_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 70void 71unexpected() 72{ 73 (*get_unexpected())(); 74 // unexpected handler should not return 75 terminate(); 76} 77 78terminate_handler 79set_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 88terminate_handler 89get_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 100void 101terminate() _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 126bool uncaught_exception() _NOEXCEPT { return uncaught_exceptions() > 0; } 127 128int 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 154exception::~exception() _NOEXCEPT 155{ 156} 157 158const 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 167bad_exception::~bad_exception() _NOEXCEPT 168{ 169} 170 171const 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 189namespace __exception_ptr 190{ 191 192struct 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 207exception_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 224exception_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 243exception_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 268nested_exception::nested_exception() _NOEXCEPT 269 : __ptr_(current_exception()) 270{ 271} 272 273#if !defined(__GLIBCXX__) 274 275nested_exception::~nested_exception() _NOEXCEPT 276{ 277} 278 279#endif 280 281_LIBCPP_NORETURN 282void 283nested_exception::rethrow_nested() const 284{ 285 if (__ptr_ == nullptr) 286 terminate(); 287 rethrow_exception(__ptr_); 288} 289 290#if !defined(__GLIBCXX__) 291 292exception_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 315void 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