1349cc55cSDimitry Andric //===----------------------------------------------------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 9*7a6dacacSDimitry Andric #include "include/overridable_function.h" 1006c3fb27SDimitry Andric #include <__memory/aligned_alloc.h> 11*7a6dacacSDimitry Andric #include <cstddef> 1206c3fb27SDimitry Andric #include <cstdlib> 1381ad6265SDimitry Andric #include <new> 140b57cec5SDimitry Andric 1506c3fb27SDimitry Andric #if !defined(__GLIBCXX__) && !defined(_LIBCPP_ABI_VCRUNTIME) 160b57cec5SDimitry Andric 1706c3fb27SDimitry Andric // The code below is copied as-is into libc++abi's libcxxabi/src/stdlib_new_delete.cpp 1806c3fb27SDimitry Andric // file. The version in this file is the canonical one. 190b57cec5SDimitry Andric 20*7a6dacacSDimitry Andric inline void __throw_bad_alloc_shim() { std::__throw_bad_alloc(); } 21*7a6dacacSDimitry Andric 22*7a6dacacSDimitry Andric # define _LIBCPP_ASSERT_SHIM(expr, str) _LIBCPP_ASSERT(expr, str) 23*7a6dacacSDimitry Andric 2406c3fb27SDimitry Andric // ------------------ BEGIN COPY ------------------ 250b57cec5SDimitry Andric // Implement all new and delete operators as weak definitions 260b57cec5SDimitry Andric // in this shared library, so that they can be overridden by programs 270b57cec5SDimitry Andric // that define non-weak copies of the functions. 280b57cec5SDimitry Andric 29*7a6dacacSDimitry Andric static void* operator_new_impl(std::size_t size) { 300b57cec5SDimitry Andric if (size == 0) 310b57cec5SDimitry Andric size = 1; 320b57cec5SDimitry Andric void* p; 335f757f3fSDimitry Andric while ((p = std::malloc(size)) == nullptr) { 340b57cec5SDimitry Andric // If malloc fails and there is a new_handler, 350b57cec5SDimitry Andric // call it to try free up memory. 360b57cec5SDimitry Andric std::new_handler nh = std::get_new_handler(); 370b57cec5SDimitry Andric if (nh) 380b57cec5SDimitry Andric nh(); 390b57cec5SDimitry Andric else 400b57cec5SDimitry Andric break; 410b57cec5SDimitry Andric } 420b57cec5SDimitry Andric return p; 430b57cec5SDimitry Andric } 440b57cec5SDimitry Andric 45*7a6dacacSDimitry Andric _LIBCPP_MAKE_OVERRIDABLE_FUNCTION_DETECTABLE _LIBCPP_WEAK void* operator new(std::size_t size) _THROW_BAD_ALLOC { 465f757f3fSDimitry Andric void* p = operator_new_impl(size); 475f757f3fSDimitry Andric if (p == nullptr) 48*7a6dacacSDimitry Andric __throw_bad_alloc_shim(); 495f757f3fSDimitry Andric return p; 505f757f3fSDimitry Andric } 515f757f3fSDimitry Andric 525f757f3fSDimitry Andric _LIBCPP_WEAK void* operator new(size_t size, const std::nothrow_t&) noexcept { 53*7a6dacacSDimitry Andric # ifdef _LIBCPP_HAS_NO_EXCEPTIONS 54*7a6dacacSDimitry Andric # if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION 55*7a6dacacSDimitry Andric _LIBCPP_ASSERT_SHIM( 56*7a6dacacSDimitry Andric !std::__is_function_overridden(static_cast<void* (*)(std::size_t)>(&operator new)), 57*7a6dacacSDimitry Andric "libc++ was configured with exceptions disabled and `operator new(size_t)` has been overridden, " 58*7a6dacacSDimitry Andric "but `operator new(size_t, nothrow_t)` has not been overridden. This is problematic because " 59*7a6dacacSDimitry Andric "`operator new(size_t, nothrow_t)` must call `operator new(size_t)`, which will terminate in case " 60*7a6dacacSDimitry Andric "it fails to allocate, making it impossible for `operator new(size_t, nothrow_t)` to fulfill its " 61*7a6dacacSDimitry Andric "contract (since it should return nullptr upon failure). Please make sure you override " 62*7a6dacacSDimitry Andric "`operator new(size_t, nothrow_t)` as well."); 63*7a6dacacSDimitry Andric # endif 64*7a6dacacSDimitry Andric 65*7a6dacacSDimitry Andric return operator_new_impl(size); 66*7a6dacacSDimitry Andric # else 67e8d8bef9SDimitry Andric void* p = nullptr; 685f757f3fSDimitry Andric try { 690b57cec5SDimitry Andric p = ::operator new(size); 705f757f3fSDimitry Andric } catch (...) { 710b57cec5SDimitry Andric } 720b57cec5SDimitry Andric return p; 73*7a6dacacSDimitry Andric # endif 740b57cec5SDimitry Andric } 750b57cec5SDimitry Andric 76*7a6dacacSDimitry Andric _LIBCPP_MAKE_OVERRIDABLE_FUNCTION_DETECTABLE _LIBCPP_WEAK void* operator new[](size_t size) _THROW_BAD_ALLOC { 77*7a6dacacSDimitry Andric return ::operator new(size); 78*7a6dacacSDimitry Andric } 790b57cec5SDimitry Andric 805f757f3fSDimitry Andric _LIBCPP_WEAK void* operator new[](size_t size, const std::nothrow_t&) noexcept { 81*7a6dacacSDimitry Andric # ifdef _LIBCPP_HAS_NO_EXCEPTIONS 82*7a6dacacSDimitry Andric # if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION 83*7a6dacacSDimitry Andric _LIBCPP_ASSERT_SHIM( 84*7a6dacacSDimitry Andric !std::__is_function_overridden(static_cast<void* (*)(std::size_t)>(&operator new[])), 85*7a6dacacSDimitry Andric "libc++ was configured with exceptions disabled and `operator new[](size_t)` has been overridden, " 86*7a6dacacSDimitry Andric "but `operator new[](size_t, nothrow_t)` has not been overridden. This is problematic because " 87*7a6dacacSDimitry Andric "`operator new[](size_t, nothrow_t)` must call `operator new[](size_t)`, which will terminate in case " 88*7a6dacacSDimitry Andric "it fails to allocate, making it impossible for `operator new[](size_t, nothrow_t)` to fulfill its " 89*7a6dacacSDimitry Andric "contract (since it should return nullptr upon failure). Please make sure you override " 90*7a6dacacSDimitry Andric "`operator new[](size_t, nothrow_t)` as well."); 91*7a6dacacSDimitry Andric # endif 92*7a6dacacSDimitry Andric 93*7a6dacacSDimitry Andric return operator_new_impl(size); 94*7a6dacacSDimitry Andric # else 95e8d8bef9SDimitry Andric void* p = nullptr; 965f757f3fSDimitry Andric try { 970b57cec5SDimitry Andric p = ::operator new[](size); 985f757f3fSDimitry Andric } catch (...) { 990b57cec5SDimitry Andric } 1000b57cec5SDimitry Andric return p; 101*7a6dacacSDimitry Andric # endif 1020b57cec5SDimitry Andric } 1030b57cec5SDimitry Andric 1045f757f3fSDimitry Andric _LIBCPP_WEAK void operator delete(void* ptr) noexcept { std::free(ptr); } 1050b57cec5SDimitry Andric 1065f757f3fSDimitry Andric _LIBCPP_WEAK void operator delete(void* ptr, const std::nothrow_t&) noexcept { ::operator delete(ptr); } 1070b57cec5SDimitry Andric 1085f757f3fSDimitry Andric _LIBCPP_WEAK void operator delete(void* ptr, size_t) noexcept { ::operator delete(ptr); } 1090b57cec5SDimitry Andric 1105f757f3fSDimitry Andric _LIBCPP_WEAK void operator delete[](void* ptr) noexcept { ::operator delete(ptr); } 1110b57cec5SDimitry Andric 1125f757f3fSDimitry Andric _LIBCPP_WEAK void operator delete[](void* ptr, const std::nothrow_t&) noexcept { ::operator delete[](ptr); } 1130b57cec5SDimitry Andric 1145f757f3fSDimitry Andric _LIBCPP_WEAK void operator delete[](void* ptr, size_t) noexcept { ::operator delete[](ptr); } 1150b57cec5SDimitry Andric 1160b57cec5SDimitry Andric # if !defined(_LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION) 1170b57cec5SDimitry Andric 118*7a6dacacSDimitry Andric static void* operator_new_aligned_impl(std::size_t size, std::align_val_t alignment) { 1190b57cec5SDimitry Andric if (size == 0) 1200b57cec5SDimitry Andric size = 1; 1210b57cec5SDimitry Andric if (static_cast<size_t>(alignment) < sizeof(void*)) 1220b57cec5SDimitry Andric alignment = std::align_val_t(sizeof(void*)); 123e8d8bef9SDimitry Andric 124e8d8bef9SDimitry Andric // Try allocating memory. If allocation fails and there is a new_handler, 125e8d8bef9SDimitry Andric // call it to try free up memory, and try again until it succeeds, or until 126e8d8bef9SDimitry Andric // the new_handler decides to terminate. 1270b57cec5SDimitry Andric void* p; 1285f757f3fSDimitry Andric while ((p = std::__libcpp_aligned_alloc(static_cast<std::size_t>(alignment), size)) == nullptr) { 1290b57cec5SDimitry Andric std::new_handler nh = std::get_new_handler(); 1300b57cec5SDimitry Andric if (nh) 1310b57cec5SDimitry Andric nh(); 1325f757f3fSDimitry Andric else 1330b57cec5SDimitry Andric break; 1340b57cec5SDimitry Andric } 1350b57cec5SDimitry Andric return p; 1360b57cec5SDimitry Andric } 1370b57cec5SDimitry Andric 138*7a6dacacSDimitry Andric _LIBCPP_MAKE_OVERRIDABLE_FUNCTION_DETECTABLE _LIBCPP_WEAK void* 139*7a6dacacSDimitry Andric operator new(std::size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC { 1405f757f3fSDimitry Andric void* p = operator_new_aligned_impl(size, alignment); 1415f757f3fSDimitry Andric if (p == nullptr) 142*7a6dacacSDimitry Andric __throw_bad_alloc_shim(); 1435f757f3fSDimitry Andric return p; 1445f757f3fSDimitry Andric } 1455f757f3fSDimitry Andric 1465f757f3fSDimitry Andric _LIBCPP_WEAK void* operator new(size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept { 147*7a6dacacSDimitry Andric # ifdef _LIBCPP_HAS_NO_EXCEPTIONS 148*7a6dacacSDimitry Andric # if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION 149*7a6dacacSDimitry Andric _LIBCPP_ASSERT_SHIM( 150*7a6dacacSDimitry Andric !std::__is_function_overridden(static_cast<void* (*)(std::size_t, std::align_val_t)>(&operator new)), 151*7a6dacacSDimitry Andric "libc++ was configured with exceptions disabled and `operator new(size_t, align_val_t)` has been overridden, " 152*7a6dacacSDimitry Andric "but `operator new(size_t, align_val_t, nothrow_t)` has not been overridden. This is problematic because " 153*7a6dacacSDimitry Andric "`operator new(size_t, align_val_t, nothrow_t)` must call `operator new(size_t, align_val_t)`, which will " 154*7a6dacacSDimitry Andric "terminate in case it fails to allocate, making it impossible for `operator new(size_t, align_val_t, nothrow_t)` " 155*7a6dacacSDimitry Andric "to fulfill its contract (since it should return nullptr upon failure). Please make sure you override " 156*7a6dacacSDimitry Andric "`operator new(size_t, align_val_t, nothrow_t)` as well."); 157*7a6dacacSDimitry Andric # endif 158*7a6dacacSDimitry Andric 159*7a6dacacSDimitry Andric return operator_new_aligned_impl(size, alignment); 160*7a6dacacSDimitry Andric # else 161e8d8bef9SDimitry Andric void* p = nullptr; 1625f757f3fSDimitry Andric try { 1630b57cec5SDimitry Andric p = ::operator new(size, alignment); 1645f757f3fSDimitry Andric } catch (...) { 1650b57cec5SDimitry Andric } 1660b57cec5SDimitry Andric return p; 167*7a6dacacSDimitry Andric # endif 1680b57cec5SDimitry Andric } 1690b57cec5SDimitry Andric 170*7a6dacacSDimitry Andric _LIBCPP_MAKE_OVERRIDABLE_FUNCTION_DETECTABLE _LIBCPP_WEAK void* 171*7a6dacacSDimitry Andric operator new[](size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC { 1720b57cec5SDimitry Andric return ::operator new(size, alignment); 1730b57cec5SDimitry Andric } 1740b57cec5SDimitry Andric 1755f757f3fSDimitry Andric _LIBCPP_WEAK void* operator new[](size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept { 176*7a6dacacSDimitry Andric # ifdef _LIBCPP_HAS_NO_EXCEPTIONS 177*7a6dacacSDimitry Andric # if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION 178*7a6dacacSDimitry Andric _LIBCPP_ASSERT_SHIM( 179*7a6dacacSDimitry Andric !std::__is_function_overridden(static_cast<void* (*)(std::size_t, std::align_val_t)>(&operator new[])), 180*7a6dacacSDimitry Andric "libc++ was configured with exceptions disabled and `operator new[](size_t, align_val_t)` has been overridden, " 181*7a6dacacSDimitry Andric "but `operator new[](size_t, align_val_t, nothrow_t)` has not been overridden. This is problematic because " 182*7a6dacacSDimitry Andric "`operator new[](size_t, align_val_t, nothrow_t)` must call `operator new[](size_t, align_val_t)`, which will " 183*7a6dacacSDimitry Andric "terminate in case it fails to allocate, making it impossible for `operator new[](size_t, align_val_t, " 184*7a6dacacSDimitry Andric "nothrow_t)` to fulfill its contract (since it should return nullptr upon failure). Please make sure you " 185*7a6dacacSDimitry Andric "override " 186*7a6dacacSDimitry Andric "`operator new[](size_t, align_val_t, nothrow_t)` as well."); 187*7a6dacacSDimitry Andric # endif 188*7a6dacacSDimitry Andric 189*7a6dacacSDimitry Andric return operator_new_aligned_impl(size, alignment); 190*7a6dacacSDimitry Andric # else 191e8d8bef9SDimitry Andric void* p = nullptr; 1925f757f3fSDimitry Andric try { 1930b57cec5SDimitry Andric p = ::operator new[](size, alignment); 1945f757f3fSDimitry Andric } catch (...) { 1950b57cec5SDimitry Andric } 1960b57cec5SDimitry Andric return p; 197*7a6dacacSDimitry Andric # endif 1980b57cec5SDimitry Andric } 1990b57cec5SDimitry Andric 2005f757f3fSDimitry Andric _LIBCPP_WEAK void operator delete(void* ptr, std::align_val_t) noexcept { std::__libcpp_aligned_free(ptr); } 2010b57cec5SDimitry Andric 2025f757f3fSDimitry Andric _LIBCPP_WEAK void operator delete(void* ptr, std::align_val_t alignment, const std::nothrow_t&) noexcept { 2030b57cec5SDimitry Andric ::operator delete(ptr, alignment); 2040b57cec5SDimitry Andric } 2050b57cec5SDimitry Andric 2065f757f3fSDimitry Andric _LIBCPP_WEAK void operator delete(void* ptr, size_t, std::align_val_t alignment) noexcept { 2070b57cec5SDimitry Andric ::operator delete(ptr, alignment); 2080b57cec5SDimitry Andric } 2090b57cec5SDimitry Andric 2105f757f3fSDimitry Andric _LIBCPP_WEAK void operator delete[](void* ptr, std::align_val_t alignment) noexcept { 2110b57cec5SDimitry Andric ::operator delete(ptr, alignment); 2120b57cec5SDimitry Andric } 2130b57cec5SDimitry Andric 2145f757f3fSDimitry Andric _LIBCPP_WEAK void operator delete[](void* ptr, std::align_val_t alignment, const std::nothrow_t&) noexcept { 2150b57cec5SDimitry Andric ::operator delete[](ptr, alignment); 2160b57cec5SDimitry Andric } 2170b57cec5SDimitry Andric 2185f757f3fSDimitry Andric _LIBCPP_WEAK void operator delete[](void* ptr, size_t, std::align_val_t alignment) noexcept { 2190b57cec5SDimitry Andric ::operator delete[](ptr, alignment); 2200b57cec5SDimitry Andric } 2210b57cec5SDimitry Andric 2220b57cec5SDimitry Andric # endif // !_LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION 22306c3fb27SDimitry Andric // ------------------ END COPY ------------------ 22406c3fb27SDimitry Andric 22506c3fb27SDimitry Andric #endif // !__GLIBCXX__ && !_LIBCPP_ABI_VCRUNTIME 226