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#include <stdio.h>
11
12#include "exception"
13#include "new"
14
15#ifndef __has_include
16#ifdef LIBCXXABI
17#define __has_include(inc) 1
18#else
19#define __has_include(inc) 0
20#endif
21#endif
22
23#ifdef __APPLE__
24  #include <cxxabi.h>
25
26  using namespace __cxxabiv1;
27  #define HAVE_DEPENDENT_EH_ABI 1
28  #ifndef _LIBCPPABI_VERSION
29    using namespace __cxxabiapple;
30    // On Darwin, there are two STL shared libraries and a lower level ABI
31    // shared library.  The globals holding the current terminate handler and
32    // current unexpected handler are in the ABI library.
33    #define __terminate_handler  __cxxabiapple::__cxa_terminate_handler
34    #define __unexpected_handler __cxxabiapple::__cxa_unexpected_handler
35  #endif  // _LIBCPPABI_VERSION
36#elif defined(LIBCXXRT) || __has_include(<cxxabi.h>)
37  #include <cxxabi.h>
38  using namespace __cxxabiv1;
39  #if defined(LIBCXXRT) || defined(_LIBCPPABI_VERSION)
40    #define HAVE_DEPENDENT_EH_ABI 1
41  #endif
42#elif !defined(__GLIBCXX__) // __has_include(<cxxabi.h>)
43  static std::terminate_handler  __terminate_handler;
44  static std::unexpected_handler __unexpected_handler;
45#endif // __has_include(<cxxabi.h>)
46
47namespace std
48{
49
50#if !defined(LIBCXXRT) && !defined(__GLIBCXX__) && !defined(__EMSCRIPTEN__)
51bool uncaught_exception() _NOEXCEPT
52{
53#if defined(__APPLE__) || defined(_LIBCPPABI_VERSION)
54    // on Darwin, there is a helper function so __cxa_get_globals is private
55    return __cxa_uncaught_exception();
56#else  // __APPLE__
57#   if defined(_MSC_VER) && ! defined(__clang__)
58        _LIBCPP_WARNING("uncaught_exception not yet implemented")
59#   else
60#       warning uncaught_exception not yet implemented
61#   endif
62    printf("uncaught_exception not yet implemented\n");
63    ::abort();
64#endif  // __APPLE__
65}
66
67
68#ifndef _LIBCPPABI_VERSION
69
70exception::~exception() _NOEXCEPT
71{
72}
73
74const char* exception::what() const _NOEXCEPT
75{
76  return "std::exception";
77}
78
79#endif  // _LIBCPPABI_VERSION
80#endif //LIBCXXRT
81#if !defined(_LIBCPPABI_VERSION) && !defined(__GLIBCXX__)
82
83bad_exception::~bad_exception() _NOEXCEPT
84{
85}
86
87const char* bad_exception::what() const _NOEXCEPT
88{
89  return "std::bad_exception";
90}
91
92#endif
93
94#if defined(__GLIBCXX__)
95
96// libsupc++ does not implement the dependent EH ABI and the functionality
97// it uses to implement std::exception_ptr (which it declares as an alias of
98// std::__exception_ptr::exception_ptr) is not directly exported to clients. So
99// we have little choice but to hijack std::__exception_ptr::exception_ptr's
100// (which fortunately has the same layout as our std::exception_ptr) copy
101// constructor, assignment operator and destructor (which are part of its
102// stable ABI), and its rethrow_exception(std::__exception_ptr::exception_ptr)
103// function.
104
105namespace __exception_ptr
106{
107
108struct exception_ptr
109{
110    void* __ptr_;
111
112    exception_ptr(const exception_ptr&) _NOEXCEPT;
113    exception_ptr& operator=(const exception_ptr&) _NOEXCEPT;
114    ~exception_ptr() _NOEXCEPT;
115};
116
117}
118
119_LIBCPP_NORETURN void rethrow_exception(__exception_ptr::exception_ptr);
120
121#endif
122
123exception_ptr::~exception_ptr() _NOEXCEPT
124{
125#if HAVE_DEPENDENT_EH_ABI
126    __cxa_decrement_exception_refcount(__ptr_);
127#elif defined(__GLIBCXX__)
128    reinterpret_cast<__exception_ptr::exception_ptr*>(this)->~exception_ptr();
129#else
130#   if defined(_MSC_VER) && ! defined(__clang__)
131        _LIBCPP_WARNING("exception_ptr not yet implemented")
132#   else
133#       warning exception_ptr not yet implemented
134#   endif
135    printf("exception_ptr not yet implemented\n");
136    ::abort();
137#endif
138}
139
140exception_ptr::exception_ptr(const exception_ptr& other) _NOEXCEPT
141    : __ptr_(other.__ptr_)
142{
143#if HAVE_DEPENDENT_EH_ABI
144    __cxa_increment_exception_refcount(__ptr_);
145#elif defined(__GLIBCXX__)
146    new (reinterpret_cast<void*>(this)) __exception_ptr::exception_ptr(
147        reinterpret_cast<const __exception_ptr::exception_ptr&>(other));
148#else
149#   if defined(_MSC_VER) && ! defined(__clang__)
150        _LIBCPP_WARNING("exception_ptr not yet implemented")
151#   else
152#       warning exception_ptr not yet implemented
153#   endif
154    printf("exception_ptr not yet implemented\n");
155    ::abort();
156#endif
157}
158
159exception_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#elif defined(__GLIBCXX__)
170    *reinterpret_cast<__exception_ptr::exception_ptr*>(this) =
171        reinterpret_cast<const __exception_ptr::exception_ptr&>(other);
172    return *this;
173#else
174#   if defined(_MSC_VER) && ! defined(__clang__)
175        _LIBCPP_WARNING("exception_ptr not yet implemented")
176#   else
177#       warning exception_ptr not yet implemented
178#   endif
179    printf("exception_ptr not yet implemented\n");
180    ::abort();
181#endif
182}
183
184nested_exception::nested_exception() _NOEXCEPT
185    : __ptr_(current_exception())
186{
187}
188
189#if !defined(__GLIBCXX__)
190
191nested_exception::~nested_exception() _NOEXCEPT
192{
193}
194
195#endif
196
197_LIBCPP_NORETURN
198void
199nested_exception::rethrow_nested() const
200{
201    if (__ptr_ == nullptr)
202        terminate();
203    rethrow_exception(__ptr_);
204}
205
206#if !defined(__GLIBCXX__)
207
208exception_ptr current_exception() _NOEXCEPT
209{
210#if HAVE_DEPENDENT_EH_ABI
211    // be nicer if there was a constructor that took a ptr, then
212    // this whole function would be just:
213    //    return exception_ptr(__cxa_current_primary_exception());
214    exception_ptr ptr;
215    ptr.__ptr_ = __cxa_current_primary_exception();
216    return ptr;
217#else
218#   if defined(_MSC_VER) && ! defined(__clang__)
219        _LIBCPP_WARNING( "exception_ptr not yet implemented" )
220#   else
221#       warning exception_ptr not yet implemented
222#   endif
223    printf("exception_ptr not yet implemented\n");
224    ::abort();
225#endif
226}
227
228#endif  // !__GLIBCXX__
229
230_LIBCPP_NORETURN
231void rethrow_exception(exception_ptr p)
232{
233#if HAVE_DEPENDENT_EH_ABI
234    __cxa_rethrow_primary_exception(p.__ptr_);
235    // if p.__ptr_ is NULL, above returns so we terminate
236    terminate();
237#elif defined(__GLIBCXX__)
238    rethrow_exception(reinterpret_cast<__exception_ptr::exception_ptr&>(p));
239#else
240#   if defined(_MSC_VER) && ! defined(__clang__)
241        _LIBCPP_WARNING("exception_ptr not yet implemented")
242#   else
243#       warning exception_ptr not yet implemented
244#   endif
245    printf("exception_ptr not yet implemented\n");
246    ::abort();
247#endif
248}
249} // std
250