diff --git a/include/exception b/include/exception index 845697203..4871f4139 100644 --- a/include/exception +++ b/include/exception @@ -40,10 +40,12 @@ public: typedef void (*unexpected_handler)(); unexpected_handler set_unexpected(unexpected_handler f ) throw(); +unexpected_handler get_unexpected() throw(); void unexpected [[noreturn]] (); typedef void (*terminate_handler)(); terminate_handler set_terminate(terminate_handler f ) throw(); +terminate_handler get_terminate() throw(); void terminate [[noreturn]] (); bool uncaught_exception() throw(); @@ -102,10 +104,12 @@ public: typedef void (*unexpected_handler)(); _LIBCPP_VISIBLE unexpected_handler set_unexpected(unexpected_handler) throw(); +_LIBCPP_VISIBLE unexpected_handler get_unexpected() throw(); _LIBCPP_VISIBLE void unexpected(); typedef void (*terminate_handler)(); _LIBCPP_VISIBLE terminate_handler set_terminate(terminate_handler) throw(); +_LIBCPP_VISIBLE terminate_handler get_terminate() throw(); _LIBCPP_VISIBLE void terminate() __attribute__((__noreturn__)); _LIBCPP_VISIBLE bool uncaught_exception() throw(); diff --git a/include/future b/include/future index 73a6391e0..3be5f0520 100644 --- a/include/future +++ b/include/future @@ -2297,6 +2297,8 @@ future<_R&>::share() return shared_future<_R&>(_STD::move(*this)); } +#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES + inline _LIBCPP_INLINE_VISIBILITY shared_future future::share() @@ -2304,6 +2306,8 @@ future::share() return shared_future(_STD::move(*this)); } +#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES + _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP_FUTURE diff --git a/include/new b/include/new index 4b3c4b877..68f0274b9 100644 --- a/include/new +++ b/include/new @@ -32,6 +32,7 @@ struct nothrow_t {}; extern const nothrow_t nothrow; typedef void (*new_handler)(); new_handler set_new_handler(new_handler new_p) throw(); +new_handler get_new_handler() throw(); } // std @@ -85,6 +86,7 @@ struct _LIBCPP_VISIBLE nothrow_t {}; extern _LIBCPP_VISIBLE const nothrow_t nothrow; typedef void (*new_handler)(); _LIBCPP_VISIBLE new_handler set_new_handler(new_handler) throw(); +_LIBCPP_VISIBLE new_handler get_new_handler() throw(); } // std diff --git a/src/exception.cpp b/src/exception.cpp index 1ab5a1952..062114c25 100644 --- a/src/exception.cpp +++ b/src/exception.cpp @@ -26,9 +26,13 @@ std::unexpected_handler std::set_unexpected(std::unexpected_handler func) throw() { - std::terminate_handler old = __unexpected_handler; - __unexpected_handler = func; - return old; + return __sync_lock_test_and_set(&__unexpected_handler, func); +} + +std::unexpected_handler +std::get_unexpected() throw() +{ + return __sync_fetch_and_add(&__unexpected_handler, (std::unexpected_handler)0); } void @@ -42,9 +46,13 @@ std::unexpected() std::terminate_handler std::set_terminate(std::terminate_handler func) throw() { - std::terminate_handler old = __terminate_handler; - __terminate_handler = func; - return old; + return __sync_lock_test_and_set(&__terminate_handler, func); +} + +std::terminate_handler +std::get_terminate() throw() +{ + return __sync_fetch_and_add(&__terminate_handler, (std::terminate_handler)0); } void diff --git a/src/new.cpp b/src/new.cpp index 874ad6c02..a3783d47e 100644 --- a/src/new.cpp +++ b/src/new.cpp @@ -130,9 +130,13 @@ const nothrow_t nothrow = {}; new_handler set_new_handler(new_handler handler) throw() { - new_handler r = __new_handler; - __new_handler = handler; - return r; + return __sync_lock_test_and_set(&__new_handler, handler); +} + +new_handler +get_new_handler() throw() +{ + return __sync_fetch_and_add(&__new_handler, (new_handler)0); } bad_alloc::bad_alloc() throw() diff --git a/test/depr/exception.unexpected/set.unexpected/get_unexpected.pass.cpp b/test/depr/exception.unexpected/set.unexpected/get_unexpected.pass.cpp new file mode 100644 index 000000000..8b0a0b979 --- /dev/null +++ b/test/depr/exception.unexpected/set.unexpected/get_unexpected.pass.cpp @@ -0,0 +1,39 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// test get_unexpected + +#include +#include +#include + +void f1() {} +void f2() {} + +void f3() +{ + std::exit(0); +} + +int main() +{ + + std::unexpected_handler old = std::get_unexpected(); + // verify there is a previous unexpected handler + assert(old); + std::set_unexpected(f1); + assert(std::get_unexpected() == f1); + // verify f1 was replace with f2 + std::set_unexpected(f2); + assert(std::get_unexpected() == f2); + // verify calling original unexpected handler calls terminate + std::set_terminate(f3); + (*old)(); + assert(0); +} diff --git a/test/language.support/support.dynamic/alloc.errors/set.new.handler/get_new_handler.pass.cpp b/test/language.support/support.dynamic/alloc.errors/set.new.handler/get_new_handler.pass.cpp new file mode 100644 index 000000000..55a3edabf --- /dev/null +++ b/test/language.support/support.dynamic/alloc.errors/set.new.handler/get_new_handler.pass.cpp @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// test get_new_handler + +#include +#include + +void f1() {} +void f2() {} + +int main() +{ + assert(std::get_new_handler() == 0); + std::set_new_handler(f1); + assert(std::get_new_handler() == f1); + std::set_new_handler(f2); + assert(std::get_new_handler() == f2); +} diff --git a/test/language.support/support.exception/exception.terminate/set.terminate/get_terminate.pass.cpp b/test/language.support/support.exception/exception.terminate/set.terminate/get_terminate.pass.cpp new file mode 100644 index 000000000..82ae4aaa8 --- /dev/null +++ b/test/language.support/support.exception/exception.terminate/set.terminate/get_terminate.pass.cpp @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// test get_terminate + +#include +#include +#include + +void f1() {} +void f2() {} + +int main() +{ + std::set_terminate(f1); + assert(std::get_terminate() == f1); + std::set_terminate(f2); + assert(std::get_terminate() == f2); +}