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 45extern "C++" { 46 47namespace 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* = 0) 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