• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===------------------------ exception.cpp -------------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is dual licensed under the MIT and the University of Illinois Open
6 // Source Licenses. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 #include <stdlib.h>
10 
11 #include "exception"
12 
13 #ifndef __has_include
14 #define __has_include(inc) 0
15 #endif
16 
17 #if __APPLE__
18   #include <cxxabi.h>
19 
20   using namespace __cxxabiv1;
21   #define HAVE_DEPENDENT_EH_ABI 1
22   #ifndef _LIBCPPABI_VERSION
23     using namespace __cxxabiapple;
24     // On Darwin, there are two STL shared libraries and a lower level ABI
25     // shared libray.  The globals holding the current terminate handler and
26     // current unexpected handler are in the ABI library.
27     #define __terminate_handler  __cxxabiapple::__cxa_terminate_handler
28     #define __unexpected_handler __cxxabiapple::__cxa_unexpected_handler
29   #endif  // _LIBCPPABI_VERSION
30 #elif defined(LIBCXXRT) || __has_include(<cxxabi.h>)
31   #include <cxxabi.h>
32   using namespace __cxxabiv1;
33   #if defined(LIBCXXRT) || defined(_LIBCPPABI_VERSION)
34     #define HAVE_DEPENDENT_EH_ABI 1
35   #endif
36 #else  // __has_include(<cxxabi.h>)
37   static std::terminate_handler  __terminate_handler;
38   static std::unexpected_handler __unexpected_handler;
39 #endif // __has_include(<cxxabi.h>)
40 
41 namespace std
42 {
43 
44 #if !defined(LIBCXXRT) && !defined(_LIBCPPABI_VERSION) && !defined(__GLIBCXX__)
45 
46 // libcxxrt provides implementations of these functions itself.
47 unexpected_handler
set_unexpected(unexpected_handler func)48 set_unexpected(unexpected_handler func) _NOEXCEPT
49 {
50     return __sync_lock_test_and_set(&__unexpected_handler, func);
51 }
52 
53 unexpected_handler
get_unexpected()54 get_unexpected() _NOEXCEPT
55 {
56     return __sync_fetch_and_add(&__unexpected_handler, (unexpected_handler)0);
57 }
58 
59 _LIBCPP_NORETURN
60 void
unexpected()61 unexpected()
62 {
63     (*get_unexpected())();
64     // unexpected handler should not return
65     terminate();
66 }
67 
68 terminate_handler
set_terminate(terminate_handler func)69 set_terminate(terminate_handler func) _NOEXCEPT
70 {
71     return __sync_lock_test_and_set(&__terminate_handler, func);
72 }
73 
74 terminate_handler
get_terminate()75 get_terminate() _NOEXCEPT
76 {
77     return __sync_fetch_and_add(&__terminate_handler, (terminate_handler)0);
78 }
79 
80 _LIBCPP_NORETURN
81 void
terminate()82 terminate() _NOEXCEPT
83 {
84 #ifndef _LIBCPP_NO_EXCEPTIONS
85     try
86     {
87 #endif  // _LIBCPP_NO_EXCEPTIONS
88         (*get_terminate())();
89         // handler should not return
90         ::abort ();
91 #ifndef _LIBCPP_NO_EXCEPTIONS
92     }
93     catch (...)
94     {
95         // handler should not throw exception
96         ::abort ();
97     }
98 #endif  // _LIBCPP_NO_EXCEPTIONS
99 }
100 #endif // !defined(LIBCXXRT) && !defined(_LIBCPPABI_VERSION)
101 
102 #if !defined(LIBCXXRT) && !defined(__GLIBCXX__)
uncaught_exception()103 bool uncaught_exception() _NOEXCEPT
104 {
105 #if __APPLE__ || defined(_LIBCPPABI_VERSION)
106     // on Darwin, there is a helper function so __cxa_get_globals is private
107     return __cxa_uncaught_exception();
108 #else  // __APPLE__
109     #warning uncaught_exception not yet implemented
110     ::abort();
111 #endif  // __APPLE__
112 }
113 
114 #ifndef _LIBCPPABI_VERSION
115 
~exception()116 exception::~exception() _NOEXCEPT
117 {
118 }
119 
what() const120 const char* exception::what() const _NOEXCEPT
121 {
122   return "std::exception";
123 }
124 
125 #endif  // _LIBCPPABI_VERSION
126 #endif //LIBCXXRT
127 #if !defined(_LIBCPPABI_VERSION) && !defined(__GLIBCXX__)
128 
~bad_exception()129 bad_exception::~bad_exception() _NOEXCEPT
130 {
131 }
132 
what() const133 const char* bad_exception::what() const _NOEXCEPT
134 {
135   return "std::bad_exception";
136 }
137 
138 #endif
139 
140 
~exception_ptr()141 exception_ptr::~exception_ptr() _NOEXCEPT
142 {
143 #if HAVE_DEPENDENT_EH_ABI
144     __cxa_decrement_exception_refcount(__ptr_);
145 #else
146     #warning exception_ptr not yet implemented
147     ::abort();
148 #endif  // __APPLE__
149 }
150 
exception_ptr(const exception_ptr & other)151 exception_ptr::exception_ptr(const exception_ptr& other) _NOEXCEPT
152     : __ptr_(other.__ptr_)
153 {
154 #if HAVE_DEPENDENT_EH_ABI
155     __cxa_increment_exception_refcount(__ptr_);
156 #else
157     #warning exception_ptr not yet implemented
158     ::abort();
159 #endif  // __APPLE__
160 }
161 
operator =(const exception_ptr & other)162 exception_ptr& exception_ptr::operator=(const exception_ptr& other) _NOEXCEPT
163 {
164 #if HAVE_DEPENDENT_EH_ABI
165     if (__ptr_ != other.__ptr_)
166     {
167         __cxa_increment_exception_refcount(other.__ptr_);
168         __cxa_decrement_exception_refcount(__ptr_);
169         __ptr_ = other.__ptr_;
170     }
171     return *this;
172 #else  // __APPLE__
173     #warning exception_ptr not yet implemented
174     ::abort();
175 #endif  // __APPLE__
176 }
177 
nested_exception()178 nested_exception::nested_exception() _NOEXCEPT
179     : __ptr_(current_exception())
180 {
181 }
182 
~nested_exception()183 nested_exception::~nested_exception() _NOEXCEPT
184 {
185 }
186 
187 _LIBCPP_NORETURN
188 void
rethrow_nested() const189 nested_exception::rethrow_nested() const
190 {
191     if (__ptr_ == nullptr)
192         terminate();
193     rethrow_exception(__ptr_);
194 }
195 
196 
current_exception()197 exception_ptr current_exception() _NOEXCEPT
198 {
199 #if HAVE_DEPENDENT_EH_ABI
200     // be nicer if there was a constructor that took a ptr, then
201     // this whole function would be just:
202     //    return exception_ptr(__cxa_current_primary_exception());
203     exception_ptr ptr;
204     ptr.__ptr_ = __cxa_current_primary_exception();
205     return ptr;
206 #else  // __APPLE__
207     #warning exception_ptr not yet implemented
208     ::abort();
209 #endif  // __APPLE__
210 }
211 
212 _LIBCPP_NORETURN
rethrow_exception(exception_ptr p)213 void rethrow_exception(exception_ptr p)
214 {
215 #if HAVE_DEPENDENT_EH_ABI
216     __cxa_rethrow_primary_exception(p.__ptr_);
217     // if p.__ptr_ is NULL, above returns so we terminate
218     terminate();
219 #else  // __APPLE__
220     #warning exception_ptr not yet implemented
221     ::abort();
222 #endif  // __APPLE__
223 }
224 } // std
225