blob: b0efda648e59d60b669f32dac7b7b1f57430d057 [file] [log] [blame]
//===------------------------ exception.cpp -------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include <stdlib.h>
#include "exception"
#if __APPLE__
#include <cxxabi.h>
using namespace __cxxabiv1;
// On Darwin, there are two STL shared libraries and a lower level ABI
// shared libray. The globals holding the current terminate handler and
// current unexpected handler are in the ABI library.
#define __terminate_handler __cxxabiapple::__cxa_terminate_handler
#define __unexpected_handler __cxxabiapple::__cxa_unexpected_handler
#else // __APPLE__
static std::terminate_handler __terminate_handler;
static std::unexpected_handler __unexpected_handler;
#endif // __APPLE__
std::unexpected_handler
std::set_unexpected(std::unexpected_handler func) _NOEXCEPT
{
return __sync_lock_test_and_set(&__unexpected_handler, func);
}
std::unexpected_handler
std::get_unexpected() _NOEXCEPT
{
return __sync_fetch_and_add(&__unexpected_handler, (std::unexpected_handler)0);
}
_ATTRIBUTE(noreturn)
void
std::unexpected()
{
(*std::get_unexpected())();
// unexpected handler should not return
std::terminate();
}
std::terminate_handler
std::set_terminate(std::terminate_handler func) _NOEXCEPT
{
return __sync_lock_test_and_set(&__terminate_handler, func);
}
std::terminate_handler
std::get_terminate() _NOEXCEPT
{
return __sync_fetch_and_add(&__terminate_handler, (std::terminate_handler)0);
}
void
std::terminate() _NOEXCEPT
{
#ifndef _LIBCPP_NO_EXCEPTIONS
try
{
#endif // _LIBCPP_NO_EXCEPTIONS
(*std::get_terminate())();
// handler should not return
::abort ();
#ifndef _LIBCPP_NO_EXCEPTIONS
}
catch (...)
{
// handler should not throw exception
::abort ();
}
#endif // _LIBCPP_NO_EXCEPTIONS
}
bool std::uncaught_exception() _NOEXCEPT
{
#if __APPLE__
// on Darwin, there is a helper function so __cxa_get_globals is private
return __cxxabiapple::__cxa_uncaught_exception();
#else // __APPLE__
#warning uncaught_exception not yet implemented
::abort();
// Not provided by Ubuntu gcc-4.2.4's cxxabi.h.
// __cxa_eh_globals * globals = __cxa_get_globals();
// return (globals->uncaughtExceptions != 0);
#endif // __APPLE__
}
namespace std
{
exception::~exception() _NOEXCEPT
{
}
bad_exception::~bad_exception() _NOEXCEPT
{
}
const char* exception::what() const _NOEXCEPT
{
return "std::exception";
}
const char* bad_exception::what() const _NOEXCEPT
{
return "std::bad_exception";
}
exception_ptr::~exception_ptr() _NOEXCEPT
{
#if __APPLE__
__cxxabiapple::__cxa_decrement_exception_refcount(__ptr_);
#else
#warning exception_ptr not yet implemented
::abort();
#endif // __APPLE__
}
exception_ptr::exception_ptr(const exception_ptr& other) _NOEXCEPT
: __ptr_(other.__ptr_)
{
#if __APPLE__
__cxxabiapple::__cxa_increment_exception_refcount(__ptr_);
#else
#warning exception_ptr not yet implemented
::abort();
#endif // __APPLE__
}
exception_ptr& exception_ptr::operator=(const exception_ptr& other) _NOEXCEPT
{
#if __APPLE__
if (__ptr_ != other.__ptr_)
{
__cxxabiapple::__cxa_increment_exception_refcount(other.__ptr_);
__cxxabiapple::__cxa_decrement_exception_refcount(__ptr_);
__ptr_ = other.__ptr_;
}
return *this;
#else // __APPLE__
#warning exception_ptr not yet implemented
::abort();
#endif // __APPLE__
}
nested_exception::nested_exception() _NOEXCEPT
: __ptr_(current_exception())
{
}
nested_exception::~nested_exception() _NOEXCEPT
{
}
_ATTRIBUTE(noreturn)
void
nested_exception::rethrow_nested() const
{
if (__ptr_ == nullptr)
terminate();
rethrow_exception(__ptr_);
}
} // std
std::exception_ptr std::current_exception() _NOEXCEPT
{
#if __APPLE__
// be nicer if there was a constructor that took a ptr, then
// this whole function would be just:
// return exception_ptr(__cxa_current_primary_exception());
std::exception_ptr ptr;
ptr.__ptr_ = __cxxabiapple::__cxa_current_primary_exception();
return ptr;
#else // __APPLE__
#warning exception_ptr not yet implemented
::abort();
#endif // __APPLE__
}
void std::rethrow_exception(exception_ptr p)
{
#if __APPLE__
__cxxabiapple::__cxa_rethrow_primary_exception(p.__ptr_);
// if p.__ptr_ is NULL, above returns so we terminate
terminate();
#else // __APPLE__
#warning exception_ptr not yet implemented
::abort();
#endif // __APPLE__
}