Home | History | Annotate | Download | only in v1
      1 // -*- C++ -*-
      2 //===-------------------------- exception ---------------------------------===//
      3 //
      4 //                     The LLVM Compiler Infrastructure
      5 //
      6 // This file is dual licensed under the MIT and the University of Illinois Open
      7 // Source Licenses. See LICENSE.TXT for details.
      8 //
      9 //===----------------------------------------------------------------------===//
     10 
     11 #ifndef _LIBCPP_EXCEPTION
     12 #define _LIBCPP_EXCEPTION
     13 
     14 /*
     15     exception synopsis
     16 
     17 namespace std
     18 {
     19 
     20 class exception
     21 {
     22 public:
     23     exception() noexcept;
     24     exception(const exception&) noexcept;
     25     exception& operator=(const exception&) noexcept;
     26     virtual ~exception() noexcept;
     27     virtual const char* what() const noexcept;
     28 };
     29 
     30 class bad_exception
     31     : public exception
     32 {
     33 public:
     34     bad_exception() noexcept;
     35     bad_exception(const bad_exception&) noexcept;
     36     bad_exception& operator=(const bad_exception&) noexcept;
     37     virtual ~bad_exception() noexcept;
     38     virtual const char* what() const noexcept;
     39 };
     40 
     41 typedef void (*unexpected_handler)();
     42 unexpected_handler set_unexpected(unexpected_handler  f ) noexcept;
     43 unexpected_handler get_unexpected() noexcept;
     44 [[noreturn]] void unexpected();
     45 
     46 typedef void (*terminate_handler)();
     47 terminate_handler set_terminate(terminate_handler  f ) noexcept;
     48 terminate_handler get_terminate() noexcept;
     49 [[noreturn]] void terminate() noexcept;
     50 
     51 bool uncaught_exception()  noexcept;
     52 int  uncaught_exceptions() noexcept;  // C++17
     53 
     54 typedef unspecified exception_ptr;
     55 
     56 exception_ptr current_exception() noexcept;
     57 void rethrow_exception [[noreturn]] (exception_ptr p);
     58 template<class E> exception_ptr make_exception_ptr(E e) noexcept;
     59 
     60 class nested_exception
     61 {
     62 public:
     63     nested_exception() noexcept;
     64     nested_exception(const nested_exception&) noexcept = default;
     65     nested_exception& operator=(const nested_exception&) noexcept = default;
     66     virtual ~nested_exception() = default;
     67 
     68     // access functions
     69     [[noreturn]] void rethrow_nested() const;
     70     exception_ptr nested_ptr() const noexcept;
     71 };
     72 
     73 template <class T> [[noreturn]] void throw_with_nested(T&& t);
     74 template <class E> void rethrow_if_nested(const E& e);
     75 
     76 }  // std
     77 
     78 */
     79 
     80 #include <__config>
     81 #include <cstddef>
     82 #include <cstdlib>
     83 #include <type_traits>
     84 
     85 #if defined(_LIBCPP_ABI_MICROSOFT)
     86 #include <vcruntime_exception.h>
     87 #endif
     88 
     89 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
     90 #pragma GCC system_header
     91 #endif
     92 
     93 namespace std  // purposefully not using versioning namespace
     94 {
     95 
     96 #if !defined(_LIBCPP_ABI_MICROSOFT)
     97 class _LIBCPP_EXCEPTION_ABI exception
     98 {
     99 public:
    100     _LIBCPP_INLINE_VISIBILITY exception() _NOEXCEPT {}
    101     virtual ~exception() _NOEXCEPT;
    102     virtual const char* what() const _NOEXCEPT;
    103 };
    104 
    105 class _LIBCPP_EXCEPTION_ABI bad_exception
    106     : public exception
    107 {
    108 public:
    109     _LIBCPP_INLINE_VISIBILITY bad_exception() _NOEXCEPT {}
    110     virtual ~bad_exception() _NOEXCEPT;
    111     virtual const char* what() const _NOEXCEPT;
    112 };
    113 #endif // !_LIBCPP_ABI_MICROSOFT
    114 
    115 #if _LIBCPP_STD_VER <= 14 \
    116     || defined(_LIBCPP_ENABLE_CXX17_REMOVED_UNEXPECTED_FUNCTIONS) \
    117     || defined(_LIBCPP_BUILDING_LIBRARY)
    118 typedef void (*unexpected_handler)();
    119 _LIBCPP_FUNC_VIS unexpected_handler set_unexpected(unexpected_handler) _NOEXCEPT;
    120 _LIBCPP_FUNC_VIS unexpected_handler get_unexpected() _NOEXCEPT;
    121 _LIBCPP_NORETURN _LIBCPP_FUNC_VIS void unexpected();
    122 #endif
    123 
    124 typedef void (*terminate_handler)();
    125 _LIBCPP_FUNC_VIS terminate_handler set_terminate(terminate_handler) _NOEXCEPT;
    126 _LIBCPP_FUNC_VIS terminate_handler get_terminate() _NOEXCEPT;
    127 _LIBCPP_NORETURN _LIBCPP_FUNC_VIS void terminate() _NOEXCEPT;
    128 
    129 _LIBCPP_FUNC_VIS bool uncaught_exception() _NOEXCEPT;
    130 _LIBCPP_FUNC_VIS int uncaught_exceptions() _NOEXCEPT;
    131 
    132 class _LIBCPP_TYPE_VIS exception_ptr;
    133 
    134 _LIBCPP_FUNC_VIS exception_ptr current_exception() _NOEXCEPT;
    135 _LIBCPP_NORETURN _LIBCPP_FUNC_VIS void rethrow_exception(exception_ptr);
    136 
    137 class _LIBCPP_TYPE_VIS exception_ptr
    138 {
    139     void* __ptr_;
    140 public:
    141     _LIBCPP_INLINE_VISIBILITY exception_ptr() _NOEXCEPT : __ptr_() {}
    142     _LIBCPP_INLINE_VISIBILITY exception_ptr(nullptr_t) _NOEXCEPT : __ptr_() {}
    143     exception_ptr(const exception_ptr&) _NOEXCEPT;
    144     exception_ptr& operator=(const exception_ptr&) _NOEXCEPT;
    145     ~exception_ptr() _NOEXCEPT;
    146 
    147     _LIBCPP_INLINE_VISIBILITY
    148     _LIBCPP_EXPLICIT
    149         operator bool() const _NOEXCEPT {return __ptr_ != nullptr;}
    150 
    151     friend _LIBCPP_INLINE_VISIBILITY
    152     bool operator==(const exception_ptr& __x, const exception_ptr& __y) _NOEXCEPT
    153         {return __x.__ptr_ == __y.__ptr_;}
    154     friend _LIBCPP_INLINE_VISIBILITY
    155     bool operator!=(const exception_ptr& __x, const exception_ptr& __y) _NOEXCEPT
    156         {return !(__x == __y);}
    157 
    158     friend _LIBCPP_FUNC_VIS exception_ptr current_exception() _NOEXCEPT;
    159     friend _LIBCPP_FUNC_VIS void rethrow_exception(exception_ptr);
    160 };
    161 
    162 template<class _Ep>
    163 exception_ptr
    164 make_exception_ptr(_Ep __e) _NOEXCEPT
    165 {
    166 #ifndef _LIBCPP_NO_EXCEPTIONS
    167     try
    168     {
    169         throw __e;
    170     }
    171     catch (...)
    172     {
    173         return current_exception();
    174     }
    175 #else
    176     ((void)__e);
    177     _VSTD::abort();
    178 #endif
    179 }
    180 
    181 // nested_exception
    182 
    183 class _LIBCPP_EXCEPTION_ABI nested_exception
    184 {
    185     exception_ptr __ptr_;
    186 public:
    187     nested_exception() _NOEXCEPT;
    188 //     nested_exception(const nested_exception&) noexcept = default;
    189 //     nested_exception& operator=(const nested_exception&) noexcept = default;
    190     virtual ~nested_exception() _NOEXCEPT;
    191 
    192     // access functions
    193     _LIBCPP_NORETURN void rethrow_nested() const;
    194     _LIBCPP_INLINE_VISIBILITY exception_ptr nested_ptr() const _NOEXCEPT {return __ptr_;}
    195 };
    196 
    197 template <class _Tp>
    198 struct __nested
    199     : public _Tp,
    200       public nested_exception
    201 {
    202     _LIBCPP_INLINE_VISIBILITY explicit __nested(const _Tp& __t) : _Tp(__t) {}
    203 };
    204 
    205 template <class _Tp>
    206 _LIBCPP_NORETURN
    207 void
    208 #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
    209 throw_with_nested(_Tp&& __t, typename enable_if<
    210                   is_class<typename remove_reference<_Tp>::type>::value &&
    211                   !is_base_of<nested_exception, typename remove_reference<_Tp>::type>::value
    212                   && !__libcpp_is_final<typename remove_reference<_Tp>::type>::value
    213                                     >::type* = 0)
    214 #else  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
    215 throw_with_nested (_Tp& __t, typename enable_if<
    216                   is_class<_Tp>::value && !is_base_of<nested_exception, _Tp>::value
    217                                     >::type* = 0)
    218 #endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
    219 {
    220 #ifndef _LIBCPP_NO_EXCEPTIONS
    221     throw __nested<typename remove_reference<_Tp>::type>(_VSTD::forward<_Tp>(__t));
    222 #else
    223     ((void)__t);
    224     // FIXME: Make this abort.
    225 #endif
    226 }
    227 
    228 template <class _Tp>
    229 _LIBCPP_NORETURN
    230 void
    231 #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
    232 throw_with_nested(_Tp&& __t, typename enable_if<
    233                   !is_class<typename remove_reference<_Tp>::type>::value ||
    234                   is_base_of<nested_exception, typename remove_reference<_Tp>::type>::value
    235                   || __libcpp_is_final<typename remove_reference<_Tp>::type>::value
    236                                     >::type* = 0)
    237 #else  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
    238 throw_with_nested (_Tp& __t, typename enable_if<
    239                   !is_class<_Tp>::value || is_base_of<nested_exception, _Tp>::value
    240                                     >::type* = 0)
    241 #endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
    242 {
    243 #ifndef _LIBCPP_NO_EXCEPTIONS
    244     throw _VSTD::forward<_Tp>(__t);
    245 #else
    246     ((void)__t);
    247     // FIXME: Make this abort
    248 #endif
    249 }
    250 
    251 template <class _From, class _To>
    252 struct __can_dynamic_cast : public _LIBCPP_BOOL_CONSTANT(
    253               is_polymorphic<_From>::value &&
    254                  (!is_base_of<_To, _From>::value ||
    255                    is_convertible<const _From*, const _To*>::value)) {};
    256 
    257 template <class _Ep>
    258 inline _LIBCPP_INLINE_VISIBILITY
    259 void
    260 rethrow_if_nested(const _Ep& __e,
    261                   typename enable_if< __can_dynamic_cast<_Ep, nested_exception>::value>::type* = 0)
    262 {
    263     const nested_exception* __nep = dynamic_cast<const nested_exception*>(_VSTD::addressof(__e));
    264     if (__nep)
    265         __nep->rethrow_nested();
    266 }
    267 
    268 template <class _Ep>
    269 inline _LIBCPP_INLINE_VISIBILITY
    270 void
    271 rethrow_if_nested(const _Ep&,
    272                   typename enable_if<!__can_dynamic_cast<_Ep, nested_exception>::value>::type* = 0)
    273 {
    274 }
    275 
    276 }  // std
    277 
    278 #endif  // _LIBCPP_EXCEPTION
    279