xref: /netbsd-src/external/gpl3/gcc.old/dist/libstdc++-v3/libsupc++/nested_exception.h (revision 8feb0f0b7eaff0608f8350bbfa3098827b4bb91b)
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