1eb8650a7SLouis Dionne //===----------------------------------------------------------------------===// 237812274SEric Fiselier // 357b08b09SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 457b08b09SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 557b08b09SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 637812274SEric Fiselier // 737812274SEric Fiselier //===----------------------------------------------------------------------===// 837812274SEric Fiselier 937812274SEric Fiselier #include "__cxxabi_config.h" 1031452655SLouis Dionne #include "abort_message.h" 1131452655SLouis Dionne #include "include/overridable_function.h" // from libc++ 1236080434SLouis Dionne #include <__memory/aligned_alloc.h> 1331452655SLouis Dionne #include <cstddef> 1437812274SEric Fiselier #include <cstdlib> 1536080434SLouis Dionne #include <new> 1637812274SEric Fiselier 17d53cf0fdSLouis Dionne // Perform a few sanity checks on libc++ and libc++abi macros to ensure that 18d53cf0fdSLouis Dionne // the code below can be an exact copy of the code in libcxx/src/new.cpp. 19d53cf0fdSLouis Dionne #if !defined(_THROW_BAD_ALLOC) 20d53cf0fdSLouis Dionne # error The _THROW_BAD_ALLOC macro should be already defined by libc++ 2137812274SEric Fiselier #endif 22d53cf0fdSLouis Dionne 23d53cf0fdSLouis Dionne #ifndef _LIBCPP_WEAK 24d53cf0fdSLouis Dionne # error The _LIBCPP_WEAK macro should be already defined by libc++ 25d53cf0fdSLouis Dionne #endif 26d53cf0fdSLouis Dionne 27ba87515fSNikolas Klauser #if defined(_LIBCXXABI_NO_EXCEPTIONS) != !_LIBCPP_HAS_EXCEPTIONS 28d53cf0fdSLouis Dionne # error libc++ and libc++abi seem to disagree on whether exceptions are enabled 29d53cf0fdSLouis Dionne #endif 30d53cf0fdSLouis Dionne 3131452655SLouis Dionne inline void __throw_bad_alloc_shim() { 32ba87515fSNikolas Klauser #if _LIBCPP_HAS_EXCEPTIONS 3331452655SLouis Dionne throw std::bad_alloc(); 3431452655SLouis Dionne #else 35e0737174SPetr Hosek __abort_message("bad_alloc was thrown in -fno-exceptions mode"); 3631452655SLouis Dionne #endif 3731452655SLouis Dionne } 3831452655SLouis Dionne 3931452655SLouis Dionne #define _LIBCPP_ASSERT_SHIM(expr, str) \ 4031452655SLouis Dionne do { \ 4131452655SLouis Dionne if (!expr) \ 42e0737174SPetr Hosek __abort_message(str); \ 4331452655SLouis Dionne } while (false) 4431452655SLouis Dionne 45d53cf0fdSLouis Dionne // ------------------ BEGIN COPY ------------------ 46b2577e5dSEric Fiselier // Implement all new and delete operators as weak definitions 47b2577e5dSEric Fiselier // in this shared library, so that they can be overridden by programs 48b2577e5dSEric Fiselier // that define non-weak copies of the functions. 4937812274SEric Fiselier 504207ad57Sazhan92 static void* operator_new_impl(std::size_t size) { 5137812274SEric Fiselier if (size == 0) 5237812274SEric Fiselier size = 1; 5337812274SEric Fiselier void* p; 54f362be59SLouis Dionne while ((p = std::malloc(size)) == nullptr) { 55b2577e5dSEric Fiselier // If malloc fails and there is a new_handler, 56b2577e5dSEric Fiselier // call it to try free up memory. 5737812274SEric Fiselier std::new_handler nh = std::get_new_handler(); 5837812274SEric Fiselier if (nh) 5937812274SEric Fiselier nh(); 6037812274SEric Fiselier else 6137812274SEric Fiselier break; 6237812274SEric Fiselier } 6337812274SEric Fiselier return p; 6437812274SEric Fiselier } 6537812274SEric Fiselier 66*4167ea2cSPetr Hosek _LIBCPP_MAKE_OVERRIDABLE_FUNCTION_DETECTABLE _LIBCPP_WEAK void* operator new(std::size_t size) _THROW_BAD_ALLOC { 67e494a96aSLouis Dionne void* p = operator_new_impl(size); 68e494a96aSLouis Dionne if (p == nullptr) 6931452655SLouis Dionne __throw_bad_alloc_shim(); 7031452655SLouis Dionne return p; 7131452655SLouis Dionne } 7231452655SLouis Dionne 7331452655SLouis Dionne _LIBCPP_WEAK void* operator new(size_t size, const std::nothrow_t&) noexcept { 74ba87515fSNikolas Klauser #if !_LIBCPP_HAS_EXCEPTIONS 7531452655SLouis Dionne # if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION 7631452655SLouis Dionne _LIBCPP_ASSERT_SHIM( 77*4167ea2cSPetr Hosek !std::__is_function_overridden(static_cast<void* (*)(std::size_t)>(&operator new)), 7831452655SLouis Dionne "libc++ was configured with exceptions disabled and `operator new(size_t)` has been overridden, " 7931452655SLouis Dionne "but `operator new(size_t, nothrow_t)` has not been overridden. This is problematic because " 8031452655SLouis Dionne "`operator new(size_t, nothrow_t)` must call `operator new(size_t)`, which will terminate in case " 8131452655SLouis Dionne "it fails to allocate, making it impossible for `operator new(size_t, nothrow_t)` to fulfill its " 8231452655SLouis Dionne "contract (since it should return nullptr upon failure). Please make sure you override " 8331452655SLouis Dionne "`operator new(size_t, nothrow_t)` as well."); 84e494a96aSLouis Dionne # endif 85e494a96aSLouis Dionne 8631452655SLouis Dionne return operator_new_impl(size); 8731452655SLouis Dionne #else 88527a7fdfSBruce Mitchener void* p = nullptr; 89f362be59SLouis Dionne try { 9037812274SEric Fiselier p = ::operator new(size); 91f362be59SLouis Dionne } catch (...) { 9237812274SEric Fiselier } 9337812274SEric Fiselier return p; 9431452655SLouis Dionne #endif 9537812274SEric Fiselier } 9637812274SEric Fiselier 97*4167ea2cSPetr Hosek _LIBCPP_MAKE_OVERRIDABLE_FUNCTION_DETECTABLE _LIBCPP_WEAK void* operator new[](size_t size) _THROW_BAD_ALLOC { 9831452655SLouis Dionne return ::operator new(size); 9931452655SLouis Dionne } 10037812274SEric Fiselier 10131452655SLouis Dionne _LIBCPP_WEAK void* operator new[](size_t size, const std::nothrow_t&) noexcept { 102ba87515fSNikolas Klauser #if !_LIBCPP_HAS_EXCEPTIONS 10331452655SLouis Dionne # if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION 10431452655SLouis Dionne _LIBCPP_ASSERT_SHIM( 105*4167ea2cSPetr Hosek !std::__is_function_overridden(static_cast<void* (*)(std::size_t)>(&operator new[])), 10631452655SLouis Dionne "libc++ was configured with exceptions disabled and `operator new[](size_t)` has been overridden, " 10731452655SLouis Dionne "but `operator new[](size_t, nothrow_t)` has not been overridden. This is problematic because " 10831452655SLouis Dionne "`operator new[](size_t, nothrow_t)` must call `operator new[](size_t)`, which will terminate in case " 10931452655SLouis Dionne "it fails to allocate, making it impossible for `operator new[](size_t, nothrow_t)` to fulfill its " 11031452655SLouis Dionne "contract (since it should return nullptr upon failure). Please make sure you override " 11131452655SLouis Dionne "`operator new[](size_t, nothrow_t)` as well."); 11231452655SLouis Dionne # endif 11331452655SLouis Dionne 11431452655SLouis Dionne return operator_new_impl(size); 11531452655SLouis Dionne #else 116527a7fdfSBruce Mitchener void* p = nullptr; 117f362be59SLouis Dionne try { 11837812274SEric Fiselier p = ::operator new[](size); 119f362be59SLouis Dionne } catch (...) { 12037812274SEric Fiselier } 12137812274SEric Fiselier return p; 12231452655SLouis Dionne #endif 12337812274SEric Fiselier } 12437812274SEric Fiselier 12531452655SLouis Dionne _LIBCPP_WEAK void operator delete(void* ptr) noexcept { std::free(ptr); } 12637812274SEric Fiselier 12731452655SLouis Dionne _LIBCPP_WEAK void operator delete(void* ptr, const std::nothrow_t&) noexcept { ::operator delete(ptr); } 12837812274SEric Fiselier 12931452655SLouis Dionne _LIBCPP_WEAK void operator delete(void* ptr, size_t) noexcept { ::operator delete(ptr); } 13037812274SEric Fiselier 13131452655SLouis Dionne _LIBCPP_WEAK void operator delete[](void* ptr) noexcept { ::operator delete(ptr); } 13237812274SEric Fiselier 13331452655SLouis Dionne _LIBCPP_WEAK void operator delete[](void* ptr, const std::nothrow_t&) noexcept { ::operator delete[](ptr); } 134b2577e5dSEric Fiselier 13531452655SLouis Dionne _LIBCPP_WEAK void operator delete[](void* ptr, size_t) noexcept { ::operator delete[](ptr); } 136b2577e5dSEric Fiselier 137ba87515fSNikolas Klauser #if _LIBCPP_HAS_LIBRARY_ALIGNED_ALLOCATION 138b2577e5dSEric Fiselier 1394207ad57Sazhan92 static void* operator_new_aligned_impl(std::size_t size, std::align_val_t alignment) { 140b2577e5dSEric Fiselier if (size == 0) 141b2577e5dSEric Fiselier size = 1; 142b2577e5dSEric Fiselier if (static_cast<size_t>(alignment) < sizeof(void*)) 143b2577e5dSEric Fiselier alignment = std::align_val_t(sizeof(void*)); 144a78aaa1aSLouis Dionne 145a78aaa1aSLouis Dionne // Try allocating memory. If allocation fails and there is a new_handler, 146a78aaa1aSLouis Dionne // call it to try free up memory, and try again until it succeeds, or until 147a78aaa1aSLouis Dionne // the new_handler decides to terminate. 148b2577e5dSEric Fiselier void* p; 149f362be59SLouis Dionne while ((p = std::__libcpp_aligned_alloc(static_cast<std::size_t>(alignment), size)) == nullptr) { 150b2577e5dSEric Fiselier std::new_handler nh = std::get_new_handler(); 151b2577e5dSEric Fiselier if (nh) 152b2577e5dSEric Fiselier nh(); 153e494a96aSLouis Dionne else 154b2577e5dSEric Fiselier break; 155e494a96aSLouis Dionne } 156e494a96aSLouis Dionne return p; 157e494a96aSLouis Dionne } 158e494a96aSLouis Dionne 159*4167ea2cSPetr Hosek _LIBCPP_MAKE_OVERRIDABLE_FUNCTION_DETECTABLE _LIBCPP_WEAK void* 160*4167ea2cSPetr Hosek operator new(std::size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC { 161e494a96aSLouis Dionne void* p = operator_new_aligned_impl(size, alignment); 162e494a96aSLouis Dionne if (p == nullptr) 16331452655SLouis Dionne __throw_bad_alloc_shim(); 164b2577e5dSEric Fiselier return p; 165b2577e5dSEric Fiselier } 166b2577e5dSEric Fiselier 16731452655SLouis Dionne _LIBCPP_WEAK void* operator new(size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept { 168ba87515fSNikolas Klauser # if !_LIBCPP_HAS_EXCEPTIONS 16931452655SLouis Dionne # if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION 17031452655SLouis Dionne _LIBCPP_ASSERT_SHIM( 171*4167ea2cSPetr Hosek !std::__is_function_overridden(static_cast<void* (*)(std::size_t, std::align_val_t)>(&operator new)), 17231452655SLouis Dionne "libc++ was configured with exceptions disabled and `operator new(size_t, align_val_t)` has been overridden, " 17331452655SLouis Dionne "but `operator new(size_t, align_val_t, nothrow_t)` has not been overridden. This is problematic because " 17431452655SLouis Dionne "`operator new(size_t, align_val_t, nothrow_t)` must call `operator new(size_t, align_val_t)`, which will " 17531452655SLouis Dionne "terminate in case it fails to allocate, making it impossible for `operator new(size_t, align_val_t, nothrow_t)` " 17631452655SLouis Dionne "to fulfill its contract (since it should return nullptr upon failure). Please make sure you override " 17731452655SLouis Dionne "`operator new(size_t, align_val_t, nothrow_t)` as well."); 17831452655SLouis Dionne # endif 17931452655SLouis Dionne 18031452655SLouis Dionne return operator_new_aligned_impl(size, alignment); 18131452655SLouis Dionne # else 182527a7fdfSBruce Mitchener void* p = nullptr; 183f362be59SLouis Dionne try { 184b2577e5dSEric Fiselier p = ::operator new(size, alignment); 185f362be59SLouis Dionne } catch (...) { 186b2577e5dSEric Fiselier } 187b2577e5dSEric Fiselier return p; 18831452655SLouis Dionne # endif 189b2577e5dSEric Fiselier } 190b2577e5dSEric Fiselier 191*4167ea2cSPetr Hosek _LIBCPP_MAKE_OVERRIDABLE_FUNCTION_DETECTABLE _LIBCPP_WEAK void* 192*4167ea2cSPetr Hosek operator new[](size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC { 193*4167ea2cSPetr Hosek return ::operator new(size, alignment); 194*4167ea2cSPetr Hosek } 195b2577e5dSEric Fiselier 19631452655SLouis Dionne _LIBCPP_WEAK void* operator new[](size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept { 197ba87515fSNikolas Klauser # if !_LIBCPP_HAS_EXCEPTIONS 19831452655SLouis Dionne # if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION 19931452655SLouis Dionne _LIBCPP_ASSERT_SHIM( 200*4167ea2cSPetr Hosek !std::__is_function_overridden(static_cast<void* (*)(std::size_t, std::align_val_t)>(&operator new[])), 20131452655SLouis Dionne "libc++ was configured with exceptions disabled and `operator new[](size_t, align_val_t)` has been overridden, " 20231452655SLouis Dionne "but `operator new[](size_t, align_val_t, nothrow_t)` has not been overridden. This is problematic because " 20331452655SLouis Dionne "`operator new[](size_t, align_val_t, nothrow_t)` must call `operator new[](size_t, align_val_t)`, which will " 20431452655SLouis Dionne "terminate in case it fails to allocate, making it impossible for `operator new[](size_t, align_val_t, " 20531452655SLouis Dionne "nothrow_t)` to fulfill its contract (since it should return nullptr upon failure). Please make sure you " 20631452655SLouis Dionne "override " 20731452655SLouis Dionne "`operator new[](size_t, align_val_t, nothrow_t)` as well."); 20831452655SLouis Dionne # endif 20931452655SLouis Dionne 21031452655SLouis Dionne return operator_new_aligned_impl(size, alignment); 21131452655SLouis Dionne # else 212527a7fdfSBruce Mitchener void* p = nullptr; 213f362be59SLouis Dionne try { 214b2577e5dSEric Fiselier p = ::operator new[](size, alignment); 215f362be59SLouis Dionne } catch (...) { 216b2577e5dSEric Fiselier } 217b2577e5dSEric Fiselier return p; 21831452655SLouis Dionne # endif 219b2577e5dSEric Fiselier } 220b2577e5dSEric Fiselier 22131452655SLouis Dionne _LIBCPP_WEAK void operator delete(void* ptr, std::align_val_t) noexcept { std::__libcpp_aligned_free(ptr); } 222b2577e5dSEric Fiselier 22331452655SLouis Dionne _LIBCPP_WEAK void operator delete(void* ptr, std::align_val_t alignment, const std::nothrow_t&) noexcept { 224b2577e5dSEric Fiselier ::operator delete(ptr, alignment); 225b2577e5dSEric Fiselier } 226b2577e5dSEric Fiselier 22731452655SLouis Dionne _LIBCPP_WEAK void operator delete(void* ptr, size_t, std::align_val_t alignment) noexcept { 22831452655SLouis Dionne ::operator delete(ptr, alignment); 22931452655SLouis Dionne } 230b2577e5dSEric Fiselier 23131452655SLouis Dionne _LIBCPP_WEAK void operator delete[](void* ptr, std::align_val_t alignment) noexcept { 23231452655SLouis Dionne ::operator delete(ptr, alignment); 23331452655SLouis Dionne } 234b2577e5dSEric Fiselier 23531452655SLouis Dionne _LIBCPP_WEAK void operator delete[](void* ptr, std::align_val_t alignment, const std::nothrow_t&) noexcept { 236b2577e5dSEric Fiselier ::operator delete[](ptr, alignment); 237b2577e5dSEric Fiselier } 238b2577e5dSEric Fiselier 23931452655SLouis Dionne _LIBCPP_WEAK void operator delete[](void* ptr, size_t, std::align_val_t alignment) noexcept { 24031452655SLouis Dionne ::operator delete[](ptr, alignment); 24131452655SLouis Dionne } 242b2577e5dSEric Fiselier 243ba87515fSNikolas Klauser #endif // _LIBCPP_HAS_LIBRARY_ALIGNED_ALLOCATION 244d53cf0fdSLouis Dionne // ------------------ END COPY ------------------ 245