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