exception_ptr.h 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. // Exception Handling support header (exception_ptr class) for -*- C++ -*-
  2. // Copyright (C) 2008-2023 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. #include <bits/c++config.h>
  30. #include <bits/exception_defines.h>
  31. #include <bits/cxxabi_init_exception.h>
  32. #include <typeinfo>
  33. #include <new>
  34. #if __cplusplus >= 201103L
  35. # include <bits/move.h>
  36. #endif
  37. #ifdef _GLIBCXX_EH_PTR_RELOPS_COMPAT
  38. # define _GLIBCXX_EH_PTR_USED __attribute__((__used__))
  39. #else
  40. # define _GLIBCXX_EH_PTR_USED
  41. #endif
  42. extern "C++" {
  43. namespace std _GLIBCXX_VISIBILITY(default)
  44. {
  45. class type_info;
  46. /**
  47. * @addtogroup exceptions
  48. * @{
  49. */
  50. namespace __exception_ptr
  51. {
  52. class exception_ptr;
  53. }
  54. using __exception_ptr::exception_ptr;
  55. /** Obtain an exception_ptr to the currently handled exception.
  56. *
  57. * If there is none, or the currently handled exception is foreign,
  58. * return the null value.
  59. *
  60. * @since C++11
  61. */
  62. exception_ptr current_exception() _GLIBCXX_USE_NOEXCEPT;
  63. template<typename _Ex>
  64. exception_ptr make_exception_ptr(_Ex) _GLIBCXX_USE_NOEXCEPT;
  65. /// Throw the object pointed to by the exception_ptr.
  66. void rethrow_exception(exception_ptr) __attribute__ ((__noreturn__));
  67. namespace __exception_ptr
  68. {
  69. using std::rethrow_exception; // So that ADL finds it.
  70. /**
  71. * @brief An opaque pointer to an arbitrary exception.
  72. *
  73. * The actual name of this type is unspecified, so the alias
  74. * `std::exception_ptr` should be used to refer to it.
  75. *
  76. * @headerfile exception
  77. * @since C++11 (but usable in C++98 as a GCC extension)
  78. * @ingroup exceptions
  79. */
  80. class exception_ptr
  81. {
  82. void* _M_exception_object;
  83. explicit exception_ptr(void* __e) _GLIBCXX_USE_NOEXCEPT;
  84. void _M_addref() _GLIBCXX_USE_NOEXCEPT;
  85. void _M_release() _GLIBCXX_USE_NOEXCEPT;
  86. void *_M_get() const _GLIBCXX_NOEXCEPT __attribute__ ((__pure__));
  87. friend exception_ptr std::current_exception() _GLIBCXX_USE_NOEXCEPT;
  88. friend void std::rethrow_exception(exception_ptr);
  89. template<typename _Ex>
  90. friend exception_ptr std::make_exception_ptr(_Ex) _GLIBCXX_USE_NOEXCEPT;
  91. public:
  92. exception_ptr() _GLIBCXX_USE_NOEXCEPT;
  93. exception_ptr(const exception_ptr&) _GLIBCXX_USE_NOEXCEPT;
  94. #if __cplusplus >= 201103L
  95. exception_ptr(nullptr_t) noexcept
  96. : _M_exception_object(nullptr)
  97. { }
  98. exception_ptr(exception_ptr&& __o) noexcept
  99. : _M_exception_object(__o._M_exception_object)
  100. { __o._M_exception_object = nullptr; }
  101. #endif
  102. #if (__cplusplus < 201103L) || defined (_GLIBCXX_EH_PTR_COMPAT)
  103. typedef void (exception_ptr::*__safe_bool)();
  104. // For construction from nullptr or 0.
  105. exception_ptr(__safe_bool) _GLIBCXX_USE_NOEXCEPT;
  106. #endif
  107. exception_ptr&
  108. operator=(const exception_ptr&) _GLIBCXX_USE_NOEXCEPT;
  109. #if __cplusplus >= 201103L
  110. exception_ptr&
  111. operator=(exception_ptr&& __o) noexcept
  112. {
  113. exception_ptr(static_cast<exception_ptr&&>(__o)).swap(*this);
  114. return *this;
  115. }
  116. #endif
  117. ~exception_ptr() _GLIBCXX_USE_NOEXCEPT;
  118. void
  119. swap(exception_ptr&) _GLIBCXX_USE_NOEXCEPT;
  120. #ifdef _GLIBCXX_EH_PTR_COMPAT
  121. // Retained for compatibility with CXXABI_1.3.
  122. void _M_safe_bool_dummy() _GLIBCXX_USE_NOEXCEPT
  123. __attribute__ ((__const__));
  124. bool operator!() const _GLIBCXX_USE_NOEXCEPT
  125. __attribute__ ((__pure__));
  126. operator __safe_bool() const _GLIBCXX_USE_NOEXCEPT;
  127. #endif
  128. #if __cplusplus >= 201103L
  129. explicit operator bool() const noexcept
  130. { return _M_exception_object; }
  131. #endif
  132. #if __cpp_impl_three_way_comparison >= 201907L \
  133. && ! defined _GLIBCXX_EH_PTR_RELOPS_COMPAT
  134. friend bool
  135. operator==(const exception_ptr&, const exception_ptr&) noexcept = default;
  136. #else
  137. friend _GLIBCXX_EH_PTR_USED bool
  138. operator==(const exception_ptr& __x, const exception_ptr& __y)
  139. _GLIBCXX_USE_NOEXCEPT
  140. { return __x._M_exception_object == __y._M_exception_object; }
  141. friend _GLIBCXX_EH_PTR_USED bool
  142. operator!=(const exception_ptr& __x, const exception_ptr& __y)
  143. _GLIBCXX_USE_NOEXCEPT
  144. { return __x._M_exception_object != __y._M_exception_object; }
  145. #endif
  146. const class std::type_info*
  147. __cxa_exception_type() const _GLIBCXX_USE_NOEXCEPT
  148. __attribute__ ((__pure__));
  149. };
  150. _GLIBCXX_EH_PTR_USED
  151. inline
  152. exception_ptr::exception_ptr() _GLIBCXX_USE_NOEXCEPT
  153. : _M_exception_object(0)
  154. { }
  155. _GLIBCXX_EH_PTR_USED
  156. inline
  157. exception_ptr::exception_ptr(const exception_ptr& __other)
  158. _GLIBCXX_USE_NOEXCEPT
  159. : _M_exception_object(__other._M_exception_object)
  160. {
  161. if (_M_exception_object)
  162. _M_addref();
  163. }
  164. _GLIBCXX_EH_PTR_USED
  165. inline
  166. exception_ptr::~exception_ptr() _GLIBCXX_USE_NOEXCEPT
  167. {
  168. if (_M_exception_object)
  169. _M_release();
  170. }
  171. _GLIBCXX_EH_PTR_USED
  172. inline exception_ptr&
  173. exception_ptr::operator=(const exception_ptr& __other) _GLIBCXX_USE_NOEXCEPT
  174. {
  175. exception_ptr(__other).swap(*this);
  176. return *this;
  177. }
  178. _GLIBCXX_EH_PTR_USED
  179. inline void
  180. exception_ptr::swap(exception_ptr &__other) _GLIBCXX_USE_NOEXCEPT
  181. {
  182. void *__tmp = _M_exception_object;
  183. _M_exception_object = __other._M_exception_object;
  184. __other._M_exception_object = __tmp;
  185. }
  186. /// @relates exception_ptr
  187. inline void
  188. swap(exception_ptr& __lhs, exception_ptr& __rhs)
  189. { __lhs.swap(__rhs); }
  190. /// @cond undocumented
  191. template<typename _Ex>
  192. _GLIBCXX_CDTOR_CALLABI
  193. inline void
  194. __dest_thunk(void* __x)
  195. { static_cast<_Ex*>(__x)->~_Ex(); }
  196. /// @endcond
  197. } // namespace __exception_ptr
  198. using __exception_ptr::swap; // So that std::swap(exp1, exp2) finds it.
  199. /// Obtain an exception_ptr pointing to a copy of the supplied object.
  200. #if (__cplusplus >= 201103L && __cpp_rtti) || __cpp_exceptions
  201. template<typename _Ex>
  202. exception_ptr
  203. make_exception_ptr(_Ex __ex) _GLIBCXX_USE_NOEXCEPT
  204. {
  205. #if __cplusplus >= 201103L && __cpp_rtti
  206. using _Ex2 = typename decay<_Ex>::type;
  207. void* __e = __cxxabiv1::__cxa_allocate_exception(sizeof(_Ex));
  208. (void) __cxxabiv1::__cxa_init_primary_exception(
  209. __e, const_cast<std::type_info*>(&typeid(_Ex)),
  210. __exception_ptr::__dest_thunk<_Ex2>);
  211. __try
  212. {
  213. ::new (__e) _Ex2(__ex);
  214. return exception_ptr(__e);
  215. }
  216. __catch(...)
  217. {
  218. __cxxabiv1::__cxa_free_exception(__e);
  219. return current_exception();
  220. }
  221. #else
  222. try
  223. {
  224. throw __ex;
  225. }
  226. catch(...)
  227. {
  228. return current_exception();
  229. }
  230. #endif
  231. }
  232. #else // no RTTI and no exceptions
  233. // This is always_inline so the linker will never use this useless definition
  234. // instead of a working one compiled with RTTI and/or exceptions enabled.
  235. template<typename _Ex>
  236. __attribute__ ((__always_inline__))
  237. inline exception_ptr
  238. make_exception_ptr(_Ex) _GLIBCXX_USE_NOEXCEPT
  239. { return exception_ptr(); }
  240. #endif
  241. #undef _GLIBCXX_EH_PTR_USED
  242. /// @} group exceptions
  243. } // namespace std
  244. } // extern "C++"
  245. #endif