exception_ptr.h 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. // Exception Handling support header (exception_ptr class) for -*- C++ -*-
  2. // Copyright (C) 2008-2022 Free Software Foundation, Inc.
  3. //
  4. // This file is part of GCC.
  5. //
  6. // GCC is free software; you can redistribute it and/or modify
  7. // it under the terms of the GNU General Public License as published by
  8. // the Free Software Foundation; either version 3, or (at your option)
  9. // any later version.
  10. //
  11. // GCC is distributed in the hope that it will be useful,
  12. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. // GNU General Public License for more details.
  15. //
  16. // Under Section 7 of GPL version 3, you are granted additional
  17. // permissions described in the GCC Runtime Library Exception, version
  18. // 3.1, as published by the Free Software Foundation.
  19. // You should have received a copy of the GNU General Public License and
  20. // a copy of the GCC Runtime Library Exception along with this program;
  21. // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
  22. // <http://www.gnu.org/licenses/>.
  23. /** @file bits/exception_ptr.h
  24. * This is an internal header file, included by other library headers.
  25. * Do not attempt to use it directly. @headername{exception}
  26. */
  27. #ifndef _EXCEPTION_PTR_H
  28. #define _EXCEPTION_PTR_H
  29. #pragma GCC visibility push(default)
  30. #include <bits/c++config.h>
  31. #include <bits/exception_defines.h>
  32. #include <bits/cxxabi_init_exception.h>
  33. #include <typeinfo>
  34. #include <new>
  35. #if __cplusplus >= 201103L
  36. # include <bits/move.h>
  37. #endif
  38. #ifdef _GLIBCXX_EH_PTR_RELOPS_COMPAT
  39. # define _GLIBCXX_EH_PTR_USED __attribute__((__used__))
  40. #else
  41. # define _GLIBCXX_EH_PTR_USED
  42. #endif
  43. extern "C++" {
  44. namespace std
  45. {
  46. class type_info;
  47. /**
  48. * @addtogroup exceptions
  49. * @{
  50. */
  51. namespace __exception_ptr
  52. {
  53. class exception_ptr;
  54. }
  55. using __exception_ptr::exception_ptr;
  56. /** Obtain an exception_ptr to the currently handled exception. If there
  57. * is none, or the currently handled exception is foreign, return the null
  58. * value.
  59. */
  60. exception_ptr current_exception() _GLIBCXX_USE_NOEXCEPT;
  61. template<typename _Ex>
  62. exception_ptr make_exception_ptr(_Ex) _GLIBCXX_USE_NOEXCEPT;
  63. /// Throw the object pointed to by the exception_ptr.
  64. void rethrow_exception(exception_ptr) __attribute__ ((__noreturn__));
  65. namespace __exception_ptr
  66. {
  67. using std::rethrow_exception;
  68. /**
  69. * @brief An opaque pointer to an arbitrary exception.
  70. * @ingroup exceptions
  71. */
  72. class exception_ptr
  73. {
  74. void* _M_exception_object;
  75. explicit exception_ptr(void* __e) _GLIBCXX_USE_NOEXCEPT;
  76. void _M_addref() _GLIBCXX_USE_NOEXCEPT;
  77. void _M_release() _GLIBCXX_USE_NOEXCEPT;
  78. void *_M_get() const _GLIBCXX_NOEXCEPT __attribute__ ((__pure__));
  79. friend exception_ptr std::current_exception() _GLIBCXX_USE_NOEXCEPT;
  80. friend void std::rethrow_exception(exception_ptr);
  81. template<typename _Ex>
  82. friend exception_ptr std::make_exception_ptr(_Ex) _GLIBCXX_USE_NOEXCEPT;
  83. public:
  84. exception_ptr() _GLIBCXX_USE_NOEXCEPT;
  85. exception_ptr(const exception_ptr&) _GLIBCXX_USE_NOEXCEPT;
  86. #if __cplusplus >= 201103L
  87. exception_ptr(nullptr_t) noexcept
  88. : _M_exception_object(nullptr)
  89. { }
  90. exception_ptr(exception_ptr&& __o) noexcept
  91. : _M_exception_object(__o._M_exception_object)
  92. { __o._M_exception_object = nullptr; }
  93. #endif
  94. #if (__cplusplus < 201103L) || defined (_GLIBCXX_EH_PTR_COMPAT)
  95. typedef void (exception_ptr::*__safe_bool)();
  96. // For construction from nullptr or 0.
  97. exception_ptr(__safe_bool) _GLIBCXX_USE_NOEXCEPT;
  98. #endif
  99. exception_ptr&
  100. operator=(const exception_ptr&) _GLIBCXX_USE_NOEXCEPT;
  101. #if __cplusplus >= 201103L
  102. exception_ptr&
  103. operator=(exception_ptr&& __o) noexcept
  104. {
  105. exception_ptr(static_cast<exception_ptr&&>(__o)).swap(*this);
  106. return *this;
  107. }
  108. #endif
  109. ~exception_ptr() _GLIBCXX_USE_NOEXCEPT;
  110. void
  111. swap(exception_ptr&) _GLIBCXX_USE_NOEXCEPT;
  112. #ifdef _GLIBCXX_EH_PTR_COMPAT
  113. // Retained for compatibility with CXXABI_1.3.
  114. void _M_safe_bool_dummy() _GLIBCXX_USE_NOEXCEPT
  115. __attribute__ ((__const__));
  116. bool operator!() const _GLIBCXX_USE_NOEXCEPT
  117. __attribute__ ((__pure__));
  118. operator __safe_bool() const _GLIBCXX_USE_NOEXCEPT;
  119. #endif
  120. #if __cplusplus >= 201103L
  121. explicit operator bool() const noexcept
  122. { return _M_exception_object; }
  123. #endif
  124. #if __cpp_impl_three_way_comparison >= 201907L \
  125. && ! defined _GLIBCXX_EH_PTR_RELOPS_COMPAT
  126. friend bool
  127. operator==(const exception_ptr&, const exception_ptr&) noexcept = default;
  128. #else
  129. friend _GLIBCXX_EH_PTR_USED bool
  130. operator==(const exception_ptr& __x, const exception_ptr& __y)
  131. _GLIBCXX_USE_NOEXCEPT
  132. { return __x._M_exception_object == __y._M_exception_object; }
  133. friend _GLIBCXX_EH_PTR_USED bool
  134. operator!=(const exception_ptr& __x, const exception_ptr& __y)
  135. _GLIBCXX_USE_NOEXCEPT
  136. { return __x._M_exception_object != __y._M_exception_object; }
  137. #endif
  138. const class std::type_info*
  139. __cxa_exception_type() const _GLIBCXX_USE_NOEXCEPT
  140. __attribute__ ((__pure__));
  141. };
  142. _GLIBCXX_EH_PTR_USED
  143. inline
  144. exception_ptr::exception_ptr() _GLIBCXX_USE_NOEXCEPT
  145. : _M_exception_object(0)
  146. { }
  147. _GLIBCXX_EH_PTR_USED
  148. inline
  149. exception_ptr::exception_ptr(const exception_ptr& __other)
  150. _GLIBCXX_USE_NOEXCEPT
  151. : _M_exception_object(__other._M_exception_object)
  152. {
  153. if (_M_exception_object)
  154. _M_addref();
  155. }
  156. _GLIBCXX_EH_PTR_USED
  157. inline
  158. exception_ptr::~exception_ptr() _GLIBCXX_USE_NOEXCEPT
  159. {
  160. if (_M_exception_object)
  161. _M_release();
  162. }
  163. _GLIBCXX_EH_PTR_USED
  164. inline exception_ptr&
  165. exception_ptr::operator=(const exception_ptr& __other) _GLIBCXX_USE_NOEXCEPT
  166. {
  167. exception_ptr(__other).swap(*this);
  168. return *this;
  169. }
  170. _GLIBCXX_EH_PTR_USED
  171. inline void
  172. exception_ptr::swap(exception_ptr &__other) _GLIBCXX_USE_NOEXCEPT
  173. {
  174. void *__tmp = _M_exception_object;
  175. _M_exception_object = __other._M_exception_object;
  176. __other._M_exception_object = __tmp;
  177. }
  178. /// @relates exception_ptr
  179. inline void
  180. swap(exception_ptr& __lhs, exception_ptr& __rhs)
  181. { __lhs.swap(__rhs); }
  182. /// @cond undocumented
  183. template<typename _Ex>
  184. _GLIBCXX_CDTOR_CALLABI
  185. inline void
  186. __dest_thunk(void* __x)
  187. { static_cast<_Ex*>(__x)->~_Ex(); }
  188. /// @endcond
  189. } // namespace __exception_ptr
  190. /// Obtain an exception_ptr pointing to a copy of the supplied object.
  191. #if (__cplusplus >= 201103L && __cpp_rtti) || __cpp_exceptions
  192. template<typename _Ex>
  193. exception_ptr
  194. make_exception_ptr(_Ex __ex) _GLIBCXX_USE_NOEXCEPT
  195. {
  196. #if __cplusplus >= 201103L && __cpp_rtti
  197. using _Ex2 = typename decay<_Ex>::type;
  198. void* __e = __cxxabiv1::__cxa_allocate_exception(sizeof(_Ex));
  199. (void) __cxxabiv1::__cxa_init_primary_exception(
  200. __e, const_cast<std::type_info*>(&typeid(_Ex)),
  201. __exception_ptr::__dest_thunk<_Ex2>);
  202. __try
  203. {
  204. ::new (__e) _Ex2(__ex);
  205. return exception_ptr(__e);
  206. }
  207. __catch(...)
  208. {
  209. __cxxabiv1::__cxa_free_exception(__e);
  210. return current_exception();
  211. }
  212. #else
  213. try
  214. {
  215. throw __ex;
  216. }
  217. catch(...)
  218. {
  219. return current_exception();
  220. }
  221. #endif
  222. }
  223. #else // no RTTI and no exceptions
  224. // This is always_inline so the linker will never use this useless definition
  225. // instead of a working one compiled with RTTI and/or exceptions enabled.
  226. template<typename _Ex>
  227. __attribute__ ((__always_inline__))
  228. exception_ptr
  229. make_exception_ptr(_Ex) _GLIBCXX_USE_NOEXCEPT
  230. { return exception_ptr(); }
  231. #endif
  232. #undef _GLIBCXX_EH_PTR_USED
  233. /// @} group exceptions
  234. } // namespace std
  235. } // extern "C++"
  236. #pragma GCC visibility pop
  237. #endif