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