Home | History | Annotate | Download | only in bits
      1 // Nested Exception support header (nested_exception class) for -*- C++ -*-
      2 
      3 // Copyright (C) 2009-2014 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