Recommit "Split exception.cpp and new.cpp implementation into different files for different runtimes."

This recommits r294707 with additional fixes. The main difference is
libc++ now correctly builds without any ABI library.

exception.cpp is a bloody mess. It's full of confusing #ifdef branches for
each different ABI library we support, and it's getting unmaintainable.

This patch breaks down exception.cpp into multiple different header files,
roughly one per implementation. Additionally it moves the definitions of
exceptions in new.cpp into the correct implementation header.

This patch also removes an unmaintained libc++abi configuration.
This configuration may still be used by Apple internally but there
are no other possible users. If it turns out that Apple still uses
this configuration internally I will re-add it in a later commit.
See http://llvm.org/PR31904.

llvm-svn: 294730
This commit is contained in:
Eric Fiselier 2017-02-10 08:57:35 +00:00
parent 7bc6028d7d
commit d22c9dc422
17 changed files with 727 additions and 510 deletions

View File

@ -125,6 +125,9 @@ if (LIBCXX_CXX_ABI STREQUAL "default")
if (LIBCXX_TARGETING_MSVC)
# FIXME: Figure out how to configure the ABI library on Windows.
set(LIBCXX_CXX_ABI_LIBNAME "vcruntime")
elseif(APPLE)
set(LIBCXX_CXX_ABI_LIBNAME "libcxxabi")
set(LIBCXX_CXX_ABI_SYSTEM 1)
else()
set(LIBCXX_CXX_ABI_LIBNAME "default")
endif()

View File

@ -103,9 +103,11 @@ elseif ("${LIBCXX_CXX_ABI_LIBNAME}" STREQUAL "libcxxabi")
# Assume c++abi is installed in the system, rely on -lc++abi link flag.
set(CXXABI_LIBNAME "c++abi")
endif()
setup_abi_lib("-DLIBCXX_BUILDING_LIBCXXABI"
${CXXABI_LIBNAME} "cxxabi.h;__cxxabi_config.h" ""
)
set(HEADERS "cxxabi.h;__cxxabi_config.h")
if (LIBCXX_CXX_ABI_SYSTEM)
set(HEADERS "")
endif()
setup_abi_lib("-DLIBCXX_BUILDING_LIBCXXABI" ${CXXABI_LIBNAME} "${HEADERS}" "")
elseif ("${LIBCXX_CXX_ABI_LIBNAME}" STREQUAL "libcxxrt")
setup_abi_lib("-DLIBCXXRT"
"cxxrt" "cxxabi.h;unwind.h;unwind-arm.h;unwind-itanium.h" ""

View File

@ -82,6 +82,10 @@ template <class E> void rethrow_if_nested(const E& e);
#include <cstdlib>
#include <type_traits>
#if defined(_LIBCPP_ABI_MICROSOFT)
#include <vcruntime_exception.h>
#endif
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
#pragma GCC system_header
#endif
@ -89,6 +93,7 @@ template <class E> void rethrow_if_nested(const E& e);
namespace std // purposefully not using versioning namespace
{
#if !defined(_LIBCPP_ABI_MICROSOFT)
class _LIBCPP_EXCEPTION_ABI exception
{
public:
@ -105,6 +110,7 @@ public:
virtual ~bad_exception() _NOEXCEPT;
virtual const char* what() const _NOEXCEPT;
};
#endif // !_LIBCPP_ABI_MICROSOFT
typedef void (*unexpected_handler)();
_LIBCPP_FUNC_VIS unexpected_handler set_unexpected(unexpected_handler) _NOEXCEPT;

View File

@ -92,6 +92,10 @@ void operator delete[](void* ptr, void*) noexcept;
#include <cstdlib>
#endif
#if defined(_LIBCPP_ABI_MICROSOFT)
#include <new.h>
#endif
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
#pragma GCC system_header
#endif
@ -110,6 +114,10 @@ void operator delete[](void* ptr, void*) noexcept;
namespace std // purposefully not using versioning namespace
{
#if !defined(_LIBCPP_ABI_MICROSOFT)
struct _LIBCPP_TYPE_VIS nothrow_t {};
extern _LIBCPP_FUNC_VIS const nothrow_t nothrow;
class _LIBCPP_EXCEPTION_ABI bad_alloc
: public exception
{
@ -128,9 +136,15 @@ public:
virtual const char* what() const _NOEXCEPT;
};
typedef void (*new_handler)();
_LIBCPP_FUNC_VIS new_handler set_new_handler(new_handler) _NOEXCEPT;
_LIBCPP_FUNC_VIS new_handler get_new_handler() _NOEXCEPT;
#endif // !_LIBCPP_ABI_MICROSOFT
_LIBCPP_NORETURN _LIBCPP_FUNC_VIS void __throw_bad_alloc(); // not in C++ spec
#if defined(_LIBCPP_BUILDING_NEW) || (_LIBCPP_STD_VER > 11)
#if defined(_LIBCPP_BUILDING_LIBRARY) || (_LIBCPP_STD_VER > 11)
class _LIBCPP_EXCEPTION_ABI bad_array_length
: public bad_alloc
@ -153,12 +167,6 @@ enum align_val_t { __zero = 0, __max = (size_t)-1 };
#endif
#endif
struct _LIBCPP_TYPE_VIS nothrow_t {};
extern _LIBCPP_FUNC_VIS const nothrow_t nothrow;
typedef void (*new_handler)();
_LIBCPP_FUNC_VIS new_handler set_new_handler(new_handler) _NOEXCEPT;
_LIBCPP_FUNC_VIS new_handler get_new_handler() _NOEXCEPT;
} // std
#if defined(_LIBCPP_CXX03_LANG)
@ -167,6 +175,8 @@ _LIBCPP_FUNC_VIS new_handler get_new_handler() _NOEXCEPT;
#define _THROW_BAD_ALLOC
#endif
#if !defined(_LIBCPP_ABI_MICROSOFT)
_LIBCPP_OVERRIDABLE_FUNC_VIS void* operator new(std::size_t __sz) _THROW_BAD_ALLOC;
_LIBCPP_OVERRIDABLE_FUNC_VIS void* operator new(std::size_t __sz, const std::nothrow_t&) _NOEXCEPT _NOALIAS;
_LIBCPP_OVERRIDABLE_FUNC_VIS void operator delete(void* __p) _NOEXCEPT;
@ -206,6 +216,8 @@ inline _LIBCPP_INLINE_VISIBILITY void* operator new[](std::size_t, void* __p) _N
inline _LIBCPP_INLINE_VISIBILITY void operator delete (void*, void*) _NOEXCEPT {}
inline _LIBCPP_INLINE_VISIBILITY void operator delete[](void*, void*) _NOEXCEPT {}
#endif // !_LIBCPP_ABI_MICROSOFT
_LIBCPP_BEGIN_NAMESPACE_STD
inline _LIBCPP_INLINE_VISIBILITY void *__allocate(size_t __size) {

View File

@ -69,7 +69,9 @@ public:
#pragma GCC system_header
#endif
#if defined(_LIBCPP_NONUNIQUE_RTTI_BIT)
#if defined(_LIBCPP_ABI_MICROSOFT)
#include <vcruntime_typeinfo.h>
#elif defined(_LIBCPP_NONUNIQUE_RTTI_BIT)
#define _LIBCPP_HAS_NONUNIQUE_TYPEINFO
#else
#define _LIBCPP_HAS_UNIQUE_TYPEINFO
@ -78,6 +80,7 @@ public:
namespace std // purposefully not using versioning namespace
{
#if !defined(_LIBCPP_ABI_MICROSOFT)
class _LIBCPP_EXCEPTION_ABI type_info
{
type_info& operator=(const type_info&);
@ -187,6 +190,8 @@ public:
virtual const char* what() const _NOEXCEPT;
};
#endif // !_LIBCPP_ABI_MICROSOFT
} // std
_LIBCPP_BEGIN_NAMESPACE_STD

View File

@ -6,328 +6,31 @@
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include <stdlib.h>
#include <stdio.h>
#include "exception"
#include "new"
#include "typeinfo"
#if defined(_LIBCPP_ABI_MICROSOFT)
#include <eh.h>
#include <corecrt_terminate.h>
#elif defined(__APPLE__) && !defined(LIBCXXRT) && \
!defined(_LIBCPP_BUILDING_HAS_NO_ABI_LIBRARY)
#include <cxxabi.h>
using namespace __cxxabiv1;
#define HAVE_DEPENDENT_EH_ABI 1
#ifndef _LIBCPPABI_VERSION
using namespace __cxxabiapple;
// On Darwin, there are two STL shared libraries and a lower level ABI
// shared library. 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
#endif // _LIBCPPABI_VERSION
#elif defined(LIBCXXRT) || defined(LIBCXX_BUILDING_LIBCXXABI)
#if defined(LIBCXXRT) || defined(LIBCXX_BUILDING_LIBCXXABI) || \
(defined(__APPLE__) && !defined(_LIBCPP_BUILDING_HAS_NO_ABI_LIBRARY))
#include <cxxabi.h>
using namespace __cxxabiv1;
#if defined(LIBCXXRT) || defined(_LIBCPPABI_VERSION)
#define HAVE_DEPENDENT_EH_ABI 1
#endif
#elif !defined(__GLIBCXX__) // defined(LIBCXX_BUILDING_LIBCXXABI)
_LIBCPP_SAFE_STATIC static std::terminate_handler __terminate_handler;
_LIBCPP_SAFE_STATIC static std::unexpected_handler __unexpected_handler;
#endif // defined(LIBCXX_BUILDING_LIBCXXABI)
namespace std
{
#if !defined(LIBCXXRT) && !defined(_LIBCPPABI_VERSION) && !defined(__GLIBCXX__)
// libcxxrt provides implementations of these functions itself.
unexpected_handler
set_unexpected(unexpected_handler func) _NOEXCEPT
{
#if defined(_LIBCPP_ABI_MICROSOFT)
return ::set_unexpected(func);
#else
return __sync_lock_test_and_set(&__unexpected_handler, func);
#endif
}
unexpected_handler
get_unexpected() _NOEXCEPT
{
#if defined(_LIBCPP_ABI_MICROSOFT)
return ::_get_unexpected();
#else
return __sync_fetch_and_add(&__unexpected_handler, (unexpected_handler)0);
#endif
}
_LIBCPP_NORETURN
void
unexpected()
{
(*get_unexpected())();
// unexpected handler should not return
terminate();
}
terminate_handler
set_terminate(terminate_handler func) _NOEXCEPT
{
#if defined(_LIBCPP_ABI_MICROSOFT)
return ::set_terminate(func);
#else
return __sync_lock_test_and_set(&__terminate_handler, func);
#endif
}
terminate_handler
get_terminate() _NOEXCEPT
{
#if defined(_LIBCPP_ABI_MICROSOFT)
return ::_get_terminate();
#else
return __sync_fetch_and_add(&__terminate_handler, (terminate_handler)0);
#endif
}
#ifndef __EMSCRIPTEN__ // We provide this in JS
_LIBCPP_NORETURN
void
terminate() _NOEXCEPT
{
#ifndef _LIBCPP_NO_EXCEPTIONS
try
{
#endif // _LIBCPP_NO_EXCEPTIONS
(*get_terminate())();
// handler should not return
fprintf(stderr, "terminate_handler unexpectedly returned\n");
::abort();
#ifndef _LIBCPP_NO_EXCEPTIONS
}
catch (...)
{
// handler should not throw exception
fprintf(stderr, "terminate_handler unexpectedly threw an exception\n");
::abort();
}
#endif // _LIBCPP_NO_EXCEPTIONS
}
#endif // !__EMSCRIPTEN__
#endif // !defined(LIBCXXRT) && !defined(_LIBCPPABI_VERSION)
#if !defined(LIBCXXRT) && !defined(__GLIBCXX__) && !defined(__EMSCRIPTEN__)
bool uncaught_exception() _NOEXCEPT { return uncaught_exceptions() > 0; }
int uncaught_exceptions() _NOEXCEPT
{
#if !defined(_LIBCPP_BUILDING_HAS_NO_ABI_LIBRARY) && \
(defined(__APPLE__) || defined(_LIBCPPABI_VERSION))
// on Darwin, there is a helper function so __cxa_get_globals is private
# if _LIBCPPABI_VERSION > 1101
return __cxa_uncaught_exceptions();
# else
return __cxa_uncaught_exception() ? 1 : 0;
# endif
#elif defined(_LIBCPP_ABI_MICROSOFT)
return __uncaught_exceptions();
#else
# if defined(_LIBCPP_MSVC)
_LIBCPP_WARNING("uncaught_exceptions not yet implemented")
# else
# warning uncaught_exception not yet implemented
# endif
fprintf(stderr, "uncaught_exceptions not yet implemented\n");
::abort();
#endif // __APPLE__
}
#ifndef _LIBCPPABI_VERSION
exception::~exception() _NOEXCEPT
{
}
const char* exception::what() const _NOEXCEPT
{
return "std::exception";
}
#endif // _LIBCPPABI_VERSION
#endif //LIBCXXRT
#if !defined(_LIBCPPABI_VERSION) && !defined(__GLIBCXX__)
bad_exception::~bad_exception() _NOEXCEPT
{
}
const char* bad_exception::what() const _NOEXCEPT
{
return "std::bad_exception";
}
#endif
#if defined(__GLIBCXX__)
// libsupc++ does not implement the dependent EH ABI and the functionality
// it uses to implement std::exception_ptr (which it declares as an alias of
// std::__exception_ptr::exception_ptr) is not directly exported to clients. So
// we have little choice but to hijack std::__exception_ptr::exception_ptr's
// (which fortunately has the same layout as our std::exception_ptr) copy
// constructor, assignment operator and destructor (which are part of its
// stable ABI), and its rethrow_exception(std::__exception_ptr::exception_ptr)
// function.
namespace __exception_ptr
{
struct exception_ptr
{
void* __ptr_;
exception_ptr(const exception_ptr&) _NOEXCEPT;
exception_ptr& operator=(const exception_ptr&) _NOEXCEPT;
~exception_ptr() _NOEXCEPT;
};
}
_LIBCPP_NORETURN void rethrow_exception(__exception_ptr::exception_ptr);
#endif
exception_ptr::~exception_ptr() _NOEXCEPT
{
#if HAVE_DEPENDENT_EH_ABI
__cxa_decrement_exception_refcount(__ptr_);
#include "support/runtime/exception_msvc.ipp"
#include "support/runtime/exception_pointer_unimplemented.ipp"
#elif defined(_LIBCPPABI_VERSION)
#include "support/runtime/exception_libcxxabi.ipp"
#include "support/runtime/exception_pointer_cxxabi.ipp"
#elif defined(LIBCXXRT)
#include "support/runtime/exception_libcxxrt.ipp"
#include "support/runtime/exception_pointer_cxxabi.ipp"
#elif defined(__GLIBCXX__)
reinterpret_cast<__exception_ptr::exception_ptr*>(this)->~exception_ptr();
#include "support/runtime/exception_glibcxx.ipp"
#include "support/runtime/exception_pointer_glibcxx.ipp"
#else
# if defined(_LIBCPP_MSVC)
_LIBCPP_WARNING("exception_ptr not yet implemented")
# else
# warning exception_ptr not yet implemented
#include "support/runtime/exception_fallback.ipp"
#include "support/runtime/exception_pointer_unimplemented.ipp"
#endif
fprintf(stderr, "exception_ptr not yet implemented\n");
::abort();
#endif
}
exception_ptr::exception_ptr(const exception_ptr& other) _NOEXCEPT
: __ptr_(other.__ptr_)
{
#if HAVE_DEPENDENT_EH_ABI
__cxa_increment_exception_refcount(__ptr_);
#elif defined(__GLIBCXX__)
new (reinterpret_cast<void*>(this)) __exception_ptr::exception_ptr(
reinterpret_cast<const __exception_ptr::exception_ptr&>(other));
#else
# if defined(_LIBCPP_MSVC)
_LIBCPP_WARNING("exception_ptr not yet implemented")
# else
# warning exception_ptr not yet implemented
# endif
fprintf(stderr, "exception_ptr not yet implemented\n");
::abort();
#endif
}
exception_ptr& exception_ptr::operator=(const exception_ptr& other) _NOEXCEPT
{
#if HAVE_DEPENDENT_EH_ABI
if (__ptr_ != other.__ptr_)
{
__cxa_increment_exception_refcount(other.__ptr_);
__cxa_decrement_exception_refcount(__ptr_);
__ptr_ = other.__ptr_;
}
return *this;
#elif defined(__GLIBCXX__)
*reinterpret_cast<__exception_ptr::exception_ptr*>(this) =
reinterpret_cast<const __exception_ptr::exception_ptr&>(other);
return *this;
#else
# if defined(_LIBCPP_MSVC)
_LIBCPP_WARNING("exception_ptr not yet implemented")
# else
# warning exception_ptr not yet implemented
# endif
fprintf(stderr, "exception_ptr not yet implemented\n");
::abort();
#endif
}
nested_exception::nested_exception() _NOEXCEPT
: __ptr_(current_exception())
{
}
#if !defined(__GLIBCXX__)
nested_exception::~nested_exception() _NOEXCEPT
{
}
#endif
_LIBCPP_NORETURN
void
nested_exception::rethrow_nested() const
{
if (__ptr_ == nullptr)
terminate();
rethrow_exception(__ptr_);
}
#if !defined(__GLIBCXX__)
exception_ptr current_exception() _NOEXCEPT
{
#if HAVE_DEPENDENT_EH_ABI
// 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());
exception_ptr ptr;
ptr.__ptr_ = __cxa_current_primary_exception();
return ptr;
#else
# if defined(_LIBCPP_MSVC)
_LIBCPP_WARNING( "exception_ptr not yet implemented" )
# else
# warning exception_ptr not yet implemented
# endif
fprintf(stderr, "exception_ptr not yet implemented\n");
::abort();
#endif
}
#endif // !__GLIBCXX__
_LIBCPP_NORETURN
void rethrow_exception(exception_ptr p)
{
#if HAVE_DEPENDENT_EH_ABI
__cxa_rethrow_primary_exception(p.__ptr_);
// if p.__ptr_ is NULL, above returns so we terminate
terminate();
#elif defined(__GLIBCXX__)
rethrow_exception(reinterpret_cast<__exception_ptr::exception_ptr&>(p));
#else
# if defined(_LIBCPP_MSVC)
_LIBCPP_WARNING("exception_ptr not yet implemented")
# else
# warning exception_ptr not yet implemented
# endif
fprintf(stderr, "exception_ptr not yet implemented\n");
::abort();
#endif
}
} // std

View File

@ -13,27 +13,43 @@
#include "new"
#if defined(__APPLE__) && !defined(LIBCXXRT) && \
!defined(_LIBCPP_BUILDING_HAS_NO_ABI_LIBRARY)
#if defined(_LIBCPP_ABI_MICROSOFT)
// nothing todo
#elif defined(LIBCXX_BUILDING_LIBCXXABI)
#include <cxxabi.h>
#elif defined(LIBCXXRT)
#include <cxxabi.h>
#include "support/runtime/new_handler_fallback.ipp"
#elif defined(__GLIBCXX__)
// nothing todo
#else
#include "support/runtime/new_handler_fallback.ipp"
#endif
#ifndef _LIBCPPABI_VERSION
// On Darwin, there are two STL shared libraries and a lower level ABI
// shared library. The global holding the current new handler is
// in the ABI library and named __cxa_new_handler.
#define __new_handler __cxxabiapple::__cxa_new_handler
#endif
#else // __APPLE__
#if defined(LIBCXXRT) || defined(LIBCXX_BUILDING_LIBCXXABI)
#include <cxxabi.h>
#endif // defined(LIBCXX_BUILDING_LIBCXXABI)
#if defined(_LIBCPP_BUILDING_HAS_NO_ABI_LIBRARY) || \
(!defined(_LIBCPPABI_VERSION) && !defined(__GLIBCXX__))
static std::new_handler __new_handler;
#endif // _LIBCPPABI_VERSION
#endif
namespace std
{
#ifndef __GLIBCXX__
const nothrow_t nothrow = {};
#endif
#ifndef LIBSTDCXX
void
__throw_bad_alloc()
{
#ifndef _LIBCPP_NO_EXCEPTIONS
throw bad_alloc();
#else
_VSTD::abort();
#endif
}
#endif // !LIBSTDCXX
} // std
#if !defined(__GLIBCXX__) && !defined(_LIBCPP_ABI_MICROSOFT)
// Implement all new and delete operators as weak definitions
// in this shared library, so that they can be overridden by programs
@ -277,107 +293,5 @@ operator delete[] (void* ptr, size_t, std::align_val_t alignment) _NOEXCEPT
::operator delete[](ptr, alignment);
}
#endif // !defined(_LIBCPP_HAS_NO_ALIGNED_ALLOCATION)
#endif // !__GLIBCXX__
namespace std
{
#ifndef __GLIBCXX__
const nothrow_t nothrow = {};
#endif
#ifndef _LIBCPPABI_VERSION
#ifndef __GLIBCXX__
new_handler
set_new_handler(new_handler handler) _NOEXCEPT
{
return __sync_lock_test_and_set(&__new_handler, handler);
}
new_handler
get_new_handler() _NOEXCEPT
{
return __sync_fetch_and_add(&__new_handler, nullptr);
}
#endif // !__GLIBCXX__
#ifndef LIBCXXRT
bad_alloc::bad_alloc() _NOEXCEPT
{
}
#ifndef __GLIBCXX__
bad_alloc::~bad_alloc() _NOEXCEPT
{
}
const char*
bad_alloc::what() const _NOEXCEPT
{
return "std::bad_alloc";
}
#endif // !__GLIBCXX__
bad_array_new_length::bad_array_new_length() _NOEXCEPT
{
}
#ifndef __GLIBCXX__
bad_array_new_length::~bad_array_new_length() _NOEXCEPT
{
}
const char*
bad_array_new_length::what() const _NOEXCEPT
{
return "bad_array_new_length";
}
#endif // !__GLIBCXX__
#endif //LIBCXXRT
bad_array_length::bad_array_length() _NOEXCEPT
{
}
#ifndef __GLIBCXX__
bad_array_length::~bad_array_length() _NOEXCEPT
{
}
const char*
bad_array_length::what() const _NOEXCEPT
{
return "bad_array_length";
}
#endif // !__GLIBCXX__
#endif // _LIBCPPABI_VERSION
#ifndef LIBSTDCXX
void
__throw_bad_alloc()
{
#ifndef _LIBCPP_NO_EXCEPTIONS
throw bad_alloc();
#else
_VSTD::abort();
#endif
}
#endif // !LIBSTDCXX
} // std
#endif // !_LIBCPP_HAS_NO_ALIGNED_ALLOCATION
#endif // !__GLIBCXX__ && !_LIBCPP_ABI_MICROSOFT

View File

@ -0,0 +1,182 @@
// -*- C++ -*-
//===----------------------------------------------------------------------===//
//
// 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 <cstdio>
namespace std {
_LIBCPP_SAFE_STATIC static std::terminate_handler __terminate_handler;
_LIBCPP_SAFE_STATIC static std::unexpected_handler __unexpected_handler;
// libcxxrt provides implementations of these functions itself.
unexpected_handler
set_unexpected(unexpected_handler func) _NOEXCEPT
{
return __sync_lock_test_and_set(&__unexpected_handler, func);
}
unexpected_handler
get_unexpected() _NOEXCEPT
{
return __sync_fetch_and_add(&__unexpected_handler, (unexpected_handler)0);
}
_LIBCPP_NORETURN
void unexpected()
{
(*get_unexpected())();
// unexpected handler should not return
terminate();
}
terminate_handler
set_terminate(terminate_handler func) _NOEXCEPT
{
return __sync_lock_test_and_set(&__terminate_handler, func);
}
terminate_handler
get_terminate() _NOEXCEPT
{
return __sync_fetch_and_add(&__terminate_handler, (terminate_handler)0);
}
#ifndef __EMSCRIPTEN__ // We provide this in JS
_LIBCPP_NORETURN
void
terminate() _NOEXCEPT
{
#ifndef _LIBCPP_NO_EXCEPTIONS
try
{
#endif // _LIBCPP_NO_EXCEPTIONS
(*get_terminate())();
// handler should not return
fprintf(stderr, "terminate_handler unexpectedly returned\n");
::abort();
#ifndef _LIBCPP_NO_EXCEPTIONS
}
catch (...)
{
// handler should not throw exception
fprintf(stderr, "terminate_handler unexpectedly threw an exception\n");
::abort();
}
#endif // _LIBCPP_NO_EXCEPTIONS
}
#endif // !__EMSCRIPTEN__
#if !defined(__EMSCRIPTEN__)
bool uncaught_exception() _NOEXCEPT { return uncaught_exceptions() > 0; }
int uncaught_exceptions() _NOEXCEPT
{
#warning uncaught_exception not yet implemented
fprintf(stderr, "uncaught_exceptions not yet implemented\n");
::abort();
}
#endif // !__EMSCRIPTEN__
exception::~exception() _NOEXCEPT
{
}
const char* exception::what() const _NOEXCEPT
{
return "std::exception";
}
bad_exception::~bad_exception() _NOEXCEPT
{
}
const char* bad_exception::what() const _NOEXCEPT
{
return "std::bad_exception";
}
bad_alloc::bad_alloc() _NOEXCEPT
{
}
bad_alloc::~bad_alloc() _NOEXCEPT
{
}
const char*
bad_alloc::what() const _NOEXCEPT
{
return "std::bad_alloc";
}
bad_array_new_length::bad_array_new_length() _NOEXCEPT
{
}
bad_array_new_length::~bad_array_new_length() _NOEXCEPT
{
}
const char*
bad_array_new_length::what() const _NOEXCEPT
{
return "bad_array_new_length";
}
bad_array_length::bad_array_length() _NOEXCEPT
{
}
bad_array_length::~bad_array_length() _NOEXCEPT
{
}
const char*
bad_array_length::what() const _NOEXCEPT
{
return "bad_array_length";
}
bad_cast::bad_cast() _NOEXCEPT
{
}
bad_typeid::bad_typeid() _NOEXCEPT
{
}
bad_cast::~bad_cast() _NOEXCEPT
{
}
const char*
bad_cast::what() const _NOEXCEPT
{
return "std::bad_cast";
}
bad_typeid::~bad_typeid() _NOEXCEPT
{
}
const char*
bad_typeid::what() const _NOEXCEPT
{
return "std::bad_typeid";
}
} // namespace std

View File

@ -0,0 +1,38 @@
// -*- C++ -*-
//===----------------------------------------------------------------------===//
//
// 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.
//
//===----------------------------------------------------------------------===//
#ifndef __GLIBCXX__
#error header can only be used when targeting libstdc++ or libsupc++
#endif
namespace std {
bad_alloc::bad_alloc() _NOEXCEPT
{
}
bad_array_new_length::bad_array_new_length() _NOEXCEPT
{
}
bad_array_length::bad_array_length() _NOEXCEPT
{
}
bad_cast::bad_cast() _NOEXCEPT
{
}
bad_typeid::bad_typeid() _NOEXCEPT
{
}
} // namespace

View File

@ -0,0 +1,28 @@
// -*- C++ -*-
//===----------------------------------------------------------------------===//
//
// 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.
//
//===----------------------------------------------------------------------===//
#ifndef _LIBCPPABI_VERSION
#error this header can only be used with libc++abi
#endif
namespace std {
bool uncaught_exception() _NOEXCEPT { return uncaught_exceptions() > 0; }
int uncaught_exceptions() _NOEXCEPT
{
# if _LIBCPPABI_VERSION > 1101
return __cxa_uncaught_exceptions();
# else
return __cxa_uncaught_exception() ? 1 : 0;
# endif
}
} // namespace std

View File

@ -0,0 +1,41 @@
// -*- C++ -*-
//===----------------------------------------------------------------------===//
//
// 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.
//
//===----------------------------------------------------------------------===//
#ifndef LIBCXXRT
#error this header may only be used when targeting libcxxrt
#endif
namespace std {
bad_exception::~bad_exception() _NOEXCEPT
{
}
const char* bad_exception::what() const _NOEXCEPT
{
return "std::bad_exception";
}
bad_array_length::bad_array_length() _NOEXCEPT
{
}
bad_array_length::~bad_array_length() _NOEXCEPT
{
}
const char*
bad_array_length::what() const _NOEXCEPT
{
return "bad_array_length";
}
} // namespace std

View File

@ -0,0 +1,89 @@
// -*- C++ -*-
//===----------------------------------------------------------------------===//
//
// 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.
//
//===----------------------------------------------------------------------===//
#ifndef _LIBCPP_ABI_MICROSOFT
#error this header can only be used when targeting the MSVC ABI
#endif
#include <stdio.h>
#include <stdlib.h>
#include <eh.h>
#include <corecrt_terminate.h>
namespace std {
// libcxxrt provides implementations of these functions itself.
unexpected_handler
set_unexpected(unexpected_handler func) _NOEXCEPT {
return ::set_unexpected(func);
}
unexpected_handler get_unexpected() _NOEXCEPT {
return ::_get_unexpected();
}
_LIBCPP_NORETURN
void unexpected() {
(*get_unexpected())();
// unexpected handler should not return
terminate();
}
terminate_handler set_terminate(terminate_handler func) _NOEXCEPT {
return ::set_terminate(func);
}
terminate_handler get_terminate() _NOEXCEPT {
return ::_get_terminate();
}
_LIBCPP_NORETURN
void terminate() _NOEXCEPT
{
#ifndef _LIBCPP_NO_EXCEPTIONS
try
{
#endif // _LIBCPP_NO_EXCEPTIONS
(*get_terminate())();
// handler should not return
fprintf(stderr, "terminate_handler unexpectedly returned\n");
::abort();
#ifndef _LIBCPP_NO_EXCEPTIONS
}
catch (...)
{
// handler should not throw exception
fprintf(stderr, "terminate_handler unexpectedly threw an exception\n");
::abort();
}
#endif // _LIBCPP_NO_EXCEPTIONS
}
bool uncaught_exception() _NOEXCEPT { return uncaught_exceptions() > 0; }
int uncaught_exceptions() _NOEXCEPT {
return __uncaught_exceptions();
}
bad_array_length::bad_array_length() _NOEXCEPT
{
}
bad_array_length::~bad_array_length() _NOEXCEPT
{
}
const char*
bad_array_length::what() const _NOEXCEPT
{
return "bad_array_length";
}
} // namespace std

View File

@ -0,0 +1,74 @@
// -*- C++ -*-
//===----------------------------------------------------------------------===//
//
// 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.
//
//===----------------------------------------------------------------------===//
#ifndef HAVE_DEPENDENT_EH_ABI
#error this header may only be used with libc++abi or libcxxrt
#endif
namespace std {
exception_ptr::~exception_ptr() _NOEXCEPT {
__cxa_decrement_exception_refcount(__ptr_);
}
exception_ptr::exception_ptr(const exception_ptr& other) _NOEXCEPT
: __ptr_(other.__ptr_)
{
__cxa_increment_exception_refcount(__ptr_);
}
exception_ptr& exception_ptr::operator=(const exception_ptr& other) _NOEXCEPT
{
if (__ptr_ != other.__ptr_)
{
__cxa_increment_exception_refcount(other.__ptr_);
__cxa_decrement_exception_refcount(__ptr_);
__ptr_ = other.__ptr_;
}
return *this;
}
nested_exception::nested_exception() _NOEXCEPT
: __ptr_(current_exception())
{
}
nested_exception::~nested_exception() _NOEXCEPT
{
}
_LIBCPP_NORETURN
void
nested_exception::rethrow_nested() const
{
if (__ptr_ == nullptr)
terminate();
rethrow_exception(__ptr_);
}
exception_ptr current_exception() _NOEXCEPT
{
// 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());
exception_ptr ptr;
ptr.__ptr_ = __cxa_current_primary_exception();
return ptr;
}
_LIBCPP_NORETURN
void rethrow_exception(exception_ptr p)
{
__cxa_rethrow_primary_exception(p.__ptr_);
// if p.__ptr_ is NULL, above returns so we terminate
terminate();
}
} // namespace std

View File

@ -0,0 +1,74 @@
// -*- C++ -*-
//===----------------------------------------------------------------------===//
//
// 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.
//
//===----------------------------------------------------------------------===//
// libsupc++ does not implement the dependent EH ABI and the functionality
// it uses to implement std::exception_ptr (which it declares as an alias of
// std::__exception_ptr::exception_ptr) is not directly exported to clients. So
// we have little choice but to hijack std::__exception_ptr::exception_ptr's
// (which fortunately has the same layout as our std::exception_ptr) copy
// constructor, assignment operator and destructor (which are part of its
// stable ABI), and its rethrow_exception(std::__exception_ptr::exception_ptr)
// function.
namespace __exception_ptr
{
struct exception_ptr
{
void* __ptr_;
exception_ptr(const exception_ptr&) _NOEXCEPT;
exception_ptr& operator=(const exception_ptr&) _NOEXCEPT;
~exception_ptr() _NOEXCEPT;
};
}
_LIBCPP_NORETURN void rethrow_exception(__exception_ptr::exception_ptr);
exception_ptr::~exception_ptr() _NOEXCEPT
{
reinterpret_cast<__exception_ptr::exception_ptr*>(this)->~exception_ptr();
}
exception_ptr::exception_ptr(const exception_ptr& other) _NOEXCEPT
: __ptr_(other.__ptr_)
{
new (reinterpret_cast<void*>(this)) __exception_ptr::exception_ptr(
reinterpret_cast<const __exception_ptr::exception_ptr&>(other));
}
exception_ptr& exception_ptr::operator=(const exception_ptr& other) _NOEXCEPT
{
*reinterpret_cast<__exception_ptr::exception_ptr*>(this) =
reinterpret_cast<const __exception_ptr::exception_ptr&>(other);
return *this;
}
nested_exception::nested_exception() _NOEXCEPT
: __ptr_(current_exception())
{
}
_LIBCPP_NORETURN
void
nested_exception::rethrow_nested() const
{
if (__ptr_ == nullptr)
terminate();
rethrow_exception(__ptr_);
}
_LIBCPP_NORETURN
void rethrow_exception(exception_ptr p)
{
rethrow_exception(reinterpret_cast<__exception_ptr::exception_ptr&>(p));
}

View File

@ -0,0 +1,80 @@
// -*- C++ -*-
//===----------------------------------------------------------------------===//
//
// 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 <stdio.h>
#include <stdlib.h>
namespace std {
exception_ptr::~exception_ptr() _NOEXCEPT
{
# warning exception_ptr not yet implemented
fprintf(stderr, "exception_ptr not yet implemented\n");
::abort();
}
exception_ptr::exception_ptr(const exception_ptr& other) _NOEXCEPT
: __ptr_(other.__ptr_)
{
# warning exception_ptr not yet implemented
fprintf(stderr, "exception_ptr not yet implemented\n");
::abort();
}
exception_ptr& exception_ptr::operator=(const exception_ptr& other) _NOEXCEPT
{
# warning exception_ptr not yet implemented
fprintf(stderr, "exception_ptr not yet implemented\n");
::abort();
}
nested_exception::nested_exception() _NOEXCEPT
: __ptr_(current_exception())
{
}
#if !defined(__GLIBCXX__)
nested_exception::~nested_exception() _NOEXCEPT
{
}
#endif
_LIBCPP_NORETURN
void
nested_exception::rethrow_nested() const
{
# warning exception_ptr not yet implemented
fprintf(stderr, "exception_ptr not yet implemented\n");
::abort();
#if 0
if (__ptr_ == nullptr)
terminate();
rethrow_exception(__ptr_);
#endif // FIXME
}
exception_ptr current_exception() _NOEXCEPT
{
# warning exception_ptr not yet implemented
fprintf(stderr, "exception_ptr not yet implemented\n");
::abort();
}
_LIBCPP_NORETURN
void rethrow_exception(exception_ptr p)
{
# warning exception_ptr not yet implemented
fprintf(stderr, "exception_ptr not yet implemented\n");
::abort();
}
} // namespace std

View File

@ -0,0 +1,27 @@
// -*- C++ -*-
//===----------------------------------------------------------------------===//
//
// 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.
//
//===----------------------------------------------------------------------===//
namespace std {
_LIBCPP_SAFE_STATIC static std::new_handler __new_handler;
new_handler
set_new_handler(new_handler handler) _NOEXCEPT
{
return __sync_lock_test_and_set(&__new_handler, handler);
}
new_handler
get_new_handler() _NOEXCEPT
{
return __sync_fetch_and_add(&__new_handler, nullptr);
}
} // namespace std

View File

@ -6,74 +6,13 @@
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include <stdlib.h>
#if !defined(_LIBCPP_BUILDING_HAS_NO_ABI_LIBRARY) && \
(defined(__APPLE__) || defined(LIBCXXRT) || defined(LIBCXX_BUILDING_LIBCXXABI))
#include <cxxabi.h>
#endif
#include "typeinfo"
#if defined(_LIBCPP_BUILDING_HAS_NO_ABI_LIBRARY) || \
defined(_LIBCPP_ABI_MICROSOFT) // FIXME: This is a temporary workaround
#if (!defined(_LIBCPP_ABI_MICROSOFT) && !defined(LIBCXX_BUILDING_LIBCXXABI) && \
!defined(LIBCXXRT) && !defined(__GLIBCXX__)) || \
defined(_LIBCPP_BUILDING_HAS_NO_ABI_LIBRARY) // FIXME: remove this configuration.
std::type_info::~type_info()
{
}
#endif
#if !defined(LIBCXXRT) && !defined(_LIBCPPABI_VERSION)
std::bad_cast::bad_cast() _NOEXCEPT
{
}
std::bad_typeid::bad_typeid() _NOEXCEPT
{
}
#ifndef __GLIBCXX__
std::bad_cast::~bad_cast() _NOEXCEPT
{
}
const char*
std::bad_cast::what() const _NOEXCEPT
{
return "std::bad_cast";
}
std::bad_typeid::~bad_typeid() _NOEXCEPT
{
}
const char*
std::bad_typeid::what() const _NOEXCEPT
{
return "std::bad_typeid";
}
#if defined(__APPLE__) && !defined(_LIBCPP_BUILDING_HAS_NO_ABI_LIBRARY)
// On Darwin, the cxa_bad_* functions cannot be in the lower level library
// because bad_cast and bad_typeid are defined in his higher level library
void __cxxabiv1::__cxa_bad_typeid()
{
#ifndef _LIBCPP_NO_EXCEPTIONS
throw std::bad_typeid();
#else
_VSTD::abort();
#endif
}
void __cxxabiv1::__cxa_bad_cast()
{
#ifndef _LIBCPP_NO_EXCEPTIONS
throw std::bad_cast();
#else
_VSTD::abort();
#endif
}
#endif
#endif // !__GLIBCXX__
#endif // !LIBCXXRT && !_LIBCPPABI_VERSION