11debfc3dSmrg // Nested Exception support header (nested_exception class) for -*- C++ -*- 21debfc3dSmrg 3*8feb0f0bSmrg // Copyright (C) 2009-2020 Free Software Foundation, Inc. 41debfc3dSmrg // 51debfc3dSmrg // This file is part of the GNU ISO C++ Library. This library is free 61debfc3dSmrg // software; you can redistribute it and/or modify it under the 71debfc3dSmrg // terms of the GNU General Public License as published by the 81debfc3dSmrg // Free Software Foundation; either version 3, or (at your option) 91debfc3dSmrg // any later version. 101debfc3dSmrg 111debfc3dSmrg // This library is distributed in the hope that it will be useful, 121debfc3dSmrg // but WITHOUT ANY WARRANTY; without even the implied warranty of 131debfc3dSmrg // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 141debfc3dSmrg // GNU General Public License for more details. 151debfc3dSmrg 161debfc3dSmrg // Under Section 7 of GPL version 3, you are granted additional 171debfc3dSmrg // permissions described in the GCC Runtime Library Exception, version 181debfc3dSmrg // 3.1, as published by the Free Software Foundation. 191debfc3dSmrg 201debfc3dSmrg // You should have received a copy of the GNU General Public License and 211debfc3dSmrg // a copy of the GCC Runtime Library Exception along with this program; 221debfc3dSmrg // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 231debfc3dSmrg // <http://www.gnu.org/licenses/>. 241debfc3dSmrg 251debfc3dSmrg /** @file bits/nested_exception.h 261debfc3dSmrg * This is an internal header file, included by other library headers. 271debfc3dSmrg * Do not attempt to use it directly. @headername{exception} 281debfc3dSmrg */ 291debfc3dSmrg 301debfc3dSmrg #ifndef _GLIBCXX_NESTED_EXCEPTION_H 311debfc3dSmrg #define _GLIBCXX_NESTED_EXCEPTION_H 1 321debfc3dSmrg 331debfc3dSmrg #pragma GCC visibility push(default) 341debfc3dSmrg 351debfc3dSmrg #if __cplusplus < 201103L 361debfc3dSmrg # include <bits/c++0x_warning.h> 371debfc3dSmrg #else 381debfc3dSmrg 391debfc3dSmrg #include <bits/c++config.h> 401debfc3dSmrg #include <bits/move.h> 411debfc3dSmrg 421debfc3dSmrg extern "C++" { 431debfc3dSmrg 441debfc3dSmrg namespace std 451debfc3dSmrg { 461debfc3dSmrg /** 471debfc3dSmrg * @addtogroup exceptions 481debfc3dSmrg * @{ 491debfc3dSmrg */ 501debfc3dSmrg 511debfc3dSmrg /// Exception class with exception_ptr data member. 521debfc3dSmrg class nested_exception 531debfc3dSmrg { 541debfc3dSmrg exception_ptr _M_ptr; 551debfc3dSmrg 561debfc3dSmrg public: nested_exception()571debfc3dSmrg nested_exception() noexcept : _M_ptr(current_exception()) { } 581debfc3dSmrg 591debfc3dSmrg nested_exception(const nested_exception&) noexcept = default; 601debfc3dSmrg 611debfc3dSmrg nested_exception& operator=(const nested_exception&) noexcept = default; 621debfc3dSmrg 631debfc3dSmrg virtual ~nested_exception() noexcept; 641debfc3dSmrg 651debfc3dSmrg [[noreturn]] 661debfc3dSmrg void rethrow_nested()671debfc3dSmrg rethrow_nested() const 681debfc3dSmrg { 691debfc3dSmrg if (_M_ptr) 701debfc3dSmrg rethrow_exception(_M_ptr); 711debfc3dSmrg std::terminate(); 721debfc3dSmrg } 731debfc3dSmrg 741debfc3dSmrg exception_ptr nested_ptr()751debfc3dSmrg nested_ptr() const noexcept 761debfc3dSmrg { return _M_ptr; } 771debfc3dSmrg }; 781debfc3dSmrg 79*8feb0f0bSmrg /// @cond undocumented 80*8feb0f0bSmrg 811debfc3dSmrg template<typename _Except> 821debfc3dSmrg struct _Nested_exception : public _Except, public nested_exception 831debfc3dSmrg { _Nested_exception_Nested_exception841debfc3dSmrg explicit _Nested_exception(const _Except& __ex) 851debfc3dSmrg : _Except(__ex) 861debfc3dSmrg { } 871debfc3dSmrg _Nested_exception_Nested_exception881debfc3dSmrg explicit _Nested_exception(_Except&& __ex) 891debfc3dSmrg : _Except(static_cast<_Except&&>(__ex)) 901debfc3dSmrg { } 911debfc3dSmrg }; 921debfc3dSmrg 931debfc3dSmrg // [except.nested]/8 941debfc3dSmrg // Throw an exception of unspecified type that is publicly derived from 951debfc3dSmrg // both remove_reference_t<_Tp> and nested_exception. 961debfc3dSmrg template<typename _Tp> 97a2dc1f3fSmrg [[noreturn]] 981debfc3dSmrg inline void __throw_with_nested_impl(_Tp && __t,true_type)991debfc3dSmrg __throw_with_nested_impl(_Tp&& __t, true_type) 1001debfc3dSmrg { 1011debfc3dSmrg using _Up = typename remove_reference<_Tp>::type; 1021debfc3dSmrg throw _Nested_exception<_Up>{std::forward<_Tp>(__t)}; 1031debfc3dSmrg } 1041debfc3dSmrg 1051debfc3dSmrg template<typename _Tp> 106a2dc1f3fSmrg [[noreturn]] 1071debfc3dSmrg inline void __throw_with_nested_impl(_Tp && __t,false_type)1081debfc3dSmrg __throw_with_nested_impl(_Tp&& __t, false_type) 1091debfc3dSmrg { throw std::forward<_Tp>(__t); } 1101debfc3dSmrg 111*8feb0f0bSmrg /// @endcond 112*8feb0f0bSmrg 1131debfc3dSmrg /// If @p __t is derived from nested_exception, throws @p __t. 1141debfc3dSmrg /// Else, throws an implementation-defined object derived from both. 1151debfc3dSmrg template<typename _Tp> 1161debfc3dSmrg [[noreturn]] 1171debfc3dSmrg inline void throw_with_nested(_Tp && __t)1181debfc3dSmrg throw_with_nested(_Tp&& __t) 1191debfc3dSmrg { 1201debfc3dSmrg using _Up = typename decay<_Tp>::type; 1211debfc3dSmrg using _CopyConstructible 1221debfc3dSmrg = __and_<is_copy_constructible<_Up>, is_move_constructible<_Up>>; 1231debfc3dSmrg static_assert(_CopyConstructible::value, 1241debfc3dSmrg "throw_with_nested argument must be CopyConstructible"); 1251debfc3dSmrg using __nest = __and_<is_class<_Up>, __bool_constant<!__is_final(_Up)>, 1261debfc3dSmrg __not_<is_base_of<nested_exception, _Up>>>; 1271debfc3dSmrg std::__throw_with_nested_impl(std::forward<_Tp>(__t), __nest{}); 1281debfc3dSmrg } 1291debfc3dSmrg 130*8feb0f0bSmrg /// @cond undocumented 131*8feb0f0bSmrg 1321debfc3dSmrg // Determine if dynamic_cast<const nested_exception&> would be well-formed. 1331debfc3dSmrg template<typename _Tp> 1341debfc3dSmrg using __rethrow_if_nested_cond = typename enable_if< 1351debfc3dSmrg __and_<is_polymorphic<_Tp>, 1361debfc3dSmrg __or_<__not_<is_base_of<nested_exception, _Tp>>, 1371debfc3dSmrg is_convertible<_Tp*, nested_exception*>>>::value 1381debfc3dSmrg >::type; 1391debfc3dSmrg 1401debfc3dSmrg // Attempt dynamic_cast to nested_exception and call rethrow_nested(). 1411debfc3dSmrg template<typename _Ex> 1421debfc3dSmrg inline __rethrow_if_nested_cond<_Ex> __rethrow_if_nested_impl(const _Ex * __ptr)1431debfc3dSmrg __rethrow_if_nested_impl(const _Ex* __ptr) 1441debfc3dSmrg { 1451debfc3dSmrg if (auto __ne_ptr = dynamic_cast<const nested_exception*>(__ptr)) 1461debfc3dSmrg __ne_ptr->rethrow_nested(); 1471debfc3dSmrg } 1481debfc3dSmrg 1491debfc3dSmrg // Otherwise, no effects. 1501debfc3dSmrg inline void __rethrow_if_nested_impl(const void *)1511debfc3dSmrg __rethrow_if_nested_impl(const void*) 1521debfc3dSmrg { } 1531debfc3dSmrg 154*8feb0f0bSmrg /// @endcond 155*8feb0f0bSmrg 1561debfc3dSmrg /// If @p __ex is derived from nested_exception, @p __ex.rethrow_nested(). 1571debfc3dSmrg template<typename _Ex> 1581debfc3dSmrg inline void rethrow_if_nested(const _Ex & __ex)1591debfc3dSmrg rethrow_if_nested(const _Ex& __ex) 1601debfc3dSmrg { std::__rethrow_if_nested_impl(std::__addressof(__ex)); } 1611debfc3dSmrg 162*8feb0f0bSmrg /// @} group exceptions 1631debfc3dSmrg } // namespace std 1641debfc3dSmrg 1651debfc3dSmrg } // extern "C++" 1661debfc3dSmrg 1671debfc3dSmrg #endif // C++11 1681debfc3dSmrg 1691debfc3dSmrg #pragma GCC visibility pop 1701debfc3dSmrg 1711debfc3dSmrg #endif // _GLIBCXX_NESTED_EXCEPTION_H 172