1 //===------------------------ exception.cpp -------------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 #include <stdlib.h>
10 
11 #include "exception"
12 
13 #if __APPLE__
14   #include <cxxabi.h>
15   using namespace __cxxabiv1;
16   // On Darwin, there are two STL shared libraries and a lower level ABI
17   // shared libray.  The globals holding the current terminate handler and
18   // current unexpected handler are in the ABI library.
19   #define __terminate_handler  __cxxabiapple::__cxa_terminate_handler
20   #define __unexpected_handler __cxxabiapple::__cxa_unexpected_handler
21 #else
22   static std::terminate_handler  __terminate_handler;
23   static std::unexpected_handler __unexpected_handler;
24 #endif
25 
26 
27 
28 std::unexpected_handler
29 std::set_unexpected(std::unexpected_handler func) throw()
30 {
31     std::terminate_handler old = __unexpected_handler;
32     __unexpected_handler = func;
33     return old;
34 }
35 
36 void
37 std::unexpected()
38 {
39     (*__unexpected_handler)();
40 	// unexpected handler should not return
41     std::terminate();
42 }
43 
44 
45 std::terminate_handler
46 std::set_terminate(std::terminate_handler func) throw()
47 {
48     std::terminate_handler old = __terminate_handler;
49     __terminate_handler = func;
50     return old;
51 }
52 
53 
54 void
55 std::terminate()
56 {
57     try {
58         (*__terminate_handler)();
59         // handler should not return
60         ::abort ();
61     }
62     catch (...) {
63         // handler should not throw exception
64         ::abort ();
65     }
66 }
67 
68 
69 bool std::uncaught_exception() throw()
70 {
71 #if __APPLE__
72 	// on Darwin, there is a helper function so __cxa_get_globals is private
73     return __cxxabiapple::__cxa_uncaught_exception();
74 #else
75     #warning uncaught_exception not yet implemented
76     ::abort();
77     // Not provided by Ubuntu gcc-4.2.4's cxxabi.h.
78     // __cxa_eh_globals * globals = __cxa_get_globals();
79     // return (globals->uncaughtExceptions != 0);
80 #endif
81 }
82 
83 
84 namespace std
85 {
86 
87 
88 exception::~exception() throw()
89 {
90 }
91 
92 bad_exception::~bad_exception() throw()
93 {
94 }
95 
96 const char* exception::what() const throw()
97 {
98   return "std::exception";
99 }
100 
101 const char* bad_exception::what() const throw()
102 {
103   return "std::bad_exception";
104 }
105 
106 
107 
108 exception_ptr::~exception_ptr()
109 {
110 #if __APPLE__
111     __cxxabiapple::__cxa_decrement_exception_refcount(__ptr_);
112 #else
113 	#warning exception_ptr not yet implemented
114 	::abort();
115 #endif
116 }
117 
118 exception_ptr::exception_ptr(const exception_ptr& other)
119     : __ptr_(other.__ptr_)
120 {
121 #if __APPLE__
122     __cxxabiapple::__cxa_increment_exception_refcount(__ptr_);
123 #else
124 	#warning exception_ptr not yet implemented
125 	::abort();
126 #endif
127 }
128 
129 exception_ptr& exception_ptr::operator=(const exception_ptr& other)
130 {
131 #if __APPLE__
132     if (__ptr_ != other.__ptr_)
133     {
134         __cxxabiapple::__cxa_increment_exception_refcount(other.__ptr_);
135         __cxxabiapple::__cxa_decrement_exception_refcount(__ptr_);
136 		__ptr_ = other.__ptr_;
137 	}
138     return *this;
139 #else
140 	#warning exception_ptr not yet implemented
141 	::abort();
142 #endif
143 }
144 
145 nested_exception::nested_exception()
146     : __ptr_(current_exception())
147 {
148 }
149 
150 nested_exception::~nested_exception()
151 {
152 }
153 
154 void
155 nested_exception::rethrow_nested /*[[noreturn]]*/ () const
156 {
157     if (__ptr_ == nullptr)
158         terminate();
159     rethrow_exception(__ptr_);
160 }
161 
162 } // std
163 
164 
165 std::exception_ptr std::current_exception()
166 {
167 #if __APPLE__
168 	// be nicer if there was a constructor that took a ptr, then
169 	// this whole function would be just:
170 	//    return exception_ptr(__cxa_current_primary_exception());
171     std::exception_ptr ptr;
172 	ptr.__ptr_ = __cxxabiapple::__cxa_current_primary_exception();
173 	return ptr;
174 #else
175 	#warning exception_ptr not yet implemented
176 	::abort();
177 #endif
178 }
179 
180 void std::rethrow_exception(exception_ptr p)
181 {
182 #if __APPLE__
183 	__cxxabiapple::__cxa_rethrow_primary_exception(p.__ptr_);
184 	// if p.__ptr_ is NULL, above returns so we terminate
185     terminate();
186 #else
187 	#warning exception_ptr not yet implemented
188 	::abort();
189 #endif
190 }
191