|  | // Nested Exception support header (nested_exception class) for -*- C++ -*- | 
|  |  | 
|  | // Copyright (C) 2009-2021 Free Software Foundation, Inc. | 
|  | // | 
|  | // This file is part of the GNU ISO C++ Library.  This library is free | 
|  | // software; you can redistribute it and/or modify it under the | 
|  | // terms of the GNU General Public License as published by the | 
|  | // Free Software Foundation; either version 3, or (at your option) | 
|  | // any later version. | 
|  |  | 
|  | // This library is distributed in the hope that it will be useful, | 
|  | // but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
|  | // GNU General Public License for more details. | 
|  |  | 
|  | // Under Section 7 of GPL version 3, you are granted additional | 
|  | // permissions described in the GCC Runtime Library Exception, version | 
|  | // 3.1, as published by the Free Software Foundation. | 
|  |  | 
|  | // You should have received a copy of the GNU General Public License and | 
|  | // a copy of the GCC Runtime Library Exception along with this program; | 
|  | // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see | 
|  | // <http://www.gnu.org/licenses/>. | 
|  |  | 
|  | /** @file bits/nested_exception.h | 
|  | *  This is an internal header file, included by other library headers. | 
|  | *  Do not attempt to use it directly. @headername{exception} | 
|  | */ | 
|  |  | 
|  | #ifndef _GLIBCXX_NESTED_EXCEPTION_H | 
|  | #define _GLIBCXX_NESTED_EXCEPTION_H 1 | 
|  |  | 
|  | #pragma GCC visibility push(default) | 
|  |  | 
|  | #if __cplusplus < 201103L | 
|  | # include <bits/c++0x_warning.h> | 
|  | #else | 
|  |  | 
|  | #include <bits/c++config.h> | 
|  | #include <bits/move.h> | 
|  |  | 
|  | extern "C++" { | 
|  |  | 
|  | namespace std | 
|  | { | 
|  | /** | 
|  | * @addtogroup exceptions | 
|  | * @{ | 
|  | */ | 
|  |  | 
|  | /// Exception class with exception_ptr data member. | 
|  | class nested_exception | 
|  | { | 
|  | exception_ptr _M_ptr; | 
|  |  | 
|  | public: | 
|  | nested_exception() noexcept : _M_ptr(current_exception()) { } | 
|  |  | 
|  | nested_exception(const nested_exception&) noexcept = default; | 
|  |  | 
|  | nested_exception& operator=(const nested_exception&) noexcept = default; | 
|  |  | 
|  | virtual ~nested_exception() noexcept; | 
|  |  | 
|  | [[noreturn]] | 
|  | void | 
|  | rethrow_nested() const | 
|  | { | 
|  | if (_M_ptr) | 
|  | rethrow_exception(_M_ptr); | 
|  | std::terminate(); | 
|  | } | 
|  |  | 
|  | exception_ptr | 
|  | nested_ptr() const noexcept | 
|  | { return _M_ptr; } | 
|  | }; | 
|  |  | 
|  | /// @cond undocumented | 
|  |  | 
|  | template<typename _Except> | 
|  | struct _Nested_exception : public _Except, public nested_exception | 
|  | { | 
|  | explicit _Nested_exception(const _Except& __ex) | 
|  | : _Except(__ex) | 
|  | { } | 
|  |  | 
|  | explicit _Nested_exception(_Except&& __ex) | 
|  | : _Except(static_cast<_Except&&>(__ex)) | 
|  | { } | 
|  | }; | 
|  |  | 
|  | // [except.nested]/8 | 
|  | // Throw an exception of unspecified type that is publicly derived from | 
|  | // both remove_reference_t<_Tp> and nested_exception. | 
|  | template<typename _Tp> | 
|  | [[noreturn]] | 
|  | inline void | 
|  | __throw_with_nested_impl(_Tp&& __t, true_type) | 
|  | { | 
|  | using _Up = typename remove_reference<_Tp>::type; | 
|  | throw _Nested_exception<_Up>{std::forward<_Tp>(__t)}; | 
|  | } | 
|  |  | 
|  | template<typename _Tp> | 
|  | [[noreturn]] | 
|  | inline void | 
|  | __throw_with_nested_impl(_Tp&& __t, false_type) | 
|  | { throw std::forward<_Tp>(__t); } | 
|  |  | 
|  | /// @endcond | 
|  |  | 
|  | /// If @p __t is derived from nested_exception, throws @p __t. | 
|  | /// Else, throws an implementation-defined object derived from both. | 
|  | template<typename _Tp> | 
|  | [[noreturn]] | 
|  | inline void | 
|  | throw_with_nested(_Tp&& __t) | 
|  | { | 
|  | using _Up = typename decay<_Tp>::type; | 
|  | using _CopyConstructible | 
|  | = __and_<is_copy_constructible<_Up>, is_move_constructible<_Up>>; | 
|  | static_assert(_CopyConstructible::value, | 
|  | "throw_with_nested argument must be CopyConstructible"); | 
|  | using __nest = __and_<is_class<_Up>, __bool_constant<!__is_final(_Up)>, | 
|  | __not_<is_base_of<nested_exception, _Up>>>; | 
|  | std::__throw_with_nested_impl(std::forward<_Tp>(__t), __nest{}); | 
|  | } | 
|  |  | 
|  | /// @cond undocumented | 
|  |  | 
|  | // Determine if dynamic_cast<const nested_exception&> would be well-formed. | 
|  | template<typename _Tp> | 
|  | using __rethrow_if_nested_cond = typename enable_if< | 
|  | __and_<is_polymorphic<_Tp>, | 
|  | __or_<__not_<is_base_of<nested_exception, _Tp>>, | 
|  | is_convertible<_Tp*, nested_exception*>>>::value | 
|  | >::type; | 
|  |  | 
|  | // Attempt dynamic_cast to nested_exception and call rethrow_nested(). | 
|  | template<typename _Ex> | 
|  | inline __rethrow_if_nested_cond<_Ex> | 
|  | __rethrow_if_nested_impl(const _Ex* __ptr) | 
|  | { | 
|  | if (auto __ne_ptr = dynamic_cast<const nested_exception*>(__ptr)) | 
|  | __ne_ptr->rethrow_nested(); | 
|  | } | 
|  |  | 
|  | // Otherwise, no effects. | 
|  | inline void | 
|  | __rethrow_if_nested_impl(const void*) | 
|  | { } | 
|  |  | 
|  | /// @endcond | 
|  |  | 
|  | /// If @p __ex is derived from nested_exception, @p __ex.rethrow_nested(). | 
|  | template<typename _Ex> | 
|  | inline void | 
|  | rethrow_if_nested(const _Ex& __ex) | 
|  | { std::__rethrow_if_nested_impl(std::__addressof(__ex)); } | 
|  |  | 
|  | /// @} group exceptions | 
|  | } // namespace std | 
|  |  | 
|  | } // extern "C++" | 
|  |  | 
|  | #endif // C++11 | 
|  |  | 
|  | #pragma GCC visibility pop | 
|  |  | 
|  | #endif // _GLIBCXX_NESTED_EXCEPTION_H |