xref: /netbsd-src/external/gpl3/gcc/dist/libstdc++-v3/libsupc++/nested_exception.h (revision e9e6e0f6fbc36b8de7586170291cf5fc97cab8b6)
14fee23f9Smrg // Nested Exception support header (nested_exception class) for -*- C++ -*-
24fee23f9Smrg 
3*e9e6e0f6Smrg // Copyright (C) 2009-2022 Free Software Foundation, Inc.
44fee23f9Smrg //
54fee23f9Smrg // This file is part of the GNU ISO C++ Library.  This library is free
64fee23f9Smrg // software; you can redistribute it and/or modify it under the
74fee23f9Smrg // terms of the GNU General Public License as published by the
84fee23f9Smrg // Free Software Foundation; either version 3, or (at your option)
94fee23f9Smrg // any later version.
104fee23f9Smrg 
114fee23f9Smrg // This library is distributed in the hope that it will be useful,
124fee23f9Smrg // but WITHOUT ANY WARRANTY; without even the implied warranty of
134fee23f9Smrg // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
144fee23f9Smrg // GNU General Public License for more details.
154fee23f9Smrg 
164fee23f9Smrg // Under Section 7 of GPL version 3, you are granted additional
174fee23f9Smrg // permissions described in the GCC Runtime Library Exception, version
184fee23f9Smrg // 3.1, as published by the Free Software Foundation.
194fee23f9Smrg 
204fee23f9Smrg // You should have received a copy of the GNU General Public License and
214fee23f9Smrg // a copy of the GCC Runtime Library Exception along with this program;
224fee23f9Smrg // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
234fee23f9Smrg // <http://www.gnu.org/licenses/>.
244fee23f9Smrg 
2523da6d05Smrg /** @file bits/nested_exception.h
2623da6d05Smrg  *  This is an internal header file, included by other library headers.
2723da6d05Smrg  *  Do not attempt to use it directly. @headername{exception}
284fee23f9Smrg  */
294fee23f9Smrg 
304fee23f9Smrg #ifndef _GLIBCXX_NESTED_EXCEPTION_H
314fee23f9Smrg #define _GLIBCXX_NESTED_EXCEPTION_H 1
324fee23f9Smrg 
334fee23f9Smrg #pragma GCC visibility push(default)
344fee23f9Smrg 
3523da6d05Smrg #if __cplusplus < 201103L
364fee23f9Smrg # include <bits/c++0x_warning.h>
374fee23f9Smrg #else
384fee23f9Smrg 
394fee23f9Smrg #include <bits/c++config.h>
40cdbfa754Smrg #include <bits/move.h>
414fee23f9Smrg 
424fee23f9Smrg extern "C++" {
434fee23f9Smrg 
444fee23f9Smrg namespace std
454fee23f9Smrg {
464fee23f9Smrg   /**
474fee23f9Smrg    * @addtogroup exceptions
484fee23f9Smrg    * @{
494fee23f9Smrg    */
504fee23f9Smrg 
514fee23f9Smrg   /// Exception class with exception_ptr data member.
524fee23f9Smrg   class nested_exception
534fee23f9Smrg   {
544fee23f9Smrg     exception_ptr _M_ptr;
554fee23f9Smrg 
564fee23f9Smrg   public:
nested_exception()5723da6d05Smrg     nested_exception() noexcept : _M_ptr(current_exception()) { }
584fee23f9Smrg 
59d35849d0Smrg     nested_exception(const nested_exception&) noexcept = default;
604fee23f9Smrg 
61d35849d0Smrg     nested_exception& operator=(const nested_exception&) noexcept = default;
624fee23f9Smrg 
6323da6d05Smrg     virtual ~nested_exception() noexcept;
644fee23f9Smrg 
65d35849d0Smrg     [[noreturn]]
664fee23f9Smrg     void
rethrow_nested()67d35849d0Smrg     rethrow_nested() const
68d35849d0Smrg     {
69d35849d0Smrg       if (_M_ptr)
70d35849d0Smrg 	rethrow_exception(_M_ptr);
71d35849d0Smrg       std::terminate();
72d35849d0Smrg     }
734fee23f9Smrg 
744fee23f9Smrg     exception_ptr
nested_ptr()75d35849d0Smrg     nested_ptr() const noexcept
764fee23f9Smrg     { return _M_ptr; }
774fee23f9Smrg   };
784fee23f9Smrg 
7943265c03Smrg   /// @cond undocumented
8043265c03Smrg 
814fee23f9Smrg   template<typename _Except>
824fee23f9Smrg     struct _Nested_exception : public _Except, public nested_exception
834fee23f9Smrg     {
_Nested_exception_Nested_exception84d35849d0Smrg       explicit _Nested_exception(const _Except& __ex)
85d35849d0Smrg       : _Except(__ex)
86d35849d0Smrg       { }
87d35849d0Smrg 
_Nested_exception_Nested_exception884fee23f9Smrg       explicit _Nested_exception(_Except&& __ex)
894fee23f9Smrg       : _Except(static_cast<_Except&&>(__ex))
904fee23f9Smrg       { }
914fee23f9Smrg     };
924fee23f9Smrg 
93cdbfa754Smrg   // [except.nested]/8
94cdbfa754Smrg   // Throw an exception of unspecified type that is publicly derived from
95cdbfa754Smrg   // both remove_reference_t<_Tp> and nested_exception.
96cdbfa754Smrg   template<typename _Tp>
973f8cba22Smrg     [[noreturn]]
98cdbfa754Smrg     inline void
__throw_with_nested_impl(_Tp && __t,true_type)99cdbfa754Smrg     __throw_with_nested_impl(_Tp&& __t, true_type)
1004fee23f9Smrg     {
101cdbfa754Smrg       using _Up = typename remove_reference<_Tp>::type;
102cdbfa754Smrg       throw _Nested_exception<_Up>{std::forward<_Tp>(__t)};
103cdbfa754Smrg     }
1044fee23f9Smrg 
105d35849d0Smrg   template<typename _Tp>
1063f8cba22Smrg     [[noreturn]]
107cdbfa754Smrg     inline void
__throw_with_nested_impl(_Tp && __t,false_type)108cdbfa754Smrg     __throw_with_nested_impl(_Tp&& __t, false_type)
109cdbfa754Smrg     { throw std::forward<_Tp>(__t); }
110d35849d0Smrg 
11143265c03Smrg   /// @endcond
11243265c03Smrg 
113d35849d0Smrg   /// If @p __t is derived from nested_exception, throws @p __t.
114d35849d0Smrg   /// Else, throws an implementation-defined object derived from both.
115d35849d0Smrg   template<typename _Tp>
116d35849d0Smrg     [[noreturn]]
1174fee23f9Smrg     inline void
throw_with_nested(_Tp && __t)118d35849d0Smrg     throw_with_nested(_Tp&& __t)
1194fee23f9Smrg     {
120cdbfa754Smrg       using _Up = typename decay<_Tp>::type;
121cdbfa754Smrg       using _CopyConstructible
122cdbfa754Smrg 	= __and_<is_copy_constructible<_Up>, is_move_constructible<_Up>>;
123cdbfa754Smrg       static_assert(_CopyConstructible::value,
124cdbfa754Smrg 	  "throw_with_nested argument must be CopyConstructible");
125cdbfa754Smrg       using __nest = __and_<is_class<_Up>, __bool_constant<!__is_final(_Up)>,
126cdbfa754Smrg 			    __not_<is_base_of<nested_exception, _Up>>>;
127cdbfa754Smrg       std::__throw_with_nested_impl(std::forward<_Tp>(__t), __nest{});
1284fee23f9Smrg     }
1294fee23f9Smrg 
13043265c03Smrg   /// @cond undocumented
13143265c03Smrg 
132cdbfa754Smrg   // Determine if dynamic_cast<const nested_exception&> would be well-formed.
133d35849d0Smrg   template<typename _Tp>
134cdbfa754Smrg     using __rethrow_if_nested_cond = typename enable_if<
135cdbfa754Smrg       __and_<is_polymorphic<_Tp>,
136cdbfa754Smrg 	     __or_<__not_<is_base_of<nested_exception, _Tp>>,
137cdbfa754Smrg 		   is_convertible<_Tp*, nested_exception*>>>::value
138cdbfa754Smrg     >::type;
139cdbfa754Smrg 
140cdbfa754Smrg   // Attempt dynamic_cast to nested_exception and call rethrow_nested().
141cdbfa754Smrg   template<typename _Ex>
142cdbfa754Smrg     inline __rethrow_if_nested_cond<_Ex>
__rethrow_if_nested_impl(const _Ex * __ptr)143cdbfa754Smrg     __rethrow_if_nested_impl(const _Ex* __ptr)
144d35849d0Smrg     {
145cdbfa754Smrg       if (auto __ne_ptr = dynamic_cast<const nested_exception*>(__ptr))
146cdbfa754Smrg 	__ne_ptr->rethrow_nested();
147cdbfa754Smrg     }
148cdbfa754Smrg 
149cdbfa754Smrg   // Otherwise, no effects.
150cdbfa754Smrg   inline void
__rethrow_if_nested_impl(const void *)151cdbfa754Smrg   __rethrow_if_nested_impl(const void*)
152cdbfa754Smrg   { }
153d35849d0Smrg 
15443265c03Smrg   /// @endcond
15543265c03Smrg 
1564fee23f9Smrg   /// If @p __ex is derived from nested_exception, @p __ex.rethrow_nested().
1574fee23f9Smrg   template<typename _Ex>
1584fee23f9Smrg     inline void
rethrow_if_nested(const _Ex & __ex)1594fee23f9Smrg     rethrow_if_nested(const _Ex& __ex)
160cdbfa754Smrg     { std::__rethrow_if_nested_impl(std::__addressof(__ex)); }
1614fee23f9Smrg 
1629f30ce74Smrg   /// @} group exceptions
1634fee23f9Smrg } // namespace std
1644fee23f9Smrg 
1654fee23f9Smrg } // extern "C++"
1664fee23f9Smrg 
16723da6d05Smrg #endif // C++11
1684fee23f9Smrg 
1694fee23f9Smrg #pragma GCC visibility pop
1704fee23f9Smrg 
1714fee23f9Smrg #endif // _GLIBCXX_NESTED_EXCEPTION_H
172