diff --git a/include/new b/include/new index 9baabdcd..00437927 100644 --- a/include/new +++ b/include/new @@ -65,7 +65,7 @@ class _LIBCPP_EXCEPTION_ABI bad_alloc : public exception { public: - _LIBCPP_INLINE_VISIBILITY bad_alloc() throw() {} + bad_alloc() throw(); virtual ~bad_alloc() throw(); virtual const char* what() const throw(); }; @@ -74,12 +74,12 @@ class _LIBCPP_EXCEPTION_ABI bad_array_new_length : public bad_alloc { public: - _LIBCPP_INLINE_VISIBILITY bad_array_new_length() throw() {} + bad_array_new_length() throw(); virtual ~bad_array_new_length() throw(); virtual const char* what() const throw(); }; -void __throw_bad_alloc(); +void __throw_bad_alloc(); // not in C++ spec struct nothrow_t {}; extern _LIBCPP_VISIBLE const nothrow_t nothrow; diff --git a/include/typeinfo b/include/typeinfo index 9b225419..8762de7a 100644 --- a/include/typeinfo +++ b/include/typeinfo @@ -63,17 +63,11 @@ public: #pragma GCC system_header -#pragma GCC visibility push(default) - -namespace __cxxabiv1 -{ - class __class_type_info; -} namespace std // purposefully not using versioning namespace { -class type_info +class _LIBCPP_EXCEPTION_ABI type_info { type_info& operator=(const type_info&); type_info(const type_info&); @@ -98,32 +92,29 @@ public: bool operator!=(const type_info& __arg) const {return !operator==(__arg);} - virtual bool __is_pointer_p() const; - virtual bool __is_function_p() const; - virtual bool __do_catch(const type_info*, void**, unsigned) const; - virtual bool __do_upcast(const __cxxabiv1::__class_type_info*, void**) const; }; -class bad_cast +class _LIBCPP_EXCEPTION_ABI bad_cast : public exception { public: - bad_cast() throw() {} + bad_cast() throw(); virtual ~bad_cast() throw(); virtual const char* what() const throw(); }; -class bad_typeid +class _LIBCPP_EXCEPTION_ABI bad_typeid : public exception { public: - bad_typeid () throw() { } + bad_typeid() throw(); virtual ~bad_typeid() throw(); virtual const char* what() const throw(); }; + } // std -#pragma GCC visibility pop + #endif // __LIBCPP_TYPEINFO diff --git a/src/exception.cpp b/src/exception.cpp new file mode 100644 index 00000000..336527df --- /dev/null +++ b/src/exception.cpp @@ -0,0 +1,171 @@ +//===------------------------ exception.cpp -------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#include + +#include "exception" + +#if __APPLE__ + #include + 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 + static std::terminate_handler __terminate_handler; + static std::unexpected_handler __unexpected_handler; +#endif + + + +std::unexpected_handler +std::set_unexpected(std::unexpected_handler func) throw() +{ + std::terminate_handler old = __unexpected_handler; + __unexpected_handler = func; + return old; +} + +void +std::unexpected() +{ + (*__unexpected_handler)(); + // unexpected handler should not return + std::terminate(); +} + + +std::terminate_handler +std::set_terminate(std::terminate_handler func) throw() +{ + std::terminate_handler old = __terminate_handler; + __terminate_handler = func; + return old; +} + + +void +std::terminate() +{ + try { + (*__terminate_handler)(); + // handler should not return + ::abort (); + } + catch (...) { + // handler should not throw exception + ::abort (); + } +} + + +bool std::uncaught_exception() throw() +{ +#if __APPLE__ + // on Darwin, there is a helper function so __cxa_get_globals is private + return __cxxabiapple::__cxa_uncaught_exception(); +#else + __cxa_eh_globals * globals = __cxa_get_globals(); + return (globals->uncaughtExceptions != 0); +#endif +} + + +namespace std +{ + + +exception::~exception() throw() +{ +} + +bad_exception::~bad_exception() throw() +{ +} + +const char* exception::what() const throw() +{ + return "std::exception"; +} + +const char* bad_exception::what() const throw() +{ + return "std::bad_exception"; +} + + + +exception_ptr::~exception_ptr() +{ +#if __APPLE__ + __cxxabiapple::__cxa_decrement_exception_refcount(__ptr_); +#else + #warning exception_ptr not yet implemented + ::abort(); +#endif +} + +exception_ptr::exception_ptr(const exception_ptr& other) + : __ptr_(other.__ptr_) +{ +#if __APPLE__ + __cxxabiapple::__cxa_increment_exception_refcount(__ptr_); +#else + #warning exception_ptr not yet implemented + ::abort(); +#endif +} + +exception_ptr& exception_ptr::operator=(const exception_ptr& other) +{ +#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 + #warning exception_ptr not yet implemented + ::abort(); +#endif +} + +} // std + + +std::exception_ptr std::current_exception() +{ +#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 + #warning exception_ptr not yet implemented + ::abort(); +#endif +} + +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 + #warning exception_ptr not yet implemented + ::abort(); +#endif +} + diff --git a/src/new.cpp b/src/new.cpp index 32e0cbd8..bc105cc4 100644 --- a/src/new.cpp +++ b/src/new.cpp @@ -7,11 +7,136 @@ // //===----------------------------------------------------------------------===// +#include +#include + #include "new" + +#if __APPLE__ + // On Darwin, there are two STL shared libraries and a lower level ABI + // shared libray. The global holding the current new handler is + // in the ABI library and named __cxa_new_handler. + #define __new_handler __cxxabiapple::__cxa_new_handler +#else + static std::new_handler __new_handler; +#endif + + +// Implement all new and delete operators as weak definitions +// in this shared library, so that they can be overriden by programs +// that define non-weak copies of the functions. + + +__attribute__((__weak__, __visibility__("default"))) +void * +operator new(std::size_t size) throw (std::bad_alloc) +{ + if (size == 0) + size = 1; + void* p; + while ((p = ::malloc(size)) == 0) + { + // If malloc fails and there is a new_handler, + // call it to try free up memory. + if (__new_handler) + __new_handler(); + else + throw std::bad_alloc(); + } + return p; +} + +__attribute__((__weak__, __visibility__("default"))) +void* +operator new(size_t size, const std::nothrow_t&) throw() +{ + void* p = 0; + try + { + p = ::operator new(size); + } + catch (...) + { + } + return p; +} + +__attribute__((__weak__, __visibility__("default"))) +void* +operator new[](size_t size) throw (std::bad_alloc) +{ + return ::operator new(size); +} + +__attribute__((__weak__, __visibility__("default"))) +void* +operator new[](size_t size, const std::nothrow_t& nothrow) throw() +{ + void* p = 0; + try + { + p = ::operator new[](size); + } + catch (...) + { + } + return p; +} + +__attribute__((__weak__, __visibility__("default"))) +void +operator delete(void* ptr) throw () +{ + if (ptr) + ::free(ptr); +} + +__attribute__((__weak__, __visibility__("default"))) +void +operator delete(void* ptr, const std::nothrow_t&) throw () +{ + ::operator delete(ptr); +} + + +__attribute__((__weak__, __visibility__("default"))) +void +operator delete[] (void* ptr) throw () +{ + ::operator delete (ptr); +} + +__attribute__((__weak__, __visibility__("default"))) +void +operator delete[] (void* ptr, const std::nothrow_t&) throw () +{ + ::operator delete[](ptr); +} + + namespace std { +bad_alloc::bad_alloc() throw() +{ +} + +bad_alloc::~bad_alloc() throw() +{ +} + +const char* +bad_alloc::what() const throw() +{ + return "std::bad_alloc"; +} + + +bad_array_new_length::bad_array_new_length() throw() +{ +} + bad_array_new_length::~bad_array_new_length() throw() { } @@ -22,6 +147,8 @@ bad_array_new_length::what() const throw() return "bad_array_new_length"; } + + void __throw_bad_alloc() { diff --git a/src/typeinfo.cpp b/src/typeinfo.cpp new file mode 100644 index 00000000..8606897e --- /dev/null +++ b/src/typeinfo.cpp @@ -0,0 +1,41 @@ +//===------------------------- typeinfo.cpp -------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#include + +#include "typeinfo" + +std::bad_cast::bad_cast() throw() +{ +} + +std::bad_cast::~bad_cast() throw() +{ +} + +const char* +std::bad_cast::what() const throw() +{ + return "std::bad_cast"; +} + + +std::bad_typeid::bad_typeid() throw() +{ +} + +std::bad_typeid::~bad_typeid() throw() +{ +} + +const char* +std::bad_typeid::what() const throw() +{ + return "std::bad_typeid"; +} +