| Howard Hinnant | bc8d3f9 | 2010-05-11 19:42:16 +0000 | [diff] [blame] | 1 | // -*- C++ -*- | 
 | 2 | //===-------------------------- exception ---------------------------------===// | 
 | 3 | // | 
| Howard Hinnant | f5256e1 | 2010-05-11 21:36:01 +0000 | [diff] [blame] | 4 | //                     The LLVM Compiler Infrastructure | 
| Howard Hinnant | bc8d3f9 | 2010-05-11 19:42:16 +0000 | [diff] [blame] | 5 | // | 
 | 6 | // This file is distributed under the University of Illinois Open Source | 
 | 7 | // License. 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() throw(); | 
 | 24 |     exception(const exception&) throw(); | 
 | 25 |     exception& operator=(const exception&) throw(); | 
 | 26 |     virtual ~exception() throw(); | 
 | 27 |     virtual const char* what() const throw(); | 
 | 28 | }; | 
 | 29 |  | 
 | 30 | class bad_exception | 
 | 31 |     : public exception | 
 | 32 | { | 
 | 33 | public: | 
 | 34 |     bad_exception() throw(); | 
 | 35 |     bad_exception(const bad_exception&) throw(); | 
 | 36 |     bad_exception& operator=(const bad_exception&) throw(); | 
 | 37 |     virtual ~bad_exception() throw(); | 
 | 38 |     virtual const char* what() const throw(); | 
 | 39 | }; | 
 | 40 |  | 
 | 41 | typedef void (*unexpected_handler)(); | 
 | 42 | unexpected_handler set_unexpected(unexpected_handler  f ) throw(); | 
 | 43 | void unexpected [[noreturn]] (); | 
 | 44 |  | 
 | 45 | typedef void (*terminate_handler)(); | 
 | 46 | terminate_handler set_terminate(terminate_handler  f ) throw(); | 
 | 47 | void terminate [[noreturn]] (); | 
 | 48 |  | 
 | 49 | bool uncaught_exception() throw(); | 
 | 50 |  | 
 | 51 | typedef unspecified exception_ptr; | 
 | 52 |  | 
 | 53 | exception_ptr current_exception(); | 
 | 54 | void rethrow_exception [[noreturn]] (exception_ptr p); | 
 | 55 | template<class E> exception_ptr make_exception_ptr(E e); | 
 | 56 |  | 
 | 57 | class nested_exception | 
 | 58 | { | 
 | 59 | public: | 
 | 60 |     nested_exception() throw(); | 
 | 61 |     nested_exception(const nested_exception&) throw() = default; | 
 | 62 |     nested_exception& operator=(const nested_exception&) throw() = default; | 
 | 63 |     virtual ~nested_exception() = default; | 
 | 64 |  | 
 | 65 |     // access functions | 
 | 66 |     void rethrow_nested [[noreturn]] () const; | 
 | 67 |     exception_ptr nested_ptr() const; | 
 | 68 | }; | 
 | 69 |  | 
 | 70 | template <class T> void throw_with_nested [[noreturn]] (T&& t); | 
 | 71 | template <class E> void rethrow_if_nested(const E& e); | 
 | 72 |  | 
 | 73 | }  // std | 
 | 74 |  | 
 | 75 | */ | 
 | 76 |  | 
 | 77 | #include <__config> | 
 | 78 | #include <cstddef> | 
| Howard Hinnant | ed2c291 | 2010-05-27 17:06:52 +0000 | [diff] [blame] | 79 | #include <type_traits> | 
| Howard Hinnant | bc8d3f9 | 2010-05-11 19:42:16 +0000 | [diff] [blame] | 80 |  | 
 | 81 | #pragma GCC system_header | 
 | 82 |  | 
 | 83 | namespace std  // purposefully not using versioning namespace | 
 | 84 | { | 
 | 85 |  | 
 | 86 | class _LIBCPP_EXCEPTION_ABI exception | 
 | 87 | { | 
 | 88 | public: | 
 | 89 |     _LIBCPP_INLINE_VISIBILITY exception() throw() {} | 
 | 90 |     virtual ~exception() throw(); | 
 | 91 |     virtual const char* what() const throw(); | 
 | 92 | }; | 
 | 93 |  | 
 | 94 | class _LIBCPP_EXCEPTION_ABI bad_exception | 
 | 95 |     : public exception | 
 | 96 | { | 
 | 97 | public: | 
 | 98 |     _LIBCPP_INLINE_VISIBILITY bad_exception() throw() {} | 
 | 99 |     virtual ~bad_exception() throw(); | 
 | 100 |     virtual const char* what() const throw(); | 
 | 101 | }; | 
 | 102 |  | 
 | 103 | typedef void (*unexpected_handler)(); | 
 | 104 | _LIBCPP_VISIBLE unexpected_handler set_unexpected(unexpected_handler) throw(); | 
 | 105 | _LIBCPP_VISIBLE void unexpected(); | 
 | 106 |  | 
 | 107 | typedef void (*terminate_handler)(); | 
 | 108 | _LIBCPP_VISIBLE terminate_handler set_terminate(terminate_handler) throw(); | 
 | 109 | _LIBCPP_VISIBLE void terminate() __attribute__((__noreturn__)); | 
 | 110 |  | 
 | 111 | _LIBCPP_VISIBLE bool uncaught_exception() throw(); | 
 | 112 |  | 
 | 113 | class exception_ptr; | 
 | 114 |  | 
 | 115 | exception_ptr current_exception(); | 
 | 116 | void rethrow_exception(exception_ptr);  // noreturn | 
 | 117 |  | 
 | 118 | class exception_ptr | 
 | 119 | { | 
 | 120 |     void* __ptr_; | 
 | 121 | public: | 
 | 122 |     exception_ptr()  : __ptr_() {} | 
 | 123 |     exception_ptr(nullptr_t) : __ptr_() {} | 
 | 124 |     exception_ptr(const exception_ptr&); | 
 | 125 |     exception_ptr& operator=(const exception_ptr&); | 
 | 126 |     ~exception_ptr(); | 
 | 127 |  | 
 | 128 |     // explicit | 
 | 129 |         operator bool() const {return __ptr_ != nullptr;} | 
 | 130 |  | 
 | 131 |     friend bool operator==(const exception_ptr& __x, const exception_ptr& __y) | 
 | 132 |         {return __x.__ptr_ == __y.__ptr_;} | 
 | 133 |     friend bool operator!=(const exception_ptr& __x, const exception_ptr& __y) | 
 | 134 |         {return !(__x == __y);} | 
 | 135 |  | 
 | 136 |     friend exception_ptr current_exception(); | 
 | 137 |     friend void rethrow_exception(exception_ptr);  // noreturn | 
 | 138 | }; | 
 | 139 |  | 
 | 140 | template<class _E> | 
 | 141 | exception_ptr | 
 | 142 | make_exception_ptr(_E __e) | 
 | 143 | { | 
| Howard Hinnant | d444470 | 2010-08-11 17:04:31 +0000 | [diff] [blame] | 144 | #ifndef _LIBCPP_NO_EXCEPTIONS | 
| Howard Hinnant | bc8d3f9 | 2010-05-11 19:42:16 +0000 | [diff] [blame] | 145 |     try | 
 | 146 |     { | 
 | 147 |         throw __e; | 
 | 148 |     } | 
 | 149 |     catch (...) | 
 | 150 |     { | 
 | 151 |         return current_exception(); | 
 | 152 |     } | 
| Howard Hinnant | 324bb03 | 2010-08-22 00:02:43 +0000 | [diff] [blame] | 153 | #endif  // _LIBCPP_NO_EXCEPTIONS | 
| Howard Hinnant | bc8d3f9 | 2010-05-11 19:42:16 +0000 | [diff] [blame] | 154 | } | 
 | 155 |  | 
| Howard Hinnant | ed2c291 | 2010-05-27 17:06:52 +0000 | [diff] [blame] | 156 | // nested_exception | 
 | 157 |  | 
 | 158 | class _LIBCPP_EXCEPTION_ABI nested_exception | 
 | 159 | { | 
 | 160 |     exception_ptr __ptr_; | 
 | 161 | public: | 
 | 162 |     nested_exception(); | 
 | 163 | //     nested_exception(const nested_exception&) throw() = default; | 
 | 164 | //     nested_exception& operator=(const nested_exception&) throw() = default; | 
 | 165 |     virtual ~nested_exception(); | 
 | 166 |  | 
 | 167 |     // access functions | 
 | 168 |     void rethrow_nested /*[[noreturn]]*/ () const; | 
 | 169 |     exception_ptr nested_ptr() const {return __ptr_;} | 
 | 170 | }; | 
 | 171 |  | 
 | 172 | template <class _Tp> | 
 | 173 | struct __nested | 
 | 174 |     : public _Tp, | 
 | 175 |       public nested_exception | 
 | 176 | { | 
 | 177 |     explicit __nested(const _Tp& __t) : _Tp(__t) {} | 
 | 178 | }; | 
 | 179 |  | 
 | 180 | template <class _Tp> | 
| Howard Hinnant | 324bb03 | 2010-08-22 00:02:43 +0000 | [diff] [blame] | 181 | void | 
| Howard Hinnant | 73d21a4 | 2010-09-04 23:28:19 +0000 | [diff] [blame^] | 182 | #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES | 
| Howard Hinnant | ed2c291 | 2010-05-27 17:06:52 +0000 | [diff] [blame] | 183 | throw_with_nested /*[[noreturn]]*/ (_Tp&& __t, typename enable_if< | 
 | 184 |                   is_class<typename remove_reference<_Tp>::type>::value && | 
 | 185 |                   !is_base_of<nested_exception, typename remove_reference<_Tp>::type>::value | 
 | 186 |                                     >::type* = 0) | 
| Howard Hinnant | 73d21a4 | 2010-09-04 23:28:19 +0000 | [diff] [blame^] | 187 | #else  // _LIBCPP_HAS_NO_RVALUE_REFERENCES | 
| Howard Hinnant | ed2c291 | 2010-05-27 17:06:52 +0000 | [diff] [blame] | 188 | throw_with_nested (_Tp& __t, typename enable_if< | 
 | 189 |                   is_class<_Tp>::value && !is_base_of<nested_exception, _Tp>::value | 
 | 190 |                                     >::type* = 0) | 
| Howard Hinnant | 73d21a4 | 2010-09-04 23:28:19 +0000 | [diff] [blame^] | 191 | #endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES | 
| Howard Hinnant | ed2c291 | 2010-05-27 17:06:52 +0000 | [diff] [blame] | 192 | { | 
| Howard Hinnant | d444470 | 2010-08-11 17:04:31 +0000 | [diff] [blame] | 193 | #ifndef _LIBCPP_NO_EXCEPTIONS | 
| Howard Hinnant | ed2c291 | 2010-05-27 17:06:52 +0000 | [diff] [blame] | 194 |     throw __nested<typename remove_reference<_Tp>::type>(_STD::forward<_Tp>(__t)); | 
| Howard Hinnant | d444470 | 2010-08-11 17:04:31 +0000 | [diff] [blame] | 195 | #endif | 
| Howard Hinnant | ed2c291 | 2010-05-27 17:06:52 +0000 | [diff] [blame] | 196 | } | 
 | 197 |  | 
 | 198 | template <class _Tp> | 
| Howard Hinnant | 324bb03 | 2010-08-22 00:02:43 +0000 | [diff] [blame] | 199 | void | 
| Howard Hinnant | 73d21a4 | 2010-09-04 23:28:19 +0000 | [diff] [blame^] | 200 | #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES | 
| Howard Hinnant | ed2c291 | 2010-05-27 17:06:52 +0000 | [diff] [blame] | 201 | throw_with_nested /*[[noreturn]]*/ (_Tp&& __t, typename enable_if< | 
 | 202 |                   !is_class<typename remove_reference<_Tp>::type>::value || | 
 | 203 |                   is_base_of<nested_exception, typename remove_reference<_Tp>::type>::value | 
 | 204 |                                     >::type* = 0) | 
| Howard Hinnant | 73d21a4 | 2010-09-04 23:28:19 +0000 | [diff] [blame^] | 205 | #else  // _LIBCPP_HAS_NO_RVALUE_REFERENCES | 
| Howard Hinnant | ed2c291 | 2010-05-27 17:06:52 +0000 | [diff] [blame] | 206 | throw_with_nested (_Tp& __t, typename enable_if< | 
 | 207 |                   !is_class<_Tp>::value || is_base_of<nested_exception, _Tp>::value | 
 | 208 |                                     >::type* = 0) | 
| Howard Hinnant | 73d21a4 | 2010-09-04 23:28:19 +0000 | [diff] [blame^] | 209 | #endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES | 
| Howard Hinnant | ed2c291 | 2010-05-27 17:06:52 +0000 | [diff] [blame] | 210 | { | 
| Howard Hinnant | d444470 | 2010-08-11 17:04:31 +0000 | [diff] [blame] | 211 | #ifndef _LIBCPP_NO_EXCEPTIONS | 
| Howard Hinnant | ed2c291 | 2010-05-27 17:06:52 +0000 | [diff] [blame] | 212 |     throw _STD::forward<_Tp>(__t); | 
| Howard Hinnant | d444470 | 2010-08-11 17:04:31 +0000 | [diff] [blame] | 213 | #endif | 
| Howard Hinnant | ed2c291 | 2010-05-27 17:06:52 +0000 | [diff] [blame] | 214 | } | 
 | 215 |  | 
 | 216 | template <class _E> | 
 | 217 | inline | 
 | 218 | void | 
 | 219 | rethrow_if_nested(const _E& __e, typename enable_if< | 
| Howard Hinnant | 6bb9f58 | 2010-05-28 13:35:41 +0000 | [diff] [blame] | 220 |                                    is_polymorphic<_E>::value | 
| Howard Hinnant | ed2c291 | 2010-05-27 17:06:52 +0000 | [diff] [blame] | 221 |                                                    >::type* = 0) | 
 | 222 | { | 
| Howard Hinnant | 6bb9f58 | 2010-05-28 13:35:41 +0000 | [diff] [blame] | 223 |     const nested_exception* __nep = dynamic_cast<const nested_exception*>(&__e); | 
 | 224 |     if (__nep) | 
 | 225 |         __nep->rethrow_nested(); | 
| Howard Hinnant | ed2c291 | 2010-05-27 17:06:52 +0000 | [diff] [blame] | 226 | } | 
 | 227 |  | 
 | 228 | template <class _E> | 
 | 229 | inline | 
 | 230 | void | 
 | 231 | rethrow_if_nested(const _E& __e, typename enable_if< | 
| Howard Hinnant | 6bb9f58 | 2010-05-28 13:35:41 +0000 | [diff] [blame] | 232 |                                    !is_polymorphic<_E>::value | 
| Howard Hinnant | ed2c291 | 2010-05-27 17:06:52 +0000 | [diff] [blame] | 233 |                                                    >::type* = 0) | 
 | 234 | { | 
 | 235 | } | 
 | 236 |  | 
| Howard Hinnant | bc8d3f9 | 2010-05-11 19:42:16 +0000 | [diff] [blame] | 237 | }  // std | 
 | 238 |  | 
 | 239 | #endif  // _LIBCPP_EXCEPTION |