1    	// Nested Exception support header (nested_exception class) for -*- C++ -*-
2    	
3    	// Copyright (C) 2009-2013 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 bits/nested_exception.h
26   	 *  This is an internal header file, included by other library headers.
27   	 *  Do not attempt to use it directly. @headername{exception}
28   	 */
29   	
30   	#ifndef _GLIBCXX_NESTED_EXCEPTION_H
31   	#define _GLIBCXX_NESTED_EXCEPTION_H 1
32   	
33   	#pragma GCC visibility push(default)
34   	
35   	#if __cplusplus < 201103L
36   	# include <bits/c++0x_warning.h>
37   	#else
38   	
39   	#include <bits/c++config.h>
40   	
41   	#if ATOMIC_INT_LOCK_FREE < 2
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() noexcept : _M_ptr(current_exception()) { }
61   	
62   	    nested_exception(const nested_exception&) = default;
63   	
64   	    nested_exception& operator=(const nested_exception&) = default;
65   	
66   	    virtual ~nested_exception() noexcept;
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   	  template<typename _Except>
78   	    struct _Nested_exception : public _Except, public nested_exception
79   	    {
80   	      explicit _Nested_exception(_Except&& __ex)
81   	      : _Except(static_cast<_Except&&>(__ex))
82   	      { }
83   	    };
84   	
85   	  template<typename _Ex>
86   	    struct __get_nested_helper
87   	    {
88   	      static const nested_exception*
89   	      _S_get(const _Ex& __ex)
90   	      { return dynamic_cast<const nested_exception*>(&__ex); }
91   	    };
92   	
93   	  template<typename _Ex>
94   	    struct __get_nested_helper<_Ex*>
95   	    {
96   	      static const nested_exception*
97   	      _S_get(const _Ex* __ex)
98   	      { return dynamic_cast<const nested_exception*>(__ex); }
99   	    };
100  	
101  	  template<typename _Ex>
102  	    inline const nested_exception*
103  	    __get_nested_exception(const _Ex& __ex)
104  	    { return __get_nested_helper<_Ex>::_S_get(__ex); }
105  	
106  	  template<typename _Ex>
107  	    void
108  	    __throw_with_nested(_Ex&&, const nested_exception* = 0)
109  	    __attribute__ ((__noreturn__));
110  	
111  	  template<typename _Ex>
112  	    void
113  	    __throw_with_nested(_Ex&&, ...) __attribute__ ((__noreturn__));
114  	
115  	  // This function should never be called, but is needed to avoid a warning
116  	  // about ambiguous base classes when instantiating throw_with_nested<_Ex>()
117  	  // with a type that has an accessible nested_exception base.
118  	  template<typename _Ex>
119  	    inline void
120  	    __throw_with_nested(_Ex&& __ex, const nested_exception*)
121  	    { throw __ex; }
122  	
123  	  template<typename _Ex>
124  	    inline void
125  	    __throw_with_nested(_Ex&& __ex, ...)
126  	    { throw _Nested_exception<_Ex>(static_cast<_Ex&&>(__ex)); }
127  	  
128  	  template<typename _Ex>
129  	    void
130  	    throw_with_nested(_Ex __ex) __attribute__ ((__noreturn__));
131  	
132  	  /// If @p __ex is derived from nested_exception, @p __ex. 
133  	  /// Else, an implementation-defined object derived from both.
134  	  template<typename _Ex>
135  	    inline void
136  	    throw_with_nested(_Ex __ex)
137  	    {
138  	      if (__get_nested_exception(__ex))
139  	        throw __ex;
140  	      __throw_with_nested(static_cast<_Ex&&>(__ex), &__ex);
141  	    }
142  	
143  	  /// If @p __ex is derived from nested_exception, @p __ex.rethrow_nested().
144  	  template<typename _Ex>
145  	    inline void
146  	    rethrow_if_nested(const _Ex& __ex)
147  	    {
148  	      if (const nested_exception* __nested = __get_nested_exception(__ex))
149  	        __nested->rethrow_nested();
150  	    }
151  	
152  	  /// Overload, See N2619
153  	  inline void
154  	  rethrow_if_nested(const nested_exception& __ex)
155  	  { __ex.rethrow_nested(); }
156  	
157  	  // @} group exceptions
158  	} // namespace std
159  	
160  	} // extern "C++"
161  	
162  	#endif // C++11
163  	
164  	#pragma GCC visibility pop
165  	
166  	#endif // _GLIBCXX_NESTED_EXCEPTION_H
167