1*e4b17023SJohn Marino // Nested Exception support header (nested_exception class) for -*- C++ -*- 2*e4b17023SJohn Marino 3*e4b17023SJohn Marino // Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc. 4*e4b17023SJohn Marino // 5*e4b17023SJohn Marino // This file is part of the GNU ISO C++ Library. This library is free 6*e4b17023SJohn Marino // software; you can redistribute it and/or modify it under the 7*e4b17023SJohn Marino // terms of the GNU General Public License as published by the 8*e4b17023SJohn Marino // Free Software Foundation; either version 3, or (at your option) 9*e4b17023SJohn Marino // any later version. 10*e4b17023SJohn Marino 11*e4b17023SJohn Marino // This library is distributed in the hope that it will be useful, 12*e4b17023SJohn Marino // but WITHOUT ANY WARRANTY; without even the implied warranty of 13*e4b17023SJohn Marino // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14*e4b17023SJohn Marino // GNU General Public License for more details. 15*e4b17023SJohn Marino 16*e4b17023SJohn Marino // Under Section 7 of GPL version 3, you are granted additional 17*e4b17023SJohn Marino // permissions described in the GCC Runtime Library Exception, version 18*e4b17023SJohn Marino // 3.1, as published by the Free Software Foundation. 19*e4b17023SJohn Marino 20*e4b17023SJohn Marino // You should have received a copy of the GNU General Public License and 21*e4b17023SJohn Marino // a copy of the GCC Runtime Library Exception along with this program; 22*e4b17023SJohn Marino // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 23*e4b17023SJohn Marino // <http://www.gnu.org/licenses/>. 24*e4b17023SJohn Marino 25*e4b17023SJohn Marino /** @file bits/nested_exception.h 26*e4b17023SJohn Marino * This is an internal header file, included by other library headers. 27*e4b17023SJohn Marino * Do not attempt to use it directly. @headername{exception} 28*e4b17023SJohn Marino */ 29*e4b17023SJohn Marino 30*e4b17023SJohn Marino #ifndef _GLIBCXX_NESTED_EXCEPTION_H 31*e4b17023SJohn Marino #define _GLIBCXX_NESTED_EXCEPTION_H 1 32*e4b17023SJohn Marino 33*e4b17023SJohn Marino #pragma GCC visibility push(default) 34*e4b17023SJohn Marino 35*e4b17023SJohn Marino #ifndef __GXX_EXPERIMENTAL_CXX0X__ 36*e4b17023SJohn Marino # include <bits/c++0x_warning.h> 37*e4b17023SJohn Marino #else 38*e4b17023SJohn Marino 39*e4b17023SJohn Marino #include <bits/c++config.h> 40*e4b17023SJohn Marino 41*e4b17023SJohn Marino #if ATOMIC_INT_LOCK_FREE < 2 42*e4b17023SJohn Marino # error This platform does not support exception propagation. 43*e4b17023SJohn Marino #endif 44*e4b17023SJohn Marino 45*e4b17023SJohn Marino extern "C++" { 46*e4b17023SJohn Marino 47*e4b17023SJohn Marino namespace std 48*e4b17023SJohn Marino { 49*e4b17023SJohn Marino /** 50*e4b17023SJohn Marino * @addtogroup exceptions 51*e4b17023SJohn Marino * @{ 52*e4b17023SJohn Marino */ 53*e4b17023SJohn Marino 54*e4b17023SJohn Marino /// Exception class with exception_ptr data member. 55*e4b17023SJohn Marino class nested_exception 56*e4b17023SJohn Marino { 57*e4b17023SJohn Marino exception_ptr _M_ptr; 58*e4b17023SJohn Marino 59*e4b17023SJohn Marino public: nested_exception()60*e4b17023SJohn Marino nested_exception() noexcept : _M_ptr(current_exception()) { } 61*e4b17023SJohn Marino 62*e4b17023SJohn Marino nested_exception(const nested_exception&) = default; 63*e4b17023SJohn Marino 64*e4b17023SJohn Marino nested_exception& operator=(const nested_exception&) = default; 65*e4b17023SJohn Marino 66*e4b17023SJohn Marino virtual ~nested_exception() noexcept; 67*e4b17023SJohn Marino 68*e4b17023SJohn Marino void rethrow_nested()69*e4b17023SJohn Marino rethrow_nested() const __attribute__ ((__noreturn__)) 70*e4b17023SJohn Marino { rethrow_exception(_M_ptr); } 71*e4b17023SJohn Marino 72*e4b17023SJohn Marino exception_ptr nested_ptr()73*e4b17023SJohn Marino nested_ptr() const 74*e4b17023SJohn Marino { return _M_ptr; } 75*e4b17023SJohn Marino }; 76*e4b17023SJohn Marino 77*e4b17023SJohn Marino template<typename _Except> 78*e4b17023SJohn Marino struct _Nested_exception : public _Except, public nested_exception 79*e4b17023SJohn Marino { _Nested_exception_Nested_exception80*e4b17023SJohn Marino explicit _Nested_exception(_Except&& __ex) 81*e4b17023SJohn Marino : _Except(static_cast<_Except&&>(__ex)) 82*e4b17023SJohn Marino { } 83*e4b17023SJohn Marino }; 84*e4b17023SJohn Marino 85*e4b17023SJohn Marino template<typename _Ex> 86*e4b17023SJohn Marino struct __get_nested_helper 87*e4b17023SJohn Marino { 88*e4b17023SJohn Marino static const nested_exception* _S_get__get_nested_helper89*e4b17023SJohn Marino _S_get(const _Ex& __ex) 90*e4b17023SJohn Marino { return dynamic_cast<const nested_exception*>(&__ex); } 91*e4b17023SJohn Marino }; 92*e4b17023SJohn Marino 93*e4b17023SJohn Marino template<typename _Ex> 94*e4b17023SJohn Marino struct __get_nested_helper<_Ex*> 95*e4b17023SJohn Marino { 96*e4b17023SJohn Marino static const nested_exception* 97*e4b17023SJohn Marino _S_get(const _Ex* __ex) 98*e4b17023SJohn Marino { return dynamic_cast<const nested_exception*>(__ex); } 99*e4b17023SJohn Marino }; 100*e4b17023SJohn Marino 101*e4b17023SJohn Marino template<typename _Ex> 102*e4b17023SJohn Marino inline const nested_exception* 103*e4b17023SJohn Marino __get_nested_exception(const _Ex& __ex) 104*e4b17023SJohn Marino { return __get_nested_helper<_Ex>::_S_get(__ex); } 105*e4b17023SJohn Marino 106*e4b17023SJohn Marino template<typename _Ex> 107*e4b17023SJohn Marino void 108*e4b17023SJohn Marino __throw_with_nested(_Ex&&, const nested_exception* = 0) 109*e4b17023SJohn Marino __attribute__ ((__noreturn__)); 110*e4b17023SJohn Marino 111*e4b17023SJohn Marino template<typename _Ex> 112*e4b17023SJohn Marino void 113*e4b17023SJohn Marino __throw_with_nested(_Ex&&, ...) __attribute__ ((__noreturn__)); 114*e4b17023SJohn Marino 115*e4b17023SJohn Marino // This function should never be called, but is needed to avoid a warning 116*e4b17023SJohn Marino // about ambiguous base classes when instantiating throw_with_nested<_Ex>() 117*e4b17023SJohn Marino // with a type that has an accessible nested_exception base. 118*e4b17023SJohn Marino template<typename _Ex> 119*e4b17023SJohn Marino inline void 120*e4b17023SJohn Marino __throw_with_nested(_Ex&& __ex, const nested_exception*) 121*e4b17023SJohn Marino { throw __ex; } 122*e4b17023SJohn Marino 123*e4b17023SJohn Marino template<typename _Ex> 124*e4b17023SJohn Marino inline void 125*e4b17023SJohn Marino __throw_with_nested(_Ex&& __ex, ...) 126*e4b17023SJohn Marino { throw _Nested_exception<_Ex>(static_cast<_Ex&&>(__ex)); } 127*e4b17023SJohn Marino 128*e4b17023SJohn Marino template<typename _Ex> 129*e4b17023SJohn Marino void 130*e4b17023SJohn Marino throw_with_nested(_Ex __ex) __attribute__ ((__noreturn__)); 131*e4b17023SJohn Marino 132*e4b17023SJohn Marino /// If @p __ex is derived from nested_exception, @p __ex. 133*e4b17023SJohn Marino /// Else, an implementation-defined object derived from both. 134*e4b17023SJohn Marino template<typename _Ex> 135*e4b17023SJohn Marino inline void 136*e4b17023SJohn Marino throw_with_nested(_Ex __ex) 137*e4b17023SJohn Marino { 138*e4b17023SJohn Marino if (__get_nested_exception(__ex)) 139*e4b17023SJohn Marino throw __ex; 140*e4b17023SJohn Marino __throw_with_nested(static_cast<_Ex&&>(__ex), &__ex); 141*e4b17023SJohn Marino } 142*e4b17023SJohn Marino 143*e4b17023SJohn Marino /// If @p __ex is derived from nested_exception, @p __ex.rethrow_nested(). 144*e4b17023SJohn Marino template<typename _Ex> 145*e4b17023SJohn Marino inline void 146*e4b17023SJohn Marino rethrow_if_nested(const _Ex& __ex) 147*e4b17023SJohn Marino { 148*e4b17023SJohn Marino if (const nested_exception* __nested = __get_nested_exception(__ex)) 149*e4b17023SJohn Marino __nested->rethrow_nested(); 150*e4b17023SJohn Marino } 151*e4b17023SJohn Marino 152*e4b17023SJohn Marino /// Overload, See N2619 153*e4b17023SJohn Marino inline void 154*e4b17023SJohn Marino rethrow_if_nested(const nested_exception& __ex) 155*e4b17023SJohn Marino { __ex.rethrow_nested(); } 156*e4b17023SJohn Marino 157*e4b17023SJohn Marino // @} group exceptions 158*e4b17023SJohn Marino } // namespace std 159*e4b17023SJohn Marino 160*e4b17023SJohn Marino } // extern "C++" 161*e4b17023SJohn Marino 162*e4b17023SJohn Marino #endif // __GXX_EXPERIMENTAL_CXX0X__ 163*e4b17023SJohn Marino 164*e4b17023SJohn Marino #pragma GCC visibility pop 165*e4b17023SJohn Marino 166*e4b17023SJohn Marino #endif // _GLIBCXX_NESTED_EXCEPTION_H 167