240 lines · cpp
1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "__cxxabi_config.h"10#include "abort_message.h"11#include "include/aligned_alloc.h" // from libc++12#include "include/overridable_function.h" // from libc++13#include <cstddef>14#include <cstdlib>15#include <new>16 17// Perform a few sanity checks on libc++ and libc++abi macros to ensure that18// the code below can be an exact copy of the code in libcxx/src/new.cpp.19#if !defined(_THROW_BAD_ALLOC)20# error The _THROW_BAD_ALLOC macro should be already defined by libc++21#endif22 23#ifndef _LIBCPP_WEAK24# error The _LIBCPP_WEAK macro should be already defined by libc++25#endif26 27#if defined(_LIBCXXABI_NO_EXCEPTIONS) != !_LIBCPP_HAS_EXCEPTIONS28# error libc++ and libc++abi seem to disagree on whether exceptions are enabled29#endif30 31inline void __throw_bad_alloc_shim() {32#if _LIBCPP_HAS_EXCEPTIONS33 throw std::bad_alloc();34#else35 __abort_message("bad_alloc was thrown in -fno-exceptions mode");36#endif37}38 39#define _LIBCPP_ASSERT_SHIM(expr, str) \40 do { \41 if (!expr) \42 __abort_message(str); \43 } while (false)44 45// ------------------ BEGIN COPY ------------------46// Implement all new and delete operators as weak definitions47// in this shared library, so that they can be overridden by programs48// that define non-weak copies of the functions.49 50static void* operator_new_impl(std::size_t size) {51 if (size == 0)52 size = 1;53 void* p;54 while ((p = std::malloc(size)) == nullptr) {55 // If malloc fails and there is a new_handler,56 // call it to try free up memory.57 std::new_handler nh = std::get_new_handler();58 if (nh)59 nh();60 else61 break;62 }63 return p;64}65 66_LIBCPP_OVERRIDABLE_FUNCTION(void*, operator new, (std::size_t size)) _THROW_BAD_ALLOC {67 void* p = operator_new_impl(size);68 if (p == nullptr)69 __throw_bad_alloc_shim();70 return p;71}72 73_LIBCPP_WEAK void* operator new(size_t size, const std::nothrow_t&) noexcept {74#if !_LIBCPP_HAS_EXCEPTIONS75# if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION76 _LIBCPP_ASSERT_SHIM(77 (!std::__is_function_overridden < void*(std::size_t), &operator new>()),78 "libc++ was configured with exceptions disabled and `operator new(size_t)` has been overridden, "79 "but `operator new(size_t, nothrow_t)` has not been overridden. This is problematic because "80 "`operator new(size_t, nothrow_t)` must call `operator new(size_t)`, which will terminate in case "81 "it fails to allocate, making it impossible for `operator new(size_t, nothrow_t)` to fulfill its "82 "contract (since it should return nullptr upon failure). Please make sure you override "83 "`operator new(size_t, nothrow_t)` as well.");84# endif85 86 return operator_new_impl(size);87#else88 void* p = nullptr;89 try {90 p = ::operator new(size);91 } catch (...) {92 }93 return p;94#endif95}96 97_LIBCPP_OVERRIDABLE_FUNCTION(void*, operator new[], (size_t size)) _THROW_BAD_ALLOC { return ::operator new(size); }98 99_LIBCPP_WEAK void* operator new[](size_t size, const std::nothrow_t&) noexcept {100#if !_LIBCPP_HAS_EXCEPTIONS101# if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION102 _LIBCPP_ASSERT_SHIM(103 (!std::__is_function_overridden < void*(std::size_t), &operator new[]>()),104 "libc++ was configured with exceptions disabled and `operator new[](size_t)` has been overridden, "105 "but `operator new[](size_t, nothrow_t)` has not been overridden. This is problematic because "106 "`operator new[](size_t, nothrow_t)` must call `operator new[](size_t)`, which will terminate in case "107 "it fails to allocate, making it impossible for `operator new[](size_t, nothrow_t)` to fulfill its "108 "contract (since it should return nullptr upon failure). Please make sure you override "109 "`operator new[](size_t, nothrow_t)` as well.");110# endif111 112 return operator_new_impl(size);113#else114 void* p = nullptr;115 try {116 p = ::operator new[](size);117 } catch (...) {118 }119 return p;120#endif121}122 123_LIBCPP_WEAK void operator delete(void* ptr) noexcept { std::free(ptr); }124 125_LIBCPP_WEAK void operator delete(void* ptr, const std::nothrow_t&) noexcept { ::operator delete(ptr); }126 127_LIBCPP_WEAK void operator delete(void* ptr, size_t) noexcept { ::operator delete(ptr); }128 129_LIBCPP_WEAK void operator delete[](void* ptr) noexcept { ::operator delete(ptr); }130 131_LIBCPP_WEAK void operator delete[](void* ptr, const std::nothrow_t&) noexcept { ::operator delete[](ptr); }132 133_LIBCPP_WEAK void operator delete[](void* ptr, size_t) noexcept { ::operator delete[](ptr); }134 135#if _LIBCPP_HAS_LIBRARY_ALIGNED_ALLOCATION136 137static void* operator_new_aligned_impl(std::size_t size, std::align_val_t alignment) {138 if (size == 0)139 size = 1;140 if (static_cast<size_t>(alignment) < sizeof(void*))141 alignment = std::align_val_t(sizeof(void*));142 143 // Try allocating memory. If allocation fails and there is a new_handler,144 // call it to try free up memory, and try again until it succeeds, or until145 // the new_handler decides to terminate.146 void* p;147 while ((p = std::__libcpp_aligned_alloc(static_cast<std::size_t>(alignment), size)) == nullptr) {148 std::new_handler nh = std::get_new_handler();149 if (nh)150 nh();151 else152 break;153 }154 return p;155}156 157_LIBCPP_OVERRIDABLE_FUNCTION(void*, operator new, (std::size_t size, std::align_val_t alignment)) _THROW_BAD_ALLOC {158 void* p = operator_new_aligned_impl(size, alignment);159 if (p == nullptr)160 __throw_bad_alloc_shim();161 return p;162}163 164_LIBCPP_WEAK void* operator new(size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept {165# if !_LIBCPP_HAS_EXCEPTIONS166# if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION167 _LIBCPP_ASSERT_SHIM(168 (!std::__is_function_overridden < void*(std::size_t, std::align_val_t), &operator new>()),169 "libc++ was configured with exceptions disabled and `operator new(size_t, align_val_t)` has been overridden, "170 "but `operator new(size_t, align_val_t, nothrow_t)` has not been overridden. This is problematic because "171 "`operator new(size_t, align_val_t, nothrow_t)` must call `operator new(size_t, align_val_t)`, which will "172 "terminate in case it fails to allocate, making it impossible for `operator new(size_t, align_val_t, nothrow_t)` "173 "to fulfill its contract (since it should return nullptr upon failure). Please make sure you override "174 "`operator new(size_t, align_val_t, nothrow_t)` as well.");175# endif176 177 return operator_new_aligned_impl(size, alignment);178# else179 void* p = nullptr;180 try {181 p = ::operator new(size, alignment);182 } catch (...) {183 }184 return p;185# endif186}187 188_LIBCPP_OVERRIDABLE_FUNCTION(void*, operator new[], (size_t size, std::align_val_t alignment)) _THROW_BAD_ALLOC {189 return ::operator new(size, alignment);190}191 192_LIBCPP_WEAK void* operator new[](size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept {193# if !_LIBCPP_HAS_EXCEPTIONS194# if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION195 _LIBCPP_ASSERT_SHIM(196 (!std::__is_function_overridden < void*(std::size_t, std::align_val_t), &operator new[]>()),197 "libc++ was configured with exceptions disabled and `operator new[](size_t, align_val_t)` has been overridden, "198 "but `operator new[](size_t, align_val_t, nothrow_t)` has not been overridden. This is problematic because "199 "`operator new[](size_t, align_val_t, nothrow_t)` must call `operator new[](size_t, align_val_t)`, which will "200 "terminate in case it fails to allocate, making it impossible for `operator new[](size_t, align_val_t, "201 "nothrow_t)` to fulfill its contract (since it should return nullptr upon failure). Please make sure you "202 "override `operator new[](size_t, align_val_t, nothrow_t)` as well.");203# endif204 205 return operator_new_aligned_impl(size, alignment);206# else207 void* p = nullptr;208 try {209 p = ::operator new[](size, alignment);210 } catch (...) {211 }212 return p;213# endif214}215 216_LIBCPP_WEAK void operator delete(void* ptr, std::align_val_t) noexcept { std::__libcpp_aligned_free(ptr); }217 218_LIBCPP_WEAK void operator delete(void* ptr, std::align_val_t alignment, const std::nothrow_t&) noexcept {219 ::operator delete(ptr, alignment);220}221 222_LIBCPP_WEAK void operator delete(void* ptr, size_t, std::align_val_t alignment) noexcept {223 ::operator delete(ptr, alignment);224}225 226_LIBCPP_WEAK void operator delete[](void* ptr, std::align_val_t alignment) noexcept {227 ::operator delete(ptr, alignment);228}229 230_LIBCPP_WEAK void operator delete[](void* ptr, std::align_val_t alignment, const std::nothrow_t&) noexcept {231 ::operator delete[](ptr, alignment);232}233 234_LIBCPP_WEAK void operator delete[](void* ptr, size_t, std::align_val_t alignment) noexcept {235 ::operator delete[](ptr, alignment);236}237 238#endif // _LIBCPP_HAS_LIBRARY_ALIGNED_ALLOCATION239// ------------------ END COPY ------------------240