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
97a6dacacSDimitry Andric #include "include/overridable_function.h"
10*0fca6ea1SDimitry Andric #include <__assert>
1106c3fb27SDimitry Andric #include <__memory/aligned_alloc.h>
127a6dacacSDimitry Andric #include <cstddef>
1306c3fb27SDimitry Andric #include <cstdlib>
1481ad6265SDimitry Andric #include <new>
150b57cec5SDimitry Andric
1606c3fb27SDimitry Andric #if !defined(__GLIBCXX__) && !defined(_LIBCPP_ABI_VCRUNTIME)
170b57cec5SDimitry Andric
1806c3fb27SDimitry Andric // The code below is copied as-is into libc++abi's libcxxabi/src/stdlib_new_delete.cpp
1906c3fb27SDimitry Andric // file. The version in this file is the canonical one.
200b57cec5SDimitry Andric
__throw_bad_alloc_shim()217a6dacacSDimitry Andric inline void __throw_bad_alloc_shim() { std::__throw_bad_alloc(); }
227a6dacacSDimitry Andric
237a6dacacSDimitry Andric # define _LIBCPP_ASSERT_SHIM(expr, str) _LIBCPP_ASSERT(expr, str)
247a6dacacSDimitry Andric
2506c3fb27SDimitry Andric // ------------------ BEGIN COPY ------------------
260b57cec5SDimitry Andric // Implement all new and delete operators as weak definitions
270b57cec5SDimitry Andric // in this shared library, so that they can be overridden by programs
280b57cec5SDimitry Andric // that define non-weak copies of the functions.
290b57cec5SDimitry Andric
operator_new_impl(std::size_t size)307a6dacacSDimitry Andric static void* operator_new_impl(std::size_t size) {
310b57cec5SDimitry Andric if (size == 0)
320b57cec5SDimitry Andric size = 1;
330b57cec5SDimitry Andric void* p;
345f757f3fSDimitry Andric while ((p = std::malloc(size)) == nullptr) {
350b57cec5SDimitry Andric // If malloc fails and there is a new_handler,
360b57cec5SDimitry Andric // call it to try free up memory.
370b57cec5SDimitry Andric std::new_handler nh = std::get_new_handler();
380b57cec5SDimitry Andric if (nh)
390b57cec5SDimitry Andric nh();
400b57cec5SDimitry Andric else
410b57cec5SDimitry Andric break;
420b57cec5SDimitry Andric }
430b57cec5SDimitry Andric return p;
440b57cec5SDimitry Andric }
450b57cec5SDimitry Andric
operator new(std::size_t size)467a6dacacSDimitry Andric _LIBCPP_MAKE_OVERRIDABLE_FUNCTION_DETECTABLE _LIBCPP_WEAK void* operator new(std::size_t size) _THROW_BAD_ALLOC {
475f757f3fSDimitry Andric void* p = operator_new_impl(size);
485f757f3fSDimitry Andric if (p == nullptr)
497a6dacacSDimitry Andric __throw_bad_alloc_shim();
505f757f3fSDimitry Andric return p;
515f757f3fSDimitry Andric }
525f757f3fSDimitry Andric
operator new(size_t size,const std::nothrow_t &)535f757f3fSDimitry Andric _LIBCPP_WEAK void* operator new(size_t size, const std::nothrow_t&) noexcept {
547a6dacacSDimitry Andric # ifdef _LIBCPP_HAS_NO_EXCEPTIONS
557a6dacacSDimitry Andric # if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION
567a6dacacSDimitry Andric _LIBCPP_ASSERT_SHIM(
577a6dacacSDimitry Andric !std::__is_function_overridden(static_cast<void* (*)(std::size_t)>(&operator new)),
587a6dacacSDimitry Andric "libc++ was configured with exceptions disabled and `operator new(size_t)` has been overridden, "
597a6dacacSDimitry Andric "but `operator new(size_t, nothrow_t)` has not been overridden. This is problematic because "
607a6dacacSDimitry Andric "`operator new(size_t, nothrow_t)` must call `operator new(size_t)`, which will terminate in case "
617a6dacacSDimitry Andric "it fails to allocate, making it impossible for `operator new(size_t, nothrow_t)` to fulfill its "
627a6dacacSDimitry Andric "contract (since it should return nullptr upon failure). Please make sure you override "
637a6dacacSDimitry Andric "`operator new(size_t, nothrow_t)` as well.");
647a6dacacSDimitry Andric # endif
657a6dacacSDimitry Andric
667a6dacacSDimitry Andric return operator_new_impl(size);
677a6dacacSDimitry Andric # else
68e8d8bef9SDimitry Andric void* p = nullptr;
695f757f3fSDimitry Andric try {
700b57cec5SDimitry Andric p = ::operator new(size);
715f757f3fSDimitry Andric } catch (...) {
720b57cec5SDimitry Andric }
730b57cec5SDimitry Andric return p;
747a6dacacSDimitry Andric # endif
750b57cec5SDimitry Andric }
760b57cec5SDimitry Andric
operator new[](size_t size)777a6dacacSDimitry Andric _LIBCPP_MAKE_OVERRIDABLE_FUNCTION_DETECTABLE _LIBCPP_WEAK void* operator new[](size_t size) _THROW_BAD_ALLOC {
787a6dacacSDimitry Andric return ::operator new(size);
797a6dacacSDimitry Andric }
800b57cec5SDimitry Andric
operator new[](size_t size,const std::nothrow_t &)815f757f3fSDimitry Andric _LIBCPP_WEAK void* operator new[](size_t size, const std::nothrow_t&) noexcept {
827a6dacacSDimitry Andric # ifdef _LIBCPP_HAS_NO_EXCEPTIONS
837a6dacacSDimitry Andric # if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION
847a6dacacSDimitry Andric _LIBCPP_ASSERT_SHIM(
857a6dacacSDimitry Andric !std::__is_function_overridden(static_cast<void* (*)(std::size_t)>(&operator new[])),
867a6dacacSDimitry Andric "libc++ was configured with exceptions disabled and `operator new[](size_t)` has been overridden, "
877a6dacacSDimitry Andric "but `operator new[](size_t, nothrow_t)` has not been overridden. This is problematic because "
887a6dacacSDimitry Andric "`operator new[](size_t, nothrow_t)` must call `operator new[](size_t)`, which will terminate in case "
897a6dacacSDimitry Andric "it fails to allocate, making it impossible for `operator new[](size_t, nothrow_t)` to fulfill its "
907a6dacacSDimitry Andric "contract (since it should return nullptr upon failure). Please make sure you override "
917a6dacacSDimitry Andric "`operator new[](size_t, nothrow_t)` as well.");
927a6dacacSDimitry Andric # endif
937a6dacacSDimitry Andric
947a6dacacSDimitry Andric return operator_new_impl(size);
957a6dacacSDimitry Andric # else
96e8d8bef9SDimitry Andric void* p = nullptr;
975f757f3fSDimitry Andric try {
980b57cec5SDimitry Andric p = ::operator new[](size);
995f757f3fSDimitry Andric } catch (...) {
1000b57cec5SDimitry Andric }
1010b57cec5SDimitry Andric return p;
1027a6dacacSDimitry Andric # endif
1030b57cec5SDimitry Andric }
1040b57cec5SDimitry Andric
operator delete(void * ptr)1055f757f3fSDimitry Andric _LIBCPP_WEAK void operator delete(void* ptr) noexcept { std::free(ptr); }
1060b57cec5SDimitry Andric
operator delete(void * ptr,const std::nothrow_t &)1075f757f3fSDimitry Andric _LIBCPP_WEAK void operator delete(void* ptr, const std::nothrow_t&) noexcept { ::operator delete(ptr); }
1080b57cec5SDimitry Andric
operator delete(void * ptr,size_t)1095f757f3fSDimitry Andric _LIBCPP_WEAK void operator delete(void* ptr, size_t) noexcept { ::operator delete(ptr); }
1100b57cec5SDimitry Andric
operator delete[](void * ptr)1115f757f3fSDimitry Andric _LIBCPP_WEAK void operator delete[](void* ptr) noexcept { ::operator delete(ptr); }
1120b57cec5SDimitry Andric
operator delete[](void * ptr,const std::nothrow_t &)1135f757f3fSDimitry Andric _LIBCPP_WEAK void operator delete[](void* ptr, const std::nothrow_t&) noexcept { ::operator delete[](ptr); }
1140b57cec5SDimitry Andric
operator delete[](void * ptr,size_t)1155f757f3fSDimitry Andric _LIBCPP_WEAK void operator delete[](void* ptr, size_t) noexcept { ::operator delete[](ptr); }
1160b57cec5SDimitry Andric
1170b57cec5SDimitry Andric # if !defined(_LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION)
1180b57cec5SDimitry Andric
operator_new_aligned_impl(std::size_t size,std::align_val_t alignment)1197a6dacacSDimitry Andric static void* operator_new_aligned_impl(std::size_t size, std::align_val_t alignment) {
1200b57cec5SDimitry Andric if (size == 0)
1210b57cec5SDimitry Andric size = 1;
1220b57cec5SDimitry Andric if (static_cast<size_t>(alignment) < sizeof(void*))
1230b57cec5SDimitry Andric alignment = std::align_val_t(sizeof(void*));
124e8d8bef9SDimitry Andric
125e8d8bef9SDimitry Andric // Try allocating memory. If allocation fails and there is a new_handler,
126e8d8bef9SDimitry Andric // call it to try free up memory, and try again until it succeeds, or until
127e8d8bef9SDimitry Andric // the new_handler decides to terminate.
1280b57cec5SDimitry Andric void* p;
1295f757f3fSDimitry Andric while ((p = std::__libcpp_aligned_alloc(static_cast<std::size_t>(alignment), size)) == nullptr) {
1300b57cec5SDimitry Andric std::new_handler nh = std::get_new_handler();
1310b57cec5SDimitry Andric if (nh)
1320b57cec5SDimitry Andric nh();
1335f757f3fSDimitry Andric else
1340b57cec5SDimitry Andric break;
1350b57cec5SDimitry Andric }
1360b57cec5SDimitry Andric return p;
1370b57cec5SDimitry Andric }
1380b57cec5SDimitry Andric
1397a6dacacSDimitry Andric _LIBCPP_MAKE_OVERRIDABLE_FUNCTION_DETECTABLE _LIBCPP_WEAK void*
operator new(std::size_t size,std::align_val_t alignment)1407a6dacacSDimitry Andric operator new(std::size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC {
1415f757f3fSDimitry Andric void* p = operator_new_aligned_impl(size, alignment);
1425f757f3fSDimitry Andric if (p == nullptr)
1437a6dacacSDimitry Andric __throw_bad_alloc_shim();
1445f757f3fSDimitry Andric return p;
1455f757f3fSDimitry Andric }
1465f757f3fSDimitry Andric
operator new(size_t size,std::align_val_t alignment,const std::nothrow_t &)1475f757f3fSDimitry Andric _LIBCPP_WEAK void* operator new(size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept {
1487a6dacacSDimitry Andric # ifdef _LIBCPP_HAS_NO_EXCEPTIONS
1497a6dacacSDimitry Andric # if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION
1507a6dacacSDimitry Andric _LIBCPP_ASSERT_SHIM(
1517a6dacacSDimitry Andric !std::__is_function_overridden(static_cast<void* (*)(std::size_t, std::align_val_t)>(&operator new)),
1527a6dacacSDimitry Andric "libc++ was configured with exceptions disabled and `operator new(size_t, align_val_t)` has been overridden, "
1537a6dacacSDimitry Andric "but `operator new(size_t, align_val_t, nothrow_t)` has not been overridden. This is problematic because "
1547a6dacacSDimitry Andric "`operator new(size_t, align_val_t, nothrow_t)` must call `operator new(size_t, align_val_t)`, which will "
1557a6dacacSDimitry Andric "terminate in case it fails to allocate, making it impossible for `operator new(size_t, align_val_t, nothrow_t)` "
1567a6dacacSDimitry Andric "to fulfill its contract (since it should return nullptr upon failure). Please make sure you override "
1577a6dacacSDimitry Andric "`operator new(size_t, align_val_t, nothrow_t)` as well.");
1587a6dacacSDimitry Andric # endif
1597a6dacacSDimitry Andric
1607a6dacacSDimitry Andric return operator_new_aligned_impl(size, alignment);
1617a6dacacSDimitry Andric # else
162e8d8bef9SDimitry Andric void* p = nullptr;
1635f757f3fSDimitry Andric try {
1640b57cec5SDimitry Andric p = ::operator new(size, alignment);
1655f757f3fSDimitry Andric } catch (...) {
1660b57cec5SDimitry Andric }
1670b57cec5SDimitry Andric return p;
1687a6dacacSDimitry Andric # endif
1690b57cec5SDimitry Andric }
1700b57cec5SDimitry Andric
1717a6dacacSDimitry Andric _LIBCPP_MAKE_OVERRIDABLE_FUNCTION_DETECTABLE _LIBCPP_WEAK void*
operator new[](size_t size,std::align_val_t alignment)1727a6dacacSDimitry Andric operator new[](size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC {
1730b57cec5SDimitry Andric return ::operator new(size, alignment);
1740b57cec5SDimitry Andric }
1750b57cec5SDimitry Andric
operator new[](size_t size,std::align_val_t alignment,const std::nothrow_t &)1765f757f3fSDimitry Andric _LIBCPP_WEAK void* operator new[](size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept {
1777a6dacacSDimitry Andric # ifdef _LIBCPP_HAS_NO_EXCEPTIONS
1787a6dacacSDimitry Andric # if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION
1797a6dacacSDimitry Andric _LIBCPP_ASSERT_SHIM(
1807a6dacacSDimitry Andric !std::__is_function_overridden(static_cast<void* (*)(std::size_t, std::align_val_t)>(&operator new[])),
1817a6dacacSDimitry Andric "libc++ was configured with exceptions disabled and `operator new[](size_t, align_val_t)` has been overridden, "
1827a6dacacSDimitry Andric "but `operator new[](size_t, align_val_t, nothrow_t)` has not been overridden. This is problematic because "
1837a6dacacSDimitry Andric "`operator new[](size_t, align_val_t, nothrow_t)` must call `operator new[](size_t, align_val_t)`, which will "
1847a6dacacSDimitry Andric "terminate in case it fails to allocate, making it impossible for `operator new[](size_t, align_val_t, "
1857a6dacacSDimitry Andric "nothrow_t)` to fulfill its contract (since it should return nullptr upon failure). Please make sure you "
1867a6dacacSDimitry Andric "override "
1877a6dacacSDimitry Andric "`operator new[](size_t, align_val_t, nothrow_t)` as well.");
1887a6dacacSDimitry Andric # endif
1897a6dacacSDimitry Andric
1907a6dacacSDimitry Andric return operator_new_aligned_impl(size, alignment);
1917a6dacacSDimitry Andric # else
192e8d8bef9SDimitry Andric void* p = nullptr;
1935f757f3fSDimitry Andric try {
1940b57cec5SDimitry Andric p = ::operator new[](size, alignment);
1955f757f3fSDimitry Andric } catch (...) {
1960b57cec5SDimitry Andric }
1970b57cec5SDimitry Andric return p;
1987a6dacacSDimitry Andric # endif
1990b57cec5SDimitry Andric }
2000b57cec5SDimitry Andric
operator delete(void * ptr,std::align_val_t)2015f757f3fSDimitry Andric _LIBCPP_WEAK void operator delete(void* ptr, std::align_val_t) noexcept { std::__libcpp_aligned_free(ptr); }
2020b57cec5SDimitry Andric
operator delete(void * ptr,std::align_val_t alignment,const std::nothrow_t &)2035f757f3fSDimitry Andric _LIBCPP_WEAK void operator delete(void* ptr, std::align_val_t alignment, const std::nothrow_t&) noexcept {
2040b57cec5SDimitry Andric ::operator delete(ptr, alignment);
2050b57cec5SDimitry Andric }
2060b57cec5SDimitry Andric
operator delete(void * ptr,size_t,std::align_val_t alignment)2075f757f3fSDimitry Andric _LIBCPP_WEAK void operator delete(void* ptr, size_t, std::align_val_t alignment) noexcept {
2080b57cec5SDimitry Andric ::operator delete(ptr, alignment);
2090b57cec5SDimitry Andric }
2100b57cec5SDimitry Andric
operator delete[](void * ptr,std::align_val_t alignment)2115f757f3fSDimitry Andric _LIBCPP_WEAK void operator delete[](void* ptr, std::align_val_t alignment) noexcept {
2120b57cec5SDimitry Andric ::operator delete(ptr, alignment);
2130b57cec5SDimitry Andric }
2140b57cec5SDimitry Andric
operator delete[](void * ptr,std::align_val_t alignment,const std::nothrow_t &)2155f757f3fSDimitry Andric _LIBCPP_WEAK void operator delete[](void* ptr, std::align_val_t alignment, const std::nothrow_t&) noexcept {
2160b57cec5SDimitry Andric ::operator delete[](ptr, alignment);
2170b57cec5SDimitry Andric }
2180b57cec5SDimitry Andric
operator delete[](void * ptr,size_t,std::align_val_t alignment)2195f757f3fSDimitry Andric _LIBCPP_WEAK void operator delete[](void* ptr, size_t, std::align_val_t alignment) noexcept {
2200b57cec5SDimitry Andric ::operator delete[](ptr, alignment);
2210b57cec5SDimitry Andric }
2220b57cec5SDimitry Andric
2230b57cec5SDimitry Andric # endif // !_LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION
22406c3fb27SDimitry Andric // ------------------ END COPY ------------------
22506c3fb27SDimitry Andric
22606c3fb27SDimitry Andric #endif // !__GLIBCXX__ && !_LIBCPP_ABI_VCRUNTIME
227