You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

172 lines
4.8KB

  1. // Nested Exception support header (nested_exception class) for -*- C++ -*-
  2. // Copyright (C) 2009-2020 Free Software Foundation, Inc.
  3. //
  4. // This file is part of the GNU ISO C++ Library. This library is free
  5. // software; you can redistribute it and/or modify it under the
  6. // terms of the GNU General Public License as published by the
  7. // Free Software Foundation; either version 3, or (at your option)
  8. // any later version.
  9. // This library is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. // Under Section 7 of GPL version 3, you are granted additional
  14. // permissions described in the GCC Runtime Library Exception, version
  15. // 3.1, as published by the Free Software Foundation.
  16. // You should have received a copy of the GNU General Public License and
  17. // a copy of the GCC Runtime Library Exception along with this program;
  18. // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
  19. // <http://www.gnu.org/licenses/>.
  20. /** @file bits/nested_exception.h
  21. * This is an internal header file, included by other library headers.
  22. * Do not attempt to use it directly. @headername{exception}
  23. */
  24. #ifndef _GLIBCXX_NESTED_EXCEPTION_H
  25. #define _GLIBCXX_NESTED_EXCEPTION_H 1
  26. #pragma GCC visibility push(default)
  27. #if __cplusplus < 201103L
  28. # include <bits/c++0x_warning.h>
  29. #else
  30. #include <bits/c++config.h>
  31. #include <bits/move.h>
  32. extern "C++" {
  33. namespace std
  34. {
  35. /**
  36. * @addtogroup exceptions
  37. * @{
  38. */
  39. /// Exception class with exception_ptr data member.
  40. class nested_exception
  41. {
  42. exception_ptr _M_ptr;
  43. public:
  44. nested_exception() noexcept : _M_ptr(current_exception()) { }
  45. nested_exception(const nested_exception&) noexcept = default;
  46. nested_exception& operator=(const nested_exception&) noexcept = default;
  47. virtual ~nested_exception() noexcept;
  48. [[noreturn]]
  49. void
  50. rethrow_nested() const
  51. {
  52. if (_M_ptr)
  53. rethrow_exception(_M_ptr);
  54. std::terminate();
  55. }
  56. exception_ptr
  57. nested_ptr() const noexcept
  58. { return _M_ptr; }
  59. };
  60. /// @cond undocumented
  61. template<typename _Except>
  62. struct _Nested_exception : public _Except, public nested_exception
  63. {
  64. explicit _Nested_exception(const _Except& __ex)
  65. : _Except(__ex)
  66. { }
  67. explicit _Nested_exception(_Except&& __ex)
  68. : _Except(static_cast<_Except&&>(__ex))
  69. { }
  70. };
  71. // [except.nested]/8
  72. // Throw an exception of unspecified type that is publicly derived from
  73. // both remove_reference_t<_Tp> and nested_exception.
  74. template<typename _Tp>
  75. [[noreturn]]
  76. inline void
  77. __throw_with_nested_impl(_Tp&& __t, true_type)
  78. {
  79. using _Up = typename remove_reference<_Tp>::type;
  80. throw _Nested_exception<_Up>{std::forward<_Tp>(__t)};
  81. }
  82. template<typename _Tp>
  83. [[noreturn]]
  84. inline void
  85. __throw_with_nested_impl(_Tp&& __t, false_type)
  86. { throw std::forward<_Tp>(__t); }
  87. /// @endcond
  88. /// If @p __t is derived from nested_exception, throws @p __t.
  89. /// Else, throws an implementation-defined object derived from both.
  90. template<typename _Tp>
  91. [[noreturn]]
  92. inline void
  93. throw_with_nested(_Tp&& __t)
  94. {
  95. using _Up = typename decay<_Tp>::type;
  96. using _CopyConstructible
  97. = __and_<is_copy_constructible<_Up>, is_move_constructible<_Up>>;
  98. static_assert(_CopyConstructible::value,
  99. "throw_with_nested argument must be CopyConstructible");
  100. using __nest = __and_<is_class<_Up>, __bool_constant<!__is_final(_Up)>,
  101. __not_<is_base_of<nested_exception, _Up>>>;
  102. std::__throw_with_nested_impl(std::forward<_Tp>(__t), __nest{});
  103. }
  104. /// @cond undocumented
  105. // Determine if dynamic_cast<const nested_exception&> would be well-formed.
  106. template<typename _Tp>
  107. using __rethrow_if_nested_cond = typename enable_if<
  108. __and_<is_polymorphic<_Tp>,
  109. __or_<__not_<is_base_of<nested_exception, _Tp>>,
  110. is_convertible<_Tp*, nested_exception*>>>::value
  111. >::type;
  112. // Attempt dynamic_cast to nested_exception and call rethrow_nested().
  113. template<typename _Ex>
  114. inline __rethrow_if_nested_cond<_Ex>
  115. __rethrow_if_nested_impl(const _Ex* __ptr)
  116. {
  117. if (auto __ne_ptr = dynamic_cast<const nested_exception*>(__ptr))
  118. __ne_ptr->rethrow_nested();
  119. }
  120. // Otherwise, no effects.
  121. inline void
  122. __rethrow_if_nested_impl(const void*)
  123. { }
  124. /// @endcond
  125. /// If @p __ex is derived from nested_exception, @p __ex.rethrow_nested().
  126. template<typename _Ex>
  127. inline void
  128. rethrow_if_nested(const _Ex& __ex)
  129. { std::__rethrow_if_nested_impl(std::__addressof(__ex)); }
  130. // @} group exceptions
  131. } // namespace std
  132. } // extern "C++"
  133. #endif // C++11
  134. #pragma GCC visibility pop
  135. #endif // _GLIBCXX_NESTED_EXCEPTION_H