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  // __APPLE__
22   static std::terminate_handler  __terminate_handler;
23   static std::unexpected_handler __unexpected_handler;
24 #endif  // __APPLE__
25 
26 std::unexpected_handler
27 std::set_unexpected(std::unexpected_handler func) throw()
28 {
29     std::terminate_handler old = __unexpected_handler;
30     __unexpected_handler = func;
31     return old;
32 }
33 
34 void
35 std::unexpected()
36 {
37     (*__unexpected_handler)();
38     // unexpected handler should not return
39     std::terminate();
40 }
41 
42 std::terminate_handler
43 std::set_terminate(std::terminate_handler func) throw()
44 {
45     std::terminate_handler old = __terminate_handler;
46     __terminate_handler = func;
47     return old;
48 }
49 
50 void
51 std::terminate()
52 {
53 #ifndef _LIBCPP_NO_EXCEPTIONS
54     try
55     {
56 #endif  // _LIBCPP_NO_EXCEPTIONS
57         (*__terminate_handler)();
58         // handler should not return
59         ::abort ();
60 #ifndef _LIBCPP_NO_EXCEPTIONS
61     }
62     catch (...)
63     {
64         // handler should not throw exception
65         ::abort ();
66     }
67 #endif  // _LIBCPP_NO_EXCEPTIONS
68 }
69 
70 bool std::uncaught_exception() throw()
71 {
72 #if __APPLE__
73     // on Darwin, there is a helper function so __cxa_get_globals is private
74     return __cxxabiapple::__cxa_uncaught_exception();
75 #else  // __APPLE__
76     #warning uncaught_exception not yet implemented
77     ::abort();
78     // Not provided by Ubuntu gcc-4.2.4's cxxabi.h.
79     // __cxa_eh_globals * globals = __cxa_get_globals();
80     // return (globals->uncaughtExceptions != 0);
81 #endif  // __APPLE__
82 }
83 
84 namespace std
85 {
86 
87 exception::~exception() throw()
88 {
89 }
90 
91 bad_exception::~bad_exception() throw()
92 {
93 }
94 
95 const char* exception::what() const throw()
96 {
97   return "std::exception";
98 }
99 
100 const char* bad_exception::what() const throw()
101 {
102   return "std::bad_exception";
103 }
104 
105 exception_ptr::~exception_ptr()
106 {
107 #if __APPLE__
108     __cxxabiapple::__cxa_decrement_exception_refcount(__ptr_);
109 #else
110     #warning exception_ptr not yet implemented
111     ::abort();
112 #endif  // __APPLE__
113 }
114 
115 exception_ptr::exception_ptr(const exception_ptr& other)
116     : __ptr_(other.__ptr_)
117 {
118 #if __APPLE__
119     __cxxabiapple::__cxa_increment_exception_refcount(__ptr_);
120 #else
121     #warning exception_ptr not yet implemented
122     ::abort();
123 #endif  // __APPLE__
124 }
125 
126 exception_ptr& exception_ptr::operator=(const exception_ptr& other)
127 {
128 #if __APPLE__
129     if (__ptr_ != other.__ptr_)
130     {
131         __cxxabiapple::__cxa_increment_exception_refcount(other.__ptr_);
132         __cxxabiapple::__cxa_decrement_exception_refcount(__ptr_);
133         __ptr_ = other.__ptr_;
134     }
135     return *this;
136 #else  // __APPLE__
137     #warning exception_ptr not yet implemented
138     ::abort();
139 #endif  // __APPLE__
140 }
141 
142 nested_exception::nested_exception()
143     : __ptr_(current_exception())
144 {
145 }
146 
147 nested_exception::~nested_exception()
148 {
149 }
150 
151 void
152 nested_exception::rethrow_nested /*[[noreturn]]*/ () const
153 {
154     if (__ptr_ == nullptr)
155         terminate();
156     rethrow_exception(__ptr_);
157 }
158 
159 } // std
160 
161 std::exception_ptr std::current_exception()
162 {
163 #if __APPLE__
164     // be nicer if there was a constructor that took a ptr, then
165     // this whole function would be just:
166     //    return exception_ptr(__cxa_current_primary_exception());
167     std::exception_ptr ptr;
168     ptr.__ptr_ = __cxxabiapple::__cxa_current_primary_exception();
169     return ptr;
170 #else  // __APPLE__
171     #warning exception_ptr not yet implemented
172     ::abort();
173 #endif  // __APPLE__
174 }
175 
176 void std::rethrow_exception(exception_ptr p)
177 {
178 #if __APPLE__
179     __cxxabiapple::__cxa_rethrow_primary_exception(p.__ptr_);
180     // if p.__ptr_ is NULL, above returns so we terminate
181     terminate();
182 #else  // __APPLE__
183     #warning exception_ptr not yet implemented
184     ::abort();
185 #endif  // __APPLE__
186 }
187