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