blob: 336527df2755e7698756ba345db185a8121d14e5 [file] [log] [blame]
Nick Kledzik804b6e72010-05-14 20:19:37 +00001//===------------------------ 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
28std::unexpected_handler
29std::set_unexpected(std::unexpected_handler func) throw()
30{
31 std::terminate_handler old = __unexpected_handler;
32 __unexpected_handler = func;
33 return old;
34}
35
36void
37std::unexpected()
38{
39 (*__unexpected_handler)();
40 // unexpected handler should not return
41 std::terminate();
42}
43
44
45std::terminate_handler
46std::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
54void
55std::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
69bool 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 __cxa_eh_globals * globals = __cxa_get_globals();
76 return (globals->uncaughtExceptions != 0);
77#endif
78}
79
80
81namespace std
82{
83
84
85exception::~exception() throw()
86{
87}
88
89bad_exception::~bad_exception() throw()
90{
91}
92
93const char* exception::what() const throw()
94{
95 return "std::exception";
96}
97
98const char* bad_exception::what() const throw()
99{
100 return "std::bad_exception";
101}
102
103
104
105exception_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
113}
114
115exception_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
124}
125
126exception_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
137 #warning exception_ptr not yet implemented
138 ::abort();
139#endif
140}
141
142} // std
143
144
145std::exception_ptr std::current_exception()
146{
147#if __APPLE__
148 // be nicer if there was a constructor that took a ptr, then
149 // this whole function would be just:
150 // return exception_ptr(__cxa_current_primary_exception());
151 std::exception_ptr ptr;
152 ptr.__ptr_ = __cxxabiapple::__cxa_current_primary_exception();
153 return ptr;
154#else
155 #warning exception_ptr not yet implemented
156 ::abort();
157#endif
158}
159
160void std::rethrow_exception(exception_ptr p)
161{
162#if __APPLE__
163 __cxxabiapple::__cxa_rethrow_primary_exception(p.__ptr_);
164 // if p.__ptr_ is NULL, above returns so we terminate
165 terminate();
166#else
167 #warning exception_ptr not yet implemented
168 ::abort();
169#endif
170}
171