diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2024-04-26 15:33:29 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2024-05-08 19:37:29 -0700 |
| commit | 06ee65af9ed6aa5ee4d1d7f4fab9d7acecf66e76 (patch) | |
| tree | 1316711b92a43dd5c599e425b8693fa8e1e0c0b7 /lib/libcxx/src/new.cpp | |
| parent | bc6ebc6f2597fda1f98842c6f545751fef2a5334 (diff) | |
| download | zig-06ee65af9ed6aa5ee4d1d7f4fab9d7acecf66e76.tar.gz zig-06ee65af9ed6aa5ee4d1d7f4fab9d7acecf66e76.zip | |
libcxx: update to LLVM 18
release/18.x branch, commit 78b99c73ee4b96fe9ce0e294d4632326afb2db42
This adds the flag `-D_LIBCPP_HARDENING_MODE` which is determined based
on the Zig optimization mode.
This commit also fixes libunwind, libcxx, and libcxxabi to properly
report sub compilation errors.
Diffstat (limited to 'lib/libcxx/src/new.cpp')
| -rw-r--r-- | lib/libcxx/src/new.cpp | 405 |
1 files changed, 186 insertions, 219 deletions
diff --git a/lib/libcxx/src/new.cpp b/lib/libcxx/src/new.cpp index c435c5ffc8..0869d90661 100644 --- a/lib/libcxx/src/new.cpp +++ b/lib/libcxx/src/new.cpp @@ -6,7 +6,9 @@ // //===----------------------------------------------------------------------===// +#include "include/overridable_function.h" #include <__memory/aligned_alloc.h> +#include <cstddef> #include <cstdlib> #include <new> @@ -15,244 +17,209 @@ // The code below is copied as-is into libc++abi's libcxxabi/src/stdlib_new_delete.cpp // file. The version in this file is the canonical one. +inline void __throw_bad_alloc_shim() { std::__throw_bad_alloc(); } + +# define _LIBCPP_ASSERT_SHIM(expr, str) _LIBCPP_ASSERT(expr, str) + // ------------------ BEGIN COPY ------------------ // Implement all new and delete operators as weak definitions // in this shared library, so that they can be overridden by programs // that define non-weak copies of the functions. -_LIBCPP_WEAK -void * -operator new(std::size_t size) _THROW_BAD_ALLOC -{ - if (size == 0) - size = 1; - void* p; - while ((p = std::malloc(size)) == nullptr) - { - // If malloc fails and there is a new_handler, - // call it to try free up memory. - std::new_handler nh = std::get_new_handler(); - if (nh) - nh(); - else -#ifndef _LIBCPP_HAS_NO_EXCEPTIONS - throw std::bad_alloc(); -#else - break; -#endif - } - return p; -} - -_LIBCPP_WEAK -void* -operator new(size_t size, const std::nothrow_t&) noexcept -{ - void* p = nullptr; -#ifndef _LIBCPP_HAS_NO_EXCEPTIONS - try - { -#endif // _LIBCPP_HAS_NO_EXCEPTIONS - p = ::operator new(size); -#ifndef _LIBCPP_HAS_NO_EXCEPTIONS - } - catch (...) - { - } -#endif // _LIBCPP_HAS_NO_EXCEPTIONS - return p; -} - -_LIBCPP_WEAK -void* -operator new[](size_t size) _THROW_BAD_ALLOC -{ - return ::operator new(size); -} - -_LIBCPP_WEAK -void* -operator new[](size_t size, const std::nothrow_t&) noexcept -{ - void* p = nullptr; -#ifndef _LIBCPP_HAS_NO_EXCEPTIONS - try - { -#endif // _LIBCPP_HAS_NO_EXCEPTIONS - p = ::operator new[](size); -#ifndef _LIBCPP_HAS_NO_EXCEPTIONS - } - catch (...) - { - } -#endif // _LIBCPP_HAS_NO_EXCEPTIONS - return p; -} - -_LIBCPP_WEAK -void -operator delete(void* ptr) noexcept -{ - std::free(ptr); -} - -_LIBCPP_WEAK -void -operator delete(void* ptr, const std::nothrow_t&) noexcept -{ - ::operator delete(ptr); -} - -_LIBCPP_WEAK -void -operator delete(void* ptr, size_t) noexcept -{ - ::operator delete(ptr); +static void* operator_new_impl(std::size_t size) { + if (size == 0) + size = 1; + void* p; + while ((p = std::malloc(size)) == nullptr) { + // If malloc fails and there is a new_handler, + // call it to try free up memory. + std::new_handler nh = std::get_new_handler(); + if (nh) + nh(); + else + break; + } + return p; +} + +_LIBCPP_MAKE_OVERRIDABLE_FUNCTION_DETECTABLE _LIBCPP_WEAK void* operator new(std::size_t size) _THROW_BAD_ALLOC { + void* p = operator_new_impl(size); + if (p == nullptr) + __throw_bad_alloc_shim(); + return p; +} + +_LIBCPP_WEAK void* operator new(size_t size, const std::nothrow_t&) noexcept { +# ifdef _LIBCPP_HAS_NO_EXCEPTIONS +# if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION + _LIBCPP_ASSERT_SHIM( + !std::__is_function_overridden(static_cast<void* (*)(std::size_t)>(&operator new)), + "libc++ was configured with exceptions disabled and `operator new(size_t)` has been overridden, " + "but `operator new(size_t, nothrow_t)` has not been overridden. This is problematic because " + "`operator new(size_t, nothrow_t)` must call `operator new(size_t)`, which will terminate in case " + "it fails to allocate, making it impossible for `operator new(size_t, nothrow_t)` to fulfill its " + "contract (since it should return nullptr upon failure). Please make sure you override " + "`operator new(size_t, nothrow_t)` as well."); +# endif + + return operator_new_impl(size); +# else + void* p = nullptr; + try { + p = ::operator new(size); + } catch (...) { + } + return p; +# endif +} + +_LIBCPP_MAKE_OVERRIDABLE_FUNCTION_DETECTABLE _LIBCPP_WEAK void* operator new[](size_t size) _THROW_BAD_ALLOC { + return ::operator new(size); +} + +_LIBCPP_WEAK void* operator new[](size_t size, const std::nothrow_t&) noexcept { +# ifdef _LIBCPP_HAS_NO_EXCEPTIONS +# if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION + _LIBCPP_ASSERT_SHIM( + !std::__is_function_overridden(static_cast<void* (*)(std::size_t)>(&operator new[])), + "libc++ was configured with exceptions disabled and `operator new[](size_t)` has been overridden, " + "but `operator new[](size_t, nothrow_t)` has not been overridden. This is problematic because " + "`operator new[](size_t, nothrow_t)` must call `operator new[](size_t)`, which will terminate in case " + "it fails to allocate, making it impossible for `operator new[](size_t, nothrow_t)` to fulfill its " + "contract (since it should return nullptr upon failure). Please make sure you override " + "`operator new[](size_t, nothrow_t)` as well."); +# endif + + return operator_new_impl(size); +# else + void* p = nullptr; + try { + p = ::operator new[](size); + } catch (...) { + } + return p; +# endif +} + +_LIBCPP_WEAK void operator delete(void* ptr) noexcept { std::free(ptr); } + +_LIBCPP_WEAK void operator delete(void* ptr, const std::nothrow_t&) noexcept { ::operator delete(ptr); } + +_LIBCPP_WEAK void operator delete(void* ptr, size_t) noexcept { ::operator delete(ptr); } + +_LIBCPP_WEAK void operator delete[](void* ptr) noexcept { ::operator delete(ptr); } + +_LIBCPP_WEAK void operator delete[](void* ptr, const std::nothrow_t&) noexcept { ::operator delete[](ptr); } + +_LIBCPP_WEAK void operator delete[](void* ptr, size_t) noexcept { ::operator delete[](ptr); } + +# if !defined(_LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION) + +static void* operator_new_aligned_impl(std::size_t size, std::align_val_t alignment) { + if (size == 0) + size = 1; + if (static_cast<size_t>(alignment) < sizeof(void*)) + alignment = std::align_val_t(sizeof(void*)); + + // Try allocating memory. If allocation fails and there is a new_handler, + // call it to try free up memory, and try again until it succeeds, or until + // the new_handler decides to terminate. + void* p; + while ((p = std::__libcpp_aligned_alloc(static_cast<std::size_t>(alignment), size)) == nullptr) { + std::new_handler nh = std::get_new_handler(); + if (nh) + nh(); + else + break; + } + return p; +} + +_LIBCPP_MAKE_OVERRIDABLE_FUNCTION_DETECTABLE _LIBCPP_WEAK void* +operator new(std::size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC { + void* p = operator_new_aligned_impl(size, alignment); + if (p == nullptr) + __throw_bad_alloc_shim(); + return p; +} + +_LIBCPP_WEAK void* operator new(size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept { +# ifdef _LIBCPP_HAS_NO_EXCEPTIONS +# if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION + _LIBCPP_ASSERT_SHIM( + !std::__is_function_overridden(static_cast<void* (*)(std::size_t, std::align_val_t)>(&operator new)), + "libc++ was configured with exceptions disabled and `operator new(size_t, align_val_t)` has been overridden, " + "but `operator new(size_t, align_val_t, nothrow_t)` has not been overridden. This is problematic because " + "`operator new(size_t, align_val_t, nothrow_t)` must call `operator new(size_t, align_val_t)`, which will " + "terminate in case it fails to allocate, making it impossible for `operator new(size_t, align_val_t, nothrow_t)` " + "to fulfill its contract (since it should return nullptr upon failure). Please make sure you override " + "`operator new(size_t, align_val_t, nothrow_t)` as well."); +# endif + + return operator_new_aligned_impl(size, alignment); +# else + void* p = nullptr; + try { + p = ::operator new(size, alignment); + } catch (...) { + } + return p; +# endif } -_LIBCPP_WEAK -void -operator delete[] (void* ptr) noexcept -{ - ::operator delete(ptr); +_LIBCPP_MAKE_OVERRIDABLE_FUNCTION_DETECTABLE _LIBCPP_WEAK void* +operator new[](size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC { + return ::operator new(size, alignment); } -_LIBCPP_WEAK -void -operator delete[] (void* ptr, const std::nothrow_t&) noexcept -{ - ::operator delete[](ptr); -} - -_LIBCPP_WEAK -void -operator delete[] (void* ptr, size_t) noexcept -{ - ::operator delete[](ptr); -} - -#if !defined(_LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION) - -_LIBCPP_WEAK -void * -operator new(std::size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC -{ - if (size == 0) - size = 1; - if (static_cast<size_t>(alignment) < sizeof(void*)) - alignment = std::align_val_t(sizeof(void*)); - - // Try allocating memory. If allocation fails and there is a new_handler, - // call it to try free up memory, and try again until it succeeds, or until - // the new_handler decides to terminate. - // - // If allocation fails and there is no new_handler, we throw bad_alloc - // (or return nullptr if exceptions are disabled). - void* p; - while ((p = std::__libcpp_aligned_alloc(static_cast<std::size_t>(alignment), size)) == nullptr) - { - std::new_handler nh = std::get_new_handler(); - if (nh) - nh(); - else { -#ifndef _LIBCPP_HAS_NO_EXCEPTIONS - throw std::bad_alloc(); -#else - break; -#endif - } - } - return p; -} - -_LIBCPP_WEAK -void* -operator new(size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept -{ - void* p = nullptr; -#ifndef _LIBCPP_HAS_NO_EXCEPTIONS - try - { -#endif // _LIBCPP_HAS_NO_EXCEPTIONS - p = ::operator new(size, alignment); -#ifndef _LIBCPP_HAS_NO_EXCEPTIONS - } - catch (...) - { - } -#endif // _LIBCPP_HAS_NO_EXCEPTIONS - return p; -} +_LIBCPP_WEAK void* operator new[](size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept { +# ifdef _LIBCPP_HAS_NO_EXCEPTIONS +# if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION + _LIBCPP_ASSERT_SHIM( + !std::__is_function_overridden(static_cast<void* (*)(std::size_t, std::align_val_t)>(&operator new[])), + "libc++ was configured with exceptions disabled and `operator new[](size_t, align_val_t)` has been overridden, " + "but `operator new[](size_t, align_val_t, nothrow_t)` has not been overridden. This is problematic because " + "`operator new[](size_t, align_val_t, nothrow_t)` must call `operator new[](size_t, align_val_t)`, which will " + "terminate in case it fails to allocate, making it impossible for `operator new[](size_t, align_val_t, " + "nothrow_t)` to fulfill its contract (since it should return nullptr upon failure). Please make sure you " + "override " + "`operator new[](size_t, align_val_t, nothrow_t)` as well."); +# endif -_LIBCPP_WEAK -void* -operator new[](size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC -{ - return ::operator new(size, alignment); + return operator_new_aligned_impl(size, alignment); +# else + void* p = nullptr; + try { + p = ::operator new[](size, alignment); + } catch (...) { + } + return p; +# endif } -_LIBCPP_WEAK -void* -operator new[](size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept -{ - void* p = nullptr; -#ifndef _LIBCPP_HAS_NO_EXCEPTIONS - try - { -#endif // _LIBCPP_HAS_NO_EXCEPTIONS - p = ::operator new[](size, alignment); -#ifndef _LIBCPP_HAS_NO_EXCEPTIONS - } - catch (...) - { - } -#endif // _LIBCPP_HAS_NO_EXCEPTIONS - return p; -} - -_LIBCPP_WEAK -void -operator delete(void* ptr, std::align_val_t) noexcept -{ - std::__libcpp_aligned_free(ptr); -} - -_LIBCPP_WEAK -void -operator delete(void* ptr, std::align_val_t alignment, const std::nothrow_t&) noexcept -{ - ::operator delete(ptr, alignment); -} - -_LIBCPP_WEAK -void -operator delete(void* ptr, size_t, std::align_val_t alignment) noexcept -{ - ::operator delete(ptr, alignment); -} +_LIBCPP_WEAK void operator delete(void* ptr, std::align_val_t) noexcept { std::__libcpp_aligned_free(ptr); } -_LIBCPP_WEAK -void -operator delete[] (void* ptr, std::align_val_t alignment) noexcept -{ - ::operator delete(ptr, alignment); +_LIBCPP_WEAK void operator delete(void* ptr, std::align_val_t alignment, const std::nothrow_t&) noexcept { + ::operator delete(ptr, alignment); } -_LIBCPP_WEAK -void -operator delete[] (void* ptr, std::align_val_t alignment, const std::nothrow_t&) noexcept -{ - ::operator delete[](ptr, alignment); +_LIBCPP_WEAK void operator delete(void* ptr, size_t, std::align_val_t alignment) noexcept { + ::operator delete(ptr, alignment); } -_LIBCPP_WEAK -void -operator delete[] (void* ptr, size_t, std::align_val_t alignment) noexcept -{ - ::operator delete[](ptr, alignment); +_LIBCPP_WEAK void operator delete[](void* ptr, std::align_val_t alignment) noexcept { + ::operator delete(ptr, alignment); } -#endif // !_LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION +_LIBCPP_WEAK void operator delete[](void* ptr, std::align_val_t alignment, const std::nothrow_t&) noexcept { + ::operator delete[](ptr, alignment); +} + +_LIBCPP_WEAK void operator delete[](void* ptr, size_t, std::align_val_t alignment) noexcept { + ::operator delete[](ptr, alignment); +} + +# endif // !_LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION // ------------------ END COPY ------------------ #endif // !__GLIBCXX__ && !_LIBCPP_ABI_VCRUNTIME |
