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-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "__cxxabi_config.h"
10#include "abort_message.h"
11#include "include/overridable_function.h" // from libc++
12#include <__memory/aligned_alloc.h>
13#include <cstddef>
14#include <cstdlib>
15#include <new>
16
17// Perform a few sanity checks on libc++ and libc++abi macros to ensure that
18// 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#endif
22
23#ifndef _LIBCPP_WEAK
24# error The _LIBCPP_WEAK macro should be already defined by libc++
25#endif
26
27#if defined(_LIBCXXABI_NO_EXCEPTIONS) != defined(_LIBCPP_HAS_NO_EXCEPTIONS)
28# error libc++ and libc++abi seem to disagree on whether exceptions are enabled
29#endif
30
31inline void __throw_bad_alloc_shim() {
32#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
33 throw std::bad_alloc();
34#else
35 abort_message("bad_alloc was thrown in -fno-exceptions mode");
36#endif
37}
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 definitions
47// in this shared library, so that they can be overridden by programs
48// 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: 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 else
61 break;
62 }
63 return p;
64}
65
66_LIBCPP_MAKE_OVERRIDABLE_FUNCTION_DETECTABLE _LIBCPP_WEAK 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#ifdef _LIBCPP_HAS_NO_EXCEPTIONS
75# if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION
76 _LIBCPP_ASSERT_SHIM(
77 !std::__is_function_overridden(static_cast<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# endif
85
86 return operator_new_impl(size);
87#else
88 void* p = nullptr;
89 try {
90 p = ::operator new(size);
91 } catch (...) {
92 }
93 return p;
94#endif
95}
96
97_LIBCPP_MAKE_OVERRIDABLE_FUNCTION_DETECTABLE _LIBCPP_WEAK void* operator new[](size_t size) _THROW_BAD_ALLOC {
98 return ::operator new(size);
99}
100
101_LIBCPP_WEAK void* operator new[](size_t size, const std::nothrow_t&) noexcept {
102#ifdef _LIBCPP_HAS_NO_EXCEPTIONS
103# if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION
104 _LIBCPP_ASSERT_SHIM(
105 !std::__is_function_overridden(static_cast<void* (*)(std::size_t)>(&operator new[])),
106 "libc++ was configured with exceptions disabled and `operator new[](size_t)` has been overridden, "
107 "but `operator new[](size_t, nothrow_t)` has not been overridden. This is problematic because "
108 "`operator new[](size_t, nothrow_t)` must call `operator new[](size_t)`, which will terminate in case "
109 "it fails to allocate, making it impossible for `operator new[](size_t, nothrow_t)` to fulfill its "
110 "contract (since it should return nullptr upon failure). Please make sure you override "
111 "`operator new[](size_t, nothrow_t)` as well.");
112# endif
113
114 return operator_new_impl(size);
115#else
116 void* p = nullptr;
117 try {
118 p = ::operator new[](size);
119 } catch (...) {
120 }
121 return p;
122#endif
123}
124
125_LIBCPP_WEAK void operator delete(void* ptr) noexcept { std::free(ptr); }
126
127_LIBCPP_WEAK void operator delete(void* ptr, const std::nothrow_t&) noexcept { ::operator delete(ptr); }
128
129_LIBCPP_WEAK void operator delete(void* ptr, size_t) noexcept { ::operator delete(ptr); }
130
131_LIBCPP_WEAK void operator delete[](void* ptr) noexcept { ::operator delete(ptr); }
132
133_LIBCPP_WEAK void operator delete[](void* ptr, const std::nothrow_t&) noexcept { ::operator delete[](ptr); }
134
135_LIBCPP_WEAK void operator delete[](void* ptr, size_t) noexcept { ::operator delete[](ptr); }
136
137#if !defined(_LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION)
138
139static void* operator_new_aligned_impl(std::size_t size, std::align_val_t alignment) {
140 if (size == 0)
141 size = 1;
142 if (static_cast<size_t>(alignment) < sizeof(void*))
143 alignment = std::align_val_t(sizeof(void*));
144
145 // Try allocating memory. If allocation fails and there is a new_handler,
146 // call it to try free up memory, and try again until it succeeds, or until
147 // the new_handler decides to terminate.
148 void* p;
149 while ((p = std::__libcpp_aligned_alloc(static_cast<std::size_t>(alignment), size)) == nullptr) {
150 std::new_handler nh = std::get_new_handler();
151 if (nh)
152 nh();
153 else
154 break;
155 }
156 return p;
157}
158
159_LIBCPP_MAKE_OVERRIDABLE_FUNCTION_DETECTABLE _LIBCPP_WEAK void*
160operator new(std::size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC {
161 void* p = operator_new_aligned_impl(size, alignment);
162 if (p == nullptr)
163 __throw_bad_alloc_shim();
164 return p;
165}
166
167_LIBCPP_WEAK void* operator new(size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept {
168# ifdef _LIBCPP_HAS_NO_EXCEPTIONS
169# if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION
170 _LIBCPP_ASSERT_SHIM(
171 !std::__is_function_overridden(static_cast<void* (*)(std::size_t, std::align_val_t)>(&operator new)),
172 "libc++ was configured with exceptions disabled and `operator new(size_t, align_val_t)` has been overridden, "
173 "but `operator new(size_t, align_val_t, nothrow_t)` has not been overridden. This is problematic because "
174 "`operator new(size_t, align_val_t, nothrow_t)` must call `operator new(size_t, align_val_t)`, which will "
175 "terminate in case it fails to allocate, making it impossible for `operator new(size_t, align_val_t, nothrow_t)` "
176 "to fulfill its contract (since it should return nullptr upon failure). Please make sure you override "
177 "`operator new(size_t, align_val_t, nothrow_t)` as well.");
178# endif
179
180 return operator_new_aligned_impl(size, alignment);
181# else
182 void* p = nullptr;
183 try {
184 p = ::operator new(size, alignment);
185 } catch (...) {
186 }
187 return p;
188# endif
189}
190
191_LIBCPP_MAKE_OVERRIDABLE_FUNCTION_DETECTABLE _LIBCPP_WEAK void*
192operator new[](size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC {
193 return ::operator new(size, alignment);
194}
195
196_LIBCPP_WEAK void* operator new[](size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept {
197# ifdef _LIBCPP_HAS_NO_EXCEPTIONS
198# if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION
199 _LIBCPP_ASSERT_SHIM(
200 !std::__is_function_overridden(static_cast<void* (*)(std::size_t, std::align_val_t)>(&operator new[])),
201 "libc++ was configured with exceptions disabled and `operator new[](size_t, align_val_t)` has been overridden, "
202 "but `operator new[](size_t, align_val_t, nothrow_t)` has not been overridden. This is problematic because "
203 "`operator new[](size_t, align_val_t, nothrow_t)` must call `operator new[](size_t, align_val_t)`, which will "
204 "terminate in case it fails to allocate, making it impossible for `operator new[](size_t, align_val_t, "
205 "nothrow_t)` to fulfill its contract (since it should return nullptr upon failure). Please make sure you "
206 "override "
207 "`operator new[](size_t, align_val_t, nothrow_t)` as well.");
208# endif
209
210 return operator_new_aligned_impl(size, alignment);
211# else
212 void* p = nullptr;
213 try {
214 p = ::operator new[](size, alignment);
215 } catch (...) {
216 }
217 return p;
218# endif
219}
220
221_LIBCPP_WEAK void operator delete(void* ptr, std::align_val_t) noexcept { std::__libcpp_aligned_free(ptr); }
222
223_LIBCPP_WEAK void operator delete(void* ptr, std::align_val_t alignment, const std::nothrow_t&) noexcept {
224 ::operator delete(ptr, alignment);
225}
226
227_LIBCPP_WEAK void operator delete(void* ptr, size_t, std::align_val_t alignment) noexcept {
228 ::operator delete(ptr, alignment);
229}
230
231_LIBCPP_WEAK void operator delete[](void* ptr, std::align_val_t alignment) noexcept {
232 ::operator delete(ptr, alignment);
233}
234
235_LIBCPP_WEAK void operator delete[](void* ptr, std::align_val_t alignment, const std::nothrow_t&) noexcept {
236 ::operator delete[](ptr, alignment);
237}
238
239_LIBCPP_WEAK void operator delete[](void* ptr, size_t, std::align_val_t alignment) noexcept {
240 ::operator delete[](ptr, alignment);
241}
242
243#endif // !_LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION
244// ------------------ END COPY ------------------
245

source code of libcxxabi/src/stdlib_new_delete.cpp