exception.cpp 9.0 KB

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