Index: CMakeLists.txt =================================================================== --- CMakeLists.txt +++ CMakeLists.txt @@ -116,11 +116,19 @@ ${LLVM_MAIN_SRC_DIR}/runtimes/libcxxabi/include NO_DEFAULT_PATH ) + find_path( + LIBCXX_LIBCXXABI_INCLUDES_EXTERNAL + cxxabi.h + PATHS /usr/include + ) if ((NOT LIBCXX_STANDALONE_BUILD OR HAVE_LIBCXXABI) AND IS_DIRECTORY "${LIBCXX_LIBCXXABI_INCLUDES_INTERNAL}") set(LIBCXX_CXX_ABI_LIBNAME "libcxxabi") set(LIBCXX_CXX_ABI_INCLUDE_PATHS "${LIBCXX_LIBCXXABI_INCLUDES_INTERNAL}") set(LIBCXX_CXX_ABI_INTREE 1) + elseif(APPLE AND IS_DIRECTORY "${LIBCXX_LIBCXXABI_INCLUDES_INTERNAL}") + set(LIBCXX_CXX_ABI_LIBNAME "libcxxabi") + set(LIBCXX_CXX_ABI_INCLUDE_PATHS "${LIBCXX_LIBCXXABI_INCLUDES_INTERNAL}") else() if (LIBCXX_TARGETING_MSVC) # FIXME: Figure out how to configure the ABI library on Windows. Index: include/exception =================================================================== --- include/exception +++ include/exception @@ -82,6 +82,10 @@ #include #include +#if defined(_LIBCPP_ABI_MICROSOFT) +#include +#endif + #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #pragma GCC system_header #endif @@ -89,6 +93,7 @@ namespace std // purposefully not using versioning namespace { +#if !defined(_LIBCPP_ABI_MICROSOFT) class _LIBCPP_EXCEPTION_ABI exception { public: @@ -105,6 +110,7 @@ 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; Index: include/new =================================================================== --- include/new +++ include/new @@ -92,6 +92,10 @@ #include #endif +#if defined(_LIBCPP_ABI_MICROSOFT) +#include +#endif + #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #pragma GCC system_header #endif @@ -110,6 +114,10 @@ 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,6 +136,12 @@ 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) @@ -153,12 +167,6 @@ #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 @@ #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 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) { Index: include/typeinfo =================================================================== --- include/typeinfo +++ include/typeinfo @@ -69,7 +69,9 @@ #pragma GCC system_header #endif -#if defined(_LIBCPP_NONUNIQUE_RTTI_BIT) +#if defined(_LIBCPP_ABI_MICROSOFT) +#include +#elif defined(_LIBCPP_NONUNIQUE_RTTI_BIT) #define _LIBCPP_HAS_NONUNIQUE_TYPEINFO #else #define _LIBCPP_HAS_UNIQUE_TYPEINFO @@ -78,6 +80,7 @@ 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 @@ virtual const char* what() const _NOEXCEPT; }; +#endif // !_LIBCPP_ABI_MICROSOFT + } // std _LIBCPP_BEGIN_NAMESPACE_STD Index: src/exception.cpp =================================================================== --- src/exception.cpp +++ src/exception.cpp @@ -6,328 +6,30 @@ // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -#include -#include #include "exception" #include "new" -#if defined(_LIBCPP_ABI_MICROSOFT) -#include -#include -#elif defined(__APPLE__) && !defined(LIBCXXRT) && \ - !defined(_LIBCPP_BUILDING_HAS_NO_ABI_LIBRARY) +#if defined(LIBCXXRT) || defined(LIBCXX_BUILDING_LIBCXXABI) || \ + (defined(__APPLE__) && !defined(_LIBCPP_BUILDING_HAS_NO_ABI_LIBRARY)) #include - 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) - #include - 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_); -#elif defined(__GLIBCXX__) - reinterpret_cast<__exception_ptr::exception_ptr*>(this)->~exception_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 -} - -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(this)) __exception_ptr::exception_ptr( - reinterpret_cast(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(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(); +#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__) - rethrow_exception(reinterpret_cast<__exception_ptr::exception_ptr&>(p)); +#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 -# endif - fprintf(stderr, "exception_ptr not yet implemented\n"); - ::abort(); +#include "support/runtime/exception_fallback.ipp" +#include "support/runtime/exception_pointer_unimplemented.ipp" #endif -} -} // std Index: src/new.cpp =================================================================== --- src/new.cpp +++ src/new.cpp @@ -13,27 +13,45 @@ #include "new" -#if defined(__APPLE__) && !defined(LIBCXXRT) && \ - !defined(_LIBCPP_BUILDING_HAS_NO_ABI_LIBRARY) - #include - - #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 - #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 +#if defined(_LIBCPP_ABI_MICROSOFT) +// nothing todo +#elif defined(LIBCXX_BUILDING_LIBCXXABI) +#include +#elif defined(LIBCXXRT) +#include +#include "new_handler_fallback.ipp" +#elif defined(__GLIBCXX__) +// nothing todo +#elif defined(_LIBCPP_BUILDING_NO_ABI_LIBRARY) +// nothing todo +#else +#error UNSUPPORTED configuration #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 +295,5 @@ ::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 Index: src/support/runtime/exception_fallback.ipp =================================================================== --- /dev/null +++ src/support/runtime/exception_fallback.ipp @@ -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. +// +//===----------------------------------------------------------------------===// + +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 +{ +} + +#ifndef __GLIBCXX__ + +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 Index: src/support/runtime/exception_glibcxx.ipp =================================================================== --- /dev/null +++ src/support/runtime/exception_glibcxx.ipp @@ -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 Index: src/support/runtime/exception_libcxxabi.ipp =================================================================== --- /dev/null +++ src/support/runtime/exception_libcxxabi.ipp @@ -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 Index: src/support/runtime/exception_libcxxrt.ipp =================================================================== --- /dev/null +++ src/support/runtime/exception_libcxxrt.ipp @@ -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 Index: src/support/runtime/exception_msvc.ipp =================================================================== --- /dev/null +++ src/support/runtime/exception_msvc.ipp @@ -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 +#include +#include +#include + +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 Index: src/support/runtime/exception_pointer_cxxabi.ipp =================================================================== --- /dev/null +++ src/support/runtime/exception_pointer_cxxabi.ipp @@ -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 Index: src/support/runtime/exception_pointer_glibcxx.ipp =================================================================== --- /dev/null +++ src/support/runtime/exception_pointer_glibcxx.ipp @@ -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(this)) __exception_ptr::exception_ptr( + reinterpret_cast(other)); +} + +exception_ptr& exception_ptr::operator=(const exception_ptr& other) _NOEXCEPT +{ + *reinterpret_cast<__exception_ptr::exception_ptr*>(this) = + reinterpret_cast(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)); +} Index: src/support/runtime/exception_pointer_unimplemented.ipp =================================================================== --- /dev/null +++ src/support/runtime/exception_pointer_unimplemented.ipp @@ -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 +#include + +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 Index: src/support/runtime/new_handler_fallback.ipp =================================================================== --- /dev/null +++ src/support/runtime/new_handler_fallback.ipp @@ -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 Index: src/typeinfo.cpp =================================================================== --- src/typeinfo.cpp +++ src/typeinfo.cpp @@ -6,74 +6,11 @@ // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -#include - -#if !defined(_LIBCPP_BUILDING_HAS_NO_ABI_LIBRARY) && \ - (defined(__APPLE__) || defined(LIBCXXRT) || defined(LIBCXX_BUILDING_LIBCXXABI)) -#include -#endif #include "typeinfo" -#if defined(_LIBCPP_BUILDING_HAS_NO_ABI_LIBRARY) || \ - defined(_LIBCPP_ABI_MICROSOFT) // FIXME: This is a temporary workaround +#if defined(_LIBCPP_BUILDING_HAS_NO_ABI_LIBRARY) 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