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"
1006c3fb27SDimitry Andric #include <__memory/aligned_alloc.h>
117a6dacacSDimitry 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 
__throw_bad_alloc_shim()207a6dacacSDimitry Andric inline void __throw_bad_alloc_shim() { std::__throw_bad_alloc(); }
217a6dacacSDimitry Andric 
227a6dacacSDimitry Andric #  define _LIBCPP_ASSERT_SHIM(expr, str) _LIBCPP_ASSERT(expr, str)
237a6dacacSDimitry 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 
operator_new_impl(std::size_t size)297a6dacacSDimitry 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 
operator new(std::size_t size)457a6dacacSDimitry 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)
487a6dacacSDimitry Andric     __throw_bad_alloc_shim();
495f757f3fSDimitry Andric   return p;
505f757f3fSDimitry Andric }
515f757f3fSDimitry Andric 
operator new(size_t size,const std::nothrow_t &)525f757f3fSDimitry Andric _LIBCPP_WEAK void* operator new(size_t size, const std::nothrow_t&) noexcept {
537a6dacacSDimitry Andric #  ifdef _LIBCPP_HAS_NO_EXCEPTIONS
547a6dacacSDimitry Andric #    if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION
557a6dacacSDimitry Andric   _LIBCPP_ASSERT_SHIM(
567a6dacacSDimitry Andric       !std::__is_function_overridden(static_cast<void* (*)(std::size_t)>(&operator new)),
577a6dacacSDimitry Andric       "libc++ was configured with exceptions disabled and `operator new(size_t)` has been overridden, "
587a6dacacSDimitry Andric       "but `operator new(size_t, nothrow_t)` has not been overridden. This is problematic because "
597a6dacacSDimitry Andric       "`operator new(size_t, nothrow_t)` must call `operator new(size_t)`, which will terminate in case "
607a6dacacSDimitry Andric       "it fails to allocate, making it impossible for `operator new(size_t, nothrow_t)` to fulfill its "
617a6dacacSDimitry Andric       "contract (since it should return nullptr upon failure). Please make sure you override "
627a6dacacSDimitry Andric       "`operator new(size_t, nothrow_t)` as well.");
637a6dacacSDimitry Andric #    endif
647a6dacacSDimitry Andric 
657a6dacacSDimitry Andric   return operator_new_impl(size);
667a6dacacSDimitry 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;
737a6dacacSDimitry Andric #  endif
740b57cec5SDimitry Andric }
750b57cec5SDimitry Andric 
operator new[](size_t size)767a6dacacSDimitry Andric _LIBCPP_MAKE_OVERRIDABLE_FUNCTION_DETECTABLE _LIBCPP_WEAK void* operator new[](size_t size) _THROW_BAD_ALLOC {
777a6dacacSDimitry Andric   return ::operator new(size);
787a6dacacSDimitry Andric }
790b57cec5SDimitry Andric 
operator new[](size_t size,const std::nothrow_t &)805f757f3fSDimitry Andric _LIBCPP_WEAK void* operator new[](size_t size, const std::nothrow_t&) noexcept {
817a6dacacSDimitry Andric #  ifdef _LIBCPP_HAS_NO_EXCEPTIONS
827a6dacacSDimitry Andric #    if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION
837a6dacacSDimitry Andric   _LIBCPP_ASSERT_SHIM(
847a6dacacSDimitry Andric       !std::__is_function_overridden(static_cast<void* (*)(std::size_t)>(&operator new[])),
857a6dacacSDimitry Andric       "libc++ was configured with exceptions disabled and `operator new[](size_t)` has been overridden, "
867a6dacacSDimitry Andric       "but `operator new[](size_t, nothrow_t)` has not been overridden. This is problematic because "
877a6dacacSDimitry Andric       "`operator new[](size_t, nothrow_t)` must call `operator new[](size_t)`, which will terminate in case "
887a6dacacSDimitry Andric       "it fails to allocate, making it impossible for `operator new[](size_t, nothrow_t)` to fulfill its "
897a6dacacSDimitry Andric       "contract (since it should return nullptr upon failure). Please make sure you override "
907a6dacacSDimitry Andric       "`operator new[](size_t, nothrow_t)` as well.");
917a6dacacSDimitry Andric #    endif
927a6dacacSDimitry Andric 
937a6dacacSDimitry Andric   return operator_new_impl(size);
947a6dacacSDimitry 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;
1017a6dacacSDimitry Andric #  endif
1020b57cec5SDimitry Andric }
1030b57cec5SDimitry Andric 
operator delete(void * ptr)1045f757f3fSDimitry Andric _LIBCPP_WEAK void operator delete(void* ptr) noexcept { std::free(ptr); }
1050b57cec5SDimitry Andric 
operator delete(void * ptr,const std::nothrow_t &)1065f757f3fSDimitry Andric _LIBCPP_WEAK void operator delete(void* ptr, const std::nothrow_t&) noexcept { ::operator delete(ptr); }
1070b57cec5SDimitry Andric 
operator delete(void * ptr,size_t)1085f757f3fSDimitry Andric _LIBCPP_WEAK void operator delete(void* ptr, size_t) noexcept { ::operator delete(ptr); }
1090b57cec5SDimitry Andric 
operator delete[](void * ptr)1105f757f3fSDimitry Andric _LIBCPP_WEAK void operator delete[](void* ptr) noexcept { ::operator delete(ptr); }
1110b57cec5SDimitry Andric 
operator delete[](void * ptr,const std::nothrow_t &)1125f757f3fSDimitry Andric _LIBCPP_WEAK void operator delete[](void* ptr, const std::nothrow_t&) noexcept { ::operator delete[](ptr); }
1130b57cec5SDimitry Andric 
operator delete[](void * ptr,size_t)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 
operator_new_aligned_impl(std::size_t size,std::align_val_t alignment)1187a6dacacSDimitry 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 
1387a6dacacSDimitry Andric _LIBCPP_MAKE_OVERRIDABLE_FUNCTION_DETECTABLE _LIBCPP_WEAK void*
operator new(std::size_t size,std::align_val_t alignment)1397a6dacacSDimitry 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)
1427a6dacacSDimitry Andric     __throw_bad_alloc_shim();
1435f757f3fSDimitry Andric   return p;
1445f757f3fSDimitry Andric }
1455f757f3fSDimitry Andric 
operator new(size_t size,std::align_val_t alignment,const std::nothrow_t &)1465f757f3fSDimitry Andric _LIBCPP_WEAK void* operator new(size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept {
1477a6dacacSDimitry Andric #    ifdef _LIBCPP_HAS_NO_EXCEPTIONS
1487a6dacacSDimitry Andric #      if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION
1497a6dacacSDimitry Andric   _LIBCPP_ASSERT_SHIM(
1507a6dacacSDimitry Andric       !std::__is_function_overridden(static_cast<void* (*)(std::size_t, std::align_val_t)>(&operator new)),
1517a6dacacSDimitry Andric       "libc++ was configured with exceptions disabled and `operator new(size_t, align_val_t)` has been overridden, "
1527a6dacacSDimitry Andric       "but `operator new(size_t, align_val_t, nothrow_t)` has not been overridden. This is problematic because "
1537a6dacacSDimitry Andric       "`operator new(size_t, align_val_t, nothrow_t)` must call `operator new(size_t, align_val_t)`, which will "
1547a6dacacSDimitry Andric       "terminate in case it fails to allocate, making it impossible for `operator new(size_t, align_val_t, nothrow_t)` "
1557a6dacacSDimitry Andric       "to fulfill its contract (since it should return nullptr upon failure). Please make sure you override "
1567a6dacacSDimitry Andric       "`operator new(size_t, align_val_t, nothrow_t)` as well.");
1577a6dacacSDimitry Andric #      endif
1587a6dacacSDimitry Andric 
1597a6dacacSDimitry Andric   return operator_new_aligned_impl(size, alignment);
1607a6dacacSDimitry 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;
1677a6dacacSDimitry Andric #    endif
1680b57cec5SDimitry Andric }
1690b57cec5SDimitry Andric 
1707a6dacacSDimitry Andric _LIBCPP_MAKE_OVERRIDABLE_FUNCTION_DETECTABLE _LIBCPP_WEAK void*
operator new[](size_t size,std::align_val_t alignment)1717a6dacacSDimitry 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 
operator new[](size_t size,std::align_val_t alignment,const std::nothrow_t &)1755f757f3fSDimitry Andric _LIBCPP_WEAK void* operator new[](size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept {
1767a6dacacSDimitry Andric #    ifdef _LIBCPP_HAS_NO_EXCEPTIONS
1777a6dacacSDimitry Andric #      if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION
1787a6dacacSDimitry Andric   _LIBCPP_ASSERT_SHIM(
1797a6dacacSDimitry Andric       !std::__is_function_overridden(static_cast<void* (*)(std::size_t, std::align_val_t)>(&operator new[])),
1807a6dacacSDimitry Andric       "libc++ was configured with exceptions disabled and `operator new[](size_t, align_val_t)` has been overridden, "
1817a6dacacSDimitry Andric       "but `operator new[](size_t, align_val_t, nothrow_t)` has not been overridden. This is problematic because "
1827a6dacacSDimitry Andric       "`operator new[](size_t, align_val_t, nothrow_t)` must call `operator new[](size_t, align_val_t)`, which will "
1837a6dacacSDimitry Andric       "terminate in case it fails to allocate, making it impossible for `operator new[](size_t, align_val_t, "
1847a6dacacSDimitry Andric       "nothrow_t)` to fulfill its contract (since it should return nullptr upon failure). Please make sure you "
1857a6dacacSDimitry Andric       "override "
1867a6dacacSDimitry Andric       "`operator new[](size_t, align_val_t, nothrow_t)` as well.");
1877a6dacacSDimitry Andric #      endif
1887a6dacacSDimitry Andric 
1897a6dacacSDimitry Andric   return operator_new_aligned_impl(size, alignment);
1907a6dacacSDimitry 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;
1977a6dacacSDimitry Andric #    endif
1980b57cec5SDimitry Andric }
1990b57cec5SDimitry Andric 
operator delete(void * ptr,std::align_val_t)2005f757f3fSDimitry Andric _LIBCPP_WEAK void operator delete(void* ptr, std::align_val_t) noexcept { std::__libcpp_aligned_free(ptr); }
2010b57cec5SDimitry Andric 
operator delete(void * ptr,std::align_val_t alignment,const std::nothrow_t &)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 
operator delete(void * ptr,size_t,std::align_val_t alignment)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 
operator delete[](void * ptr,std::align_val_t alignment)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 
operator delete[](void * ptr,std::align_val_t alignment,const std::nothrow_t &)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 
operator delete[](void * ptr,size_t,std::align_val_t alignment)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