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
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() 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