OSDN Git Service

PR c++/38796, Core issue 906
[pf3gnuchains/gcc-fork.git] / libstdc++-v3 / libsupc++ / nested_exception.h
1 // Nested Exception support header (nested_exception class) for -*- C++ -*-
2
3 // Copyright (C) 2009 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 <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   /// nested_exception
55   class nested_exception
56   {
57   public:
58     nested_exception() throw() : _M_ptr(current_exception()) { }
59
60     nested_exception(const nested_exception&) = default;
61
62     nested_exception& operator=(const nested_exception&) = default;
63
64     virtual ~nested_exception() = default;
65
66     void
67     rethrow_nested() const __attribute__ ((__noreturn__))
68     { rethrow_exception(_M_ptr); }
69
70     exception_ptr
71     nested_ptr() const
72     { return _M_ptr; }
73
74   private:
75     exception_ptr _M_ptr;
76   };
77
78   template<typename _Except>
79     struct _Nested_exception : public _Except, public nested_exception
80     {
81       explicit
82       _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       {
93         return dynamic_cast<const nested_exception*>(&__ex);
94       }
95     };
96
97   template<typename _Ex>
98     struct __get_nested_helper<_Ex*>
99     {
100       static const nested_exception*
101       _S_get(const _Ex* __ex)
102       {
103         return dynamic_cast<const nested_exception*>(__ex);
104       }
105     };
106
107   template<typename _Ex>
108     inline const nested_exception*
109     __get_nested_exception(const _Ex& __ex)
110     {
111       return __get_nested_helper<_Ex>::_S_get(__ex);
112     }
113
114   template<typename _Ex>
115     void
116     __throw_with_nested(_Ex&&, const nested_exception* = 0)
117     __attribute__ ((__noreturn__));
118
119   template<typename _Ex>
120     void
121     __throw_with_nested(_Ex&&, ...) __attribute__ ((__noreturn__));
122
123   // This function should never be called, but is needed to avoid a warning
124   // about ambiguous base classes when instantiating throw_with_nested<_Ex>()
125   // with a type that has an accessible nested_exception base.
126   template<typename _Ex>
127     inline void
128     __throw_with_nested(_Ex&& __ex, const nested_exception* = 0)
129     {
130       throw __ex;
131     }
132
133   template<typename _Ex>
134     inline void
135     __throw_with_nested(_Ex&& __ex, ...)
136     {
137       throw _Nested_exception<_Ex>(static_cast<_Ex&&>(__ex));
138     }
139   
140   template<typename _Ex>
141     void
142     throw_with_nested(_Ex __ex) __attribute__ ((__noreturn__));
143
144   template<typename _Ex>
145     inline void
146     throw_with_nested(_Ex __ex)
147     {
148       if (__get_nested_exception(__ex))
149         throw __ex;
150       __throw_with_nested(static_cast<_Ex&&>(__ex), &__ex);
151     }
152
153   template<typename _Ex>
154     inline void
155     rethrow_if_nested(const _Ex& __ex)
156     {
157       if (const nested_exception* __nested = __get_nested_exception(__ex))
158         __nested->rethrow_nested();
159     }
160
161   // see n2619
162   inline void
163   rethrow_if_nested(const nested_exception& __ex)
164   {
165     __ex.rethrow_nested();
166   }
167
168   // @} group exceptions
169 } // namespace std
170
171 } // extern "C++"
172
173 #endif // __GXX_EXPERIMENTAL_CXX0X__
174
175 #pragma GCC visibility pop
176
177 #endif // _GLIBCXX_NESTED_EXCEPTION_H