diff --git a/libcxx/include/new b/libcxx/include/new --- a/libcxx/include/new +++ b/libcxx/include/new @@ -146,10 +146,6 @@ const char* what() const _NOEXCEPT override; }; -typedef void (*new_handler)(); -_LIBCPP_EXPORTED_FROM_ABI new_handler set_new_handler(new_handler) _NOEXCEPT; -_LIBCPP_EXPORTED_FROM_ABI new_handler get_new_handler() _NOEXCEPT; - #elif defined(_HAS_EXCEPTIONS) && _HAS_EXCEPTIONS == 0 // !_LIBCPP_ABI_VCRUNTIME // When _HAS_EXCEPTIONS == 0, these complete definitions are needed, @@ -170,6 +166,16 @@ }; #endif // defined(_LIBCPP_ABI_VCRUNTIME) && defined(_HAS_EXCEPTIONS) && _HAS_EXCEPTIONS == 0 +#if defined(_LIBCPP_ABI_VCRUNTIME) +#define _NEW_HANDLER_EXPORTED +#else +#define _NEW_HANDLER_EXPORTED _LIBCPP_EXPORTED_FROM_ABI +#endif + +typedef void (*new_handler)(); +_NEW_HANDLER_EXPORTED new_handler set_new_handler(new_handler) _NOEXCEPT; +_NEW_HANDLER_EXPORTED new_handler get_new_handler() _NOEXCEPT; + _LIBCPP_NORETURN _LIBCPP_EXPORTED_FROM_ABI void __throw_bad_alloc(); // not in C++ spec _LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY diff --git a/libcxx/src/new_handler.cpp b/libcxx/src/new_handler.cpp --- a/libcxx/src/new_handler.cpp +++ b/libcxx/src/new_handler.cpp @@ -6,14 +6,13 @@ // //===----------------------------------------------------------------------===// +#include #include #include "include/atomic_support.h" #if defined(_LIBCPP_ABI_MICROSOFT) -# if !defined(_LIBCPP_ABI_VCRUNTIME) -# define _LIBPCPP_DEFINE_NEW_HANDLER -# endif +# define _LIBPCPP_DEFINE_NEW_HANDLER #elif defined(LIBCXX_BUILDING_LIBCXXABI) // nothing to do, we use the one from libc++abi #elif defined(LIBCXXRT) @@ -26,14 +25,48 @@ #if defined(_LIBPCPP_DEFINE_NEW_HANDLER) +# if defined(_LIBCPP_ABI_MICROSOFT) + +using _new_handler = int(__cdecl*)(size_t); +extern "C" _new_handler __cdecl _set_new_handler(_new_handler); + +# endif // _LIBCPP_ABI_MICROSOFT + namespace std { // purposefully not versioned +# if defined(_LIBCPP_ABI_MICROSOFT) + +static constinit new_handler __new_handler = nullptr; +static mutex __new_handler_lock; + +int __cdecl _new_handler_interface(size_t) { + __new_handler(); + return 1; +} + +new_handler set_new_handler(new_handler handler) noexcept { + lock_guard guard(__new_handler_lock); + new_handler old = __new_handler; + __new_handler = handler; + _set_new_handler(handler ? _new_handler_interface : nullptr); + return old; +} + +new_handler get_new_handler() noexcept { + lock_guard guard(__new_handler_lock); + return __new_handler; +} + +# else // _LIBCPP_ABI_MICROSOFT + static constinit std::new_handler __new_handler = nullptr; new_handler set_new_handler(new_handler handler) noexcept { return __libcpp_atomic_exchange(&__new_handler, handler); } new_handler get_new_handler() noexcept { return __libcpp_atomic_load(&__new_handler); } +# endif // _LIBCPP_ABI_MICROSOFT + } // namespace std #endif // _LIBPCPP_DEFINE_NEW_HANDLER diff --git a/libcxx/test/std/language.support/support.dynamic/alloc.errors/set.new.handler/get_new_handler.pass.cpp b/libcxx/test/std/language.support/support.dynamic/alloc.errors/set.new.handler/get_new_handler.pass.cpp --- a/libcxx/test/std/language.support/support.dynamic/alloc.errors/set.new.handler/get_new_handler.pass.cpp +++ b/libcxx/test/std/language.support/support.dynamic/alloc.errors/set.new.handler/get_new_handler.pass.cpp @@ -13,8 +13,6 @@ // are provided by vcruntime/UCRT's new.h. However, that header actually only // declares set_new_handler - it's missing a declaration of get_new_handler. -// XFAIL: msvc && stdlib=libc++ - #include #include