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