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 "include/overridable_function.h" |
10 | #include <__memory/aligned_alloc.h> |
11 | #include <cstddef> |
12 | #include <cstdlib> |
13 | #include <new> |
14 | |
15 | #if !defined(__GLIBCXX__) && !defined(_LIBCPP_ABI_VCRUNTIME) |
16 | |
17 | // The code below is copied as-is into libc++abi's libcxxabi/src/stdlib_new_delete.cpp |
18 | // file. The version in this file is the canonical one. |
19 | |
20 | inline void __throw_bad_alloc_shim() { std::__throw_bad_alloc(); } |
21 | |
22 | # define _LIBCPP_ASSERT_SHIM(expr, str) _LIBCPP_ASSERT(expr, str) |
23 | |
24 | // ------------------ BEGIN COPY ------------------ |
25 | // Implement all new and delete operators as weak definitions |
26 | // in this shared library, so that they can be overridden by programs |
27 | // that define non-weak copies of the functions. |
28 | |
29 | static void* operator_new_impl(std::size_t size) { |
30 | if (size == 0) |
31 | size = 1; |
32 | void* p; |
33 | while ((p = std::malloc(size)) == nullptr) { |
34 | // If malloc fails and there is a new_handler, |
35 | // call it to try free up memory. |
36 | std::new_handler nh = std::get_new_handler(); |
37 | if (nh) |
38 | nh(); |
39 | else |
40 | break; |
41 | } |
42 | return p; |
43 | } |
44 | |
45 | _LIBCPP_MAKE_OVERRIDABLE_FUNCTION_DETECTABLE _LIBCPP_WEAK void* operator new(std::size_t size) _THROW_BAD_ALLOC { |
46 | void* p = operator_new_impl(size); |
47 | if (p == nullptr) |
48 | __throw_bad_alloc_shim(); |
49 | return p; |
50 | } |
51 | |
52 | _LIBCPP_WEAK void* operator new(size_t size, const std::nothrow_t&) noexcept { |
53 | # ifdef _LIBCPP_HAS_NO_EXCEPTIONS |
54 | # if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION |
55 | _LIBCPP_ASSERT_SHIM( |
56 | !std::__is_function_overridden(static_cast<void* (*)(std::size_t)>(&operator new)), |
57 | "libc++ was configured with exceptions disabled and `operator new(size_t)` has been overridden, " |
58 | "but `operator new(size_t, nothrow_t)` has not been overridden. This is problematic because " |
59 | "`operator new(size_t, nothrow_t)` must call `operator new(size_t)`, which will terminate in case " |
60 | "it fails to allocate, making it impossible for `operator new(size_t, nothrow_t)` to fulfill its " |
61 | "contract (since it should return nullptr upon failure). Please make sure you override " |
62 | "`operator new(size_t, nothrow_t)` as well." ); |
63 | # endif |
64 | |
65 | return operator_new_impl(size); |
66 | # else |
67 | void* p = nullptr; |
68 | try { |
69 | p = ::operator new(size); |
70 | } catch (...) { |
71 | } |
72 | return p; |
73 | # endif |
74 | } |
75 | |
76 | _LIBCPP_MAKE_OVERRIDABLE_FUNCTION_DETECTABLE _LIBCPP_WEAK void* operator new[](size_t size) _THROW_BAD_ALLOC { |
77 | return ::operator new(size); |
78 | } |
79 | |
80 | _LIBCPP_WEAK void* operator new[](size_t size, const std::nothrow_t&) noexcept { |
81 | # ifdef _LIBCPP_HAS_NO_EXCEPTIONS |
82 | # if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION |
83 | _LIBCPP_ASSERT_SHIM( |
84 | !std::__is_function_overridden(static_cast<void* (*)(std::size_t)>(&operator new[])), |
85 | "libc++ was configured with exceptions disabled and `operator new[](size_t)` has been overridden, " |
86 | "but `operator new[](size_t, nothrow_t)` has not been overridden. This is problematic because " |
87 | "`operator new[](size_t, nothrow_t)` must call `operator new[](size_t)`, which will terminate in case " |
88 | "it fails to allocate, making it impossible for `operator new[](size_t, nothrow_t)` to fulfill its " |
89 | "contract (since it should return nullptr upon failure). Please make sure you override " |
90 | "`operator new[](size_t, nothrow_t)` as well." ); |
91 | # endif |
92 | |
93 | return operator_new_impl(size); |
94 | # else |
95 | void* p = nullptr; |
96 | try { |
97 | p = ::operator new[](size); |
98 | } catch (...) { |
99 | } |
100 | return p; |
101 | # endif |
102 | } |
103 | |
104 | _LIBCPP_WEAK void operator delete(void* ptr) noexcept { std::free(ptr); } |
105 | |
106 | _LIBCPP_WEAK void operator delete(void* ptr, const std::nothrow_t&) noexcept { ::operator delete(ptr); } |
107 | |
108 | _LIBCPP_WEAK void operator delete(void* ptr, size_t) noexcept { ::operator delete(ptr); } |
109 | |
110 | _LIBCPP_WEAK void operator delete[](void* ptr) noexcept { ::operator delete(ptr); } |
111 | |
112 | _LIBCPP_WEAK void operator delete[](void* ptr, const std::nothrow_t&) noexcept { ::operator delete[](ptr); } |
113 | |
114 | _LIBCPP_WEAK void operator delete[](void* ptr, size_t) noexcept { ::operator delete[](ptr); } |
115 | |
116 | # if !defined(_LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION) |
117 | |
118 | static void* operator_new_aligned_impl(std::size_t size, std::align_val_t alignment) { |
119 | if (size == 0) |
120 | size = 1; |
121 | if (static_cast<size_t>(alignment) < sizeof(void*)) |
122 | alignment = std::align_val_t(sizeof(void*)); |
123 | |
124 | // Try allocating memory. If allocation fails and there is a new_handler, |
125 | // call it to try free up memory, and try again until it succeeds, or until |
126 | // the new_handler decides to terminate. |
127 | void* p; |
128 | while ((p = std::__libcpp_aligned_alloc(static_cast<std::size_t>(alignment), size)) == nullptr) { |
129 | std::new_handler nh = std::get_new_handler(); |
130 | if (nh) |
131 | nh(); |
132 | else |
133 | break; |
134 | } |
135 | return p; |
136 | } |
137 | |
138 | _LIBCPP_MAKE_OVERRIDABLE_FUNCTION_DETECTABLE _LIBCPP_WEAK void* |
139 | operator new(std::size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC { |
140 | void* p = operator_new_aligned_impl(size, alignment); |
141 | if (p == nullptr) |
142 | __throw_bad_alloc_shim(); |
143 | return p; |
144 | } |
145 | |
146 | _LIBCPP_WEAK void* operator new(size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept { |
147 | # ifdef _LIBCPP_HAS_NO_EXCEPTIONS |
148 | # if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION |
149 | _LIBCPP_ASSERT_SHIM( |
150 | !std::__is_function_overridden(static_cast<void* (*)(std::size_t, std::align_val_t)>(&operator new)), |
151 | "libc++ was configured with exceptions disabled and `operator new(size_t, align_val_t)` has been overridden, " |
152 | "but `operator new(size_t, align_val_t, nothrow_t)` has not been overridden. This is problematic because " |
153 | "`operator new(size_t, align_val_t, nothrow_t)` must call `operator new(size_t, align_val_t)`, which will " |
154 | "terminate in case it fails to allocate, making it impossible for `operator new(size_t, align_val_t, nothrow_t)` " |
155 | "to fulfill its contract (since it should return nullptr upon failure). Please make sure you override " |
156 | "`operator new(size_t, align_val_t, nothrow_t)` as well." ); |
157 | # endif |
158 | |
159 | return operator_new_aligned_impl(size, alignment); |
160 | # else |
161 | void* p = nullptr; |
162 | try { |
163 | p = ::operator new(size, alignment); |
164 | } catch (...) { |
165 | } |
166 | return p; |
167 | # endif |
168 | } |
169 | |
170 | _LIBCPP_MAKE_OVERRIDABLE_FUNCTION_DETECTABLE _LIBCPP_WEAK void* |
171 | operator new[](size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC { |
172 | return ::operator new(size, alignment); |
173 | } |
174 | |
175 | _LIBCPP_WEAK void* operator new[](size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept { |
176 | # ifdef _LIBCPP_HAS_NO_EXCEPTIONS |
177 | # if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION |
178 | _LIBCPP_ASSERT_SHIM( |
179 | !std::__is_function_overridden(static_cast<void* (*)(std::size_t, std::align_val_t)>(&operator new[])), |
180 | "libc++ was configured with exceptions disabled and `operator new[](size_t, align_val_t)` has been overridden, " |
181 | "but `operator new[](size_t, align_val_t, nothrow_t)` has not been overridden. This is problematic because " |
182 | "`operator new[](size_t, align_val_t, nothrow_t)` must call `operator new[](size_t, align_val_t)`, which will " |
183 | "terminate in case it fails to allocate, making it impossible for `operator new[](size_t, align_val_t, " |
184 | "nothrow_t)` to fulfill its contract (since it should return nullptr upon failure). Please make sure you " |
185 | "override " |
186 | "`operator new[](size_t, align_val_t, nothrow_t)` as well." ); |
187 | # endif |
188 | |
189 | return operator_new_aligned_impl(size, alignment); |
190 | # else |
191 | void* p = nullptr; |
192 | try { |
193 | p = ::operator new[](size, alignment); |
194 | } catch (...) { |
195 | } |
196 | return p; |
197 | # endif |
198 | } |
199 | |
200 | _LIBCPP_WEAK void operator delete(void* ptr, std::align_val_t) noexcept { std::__libcpp_aligned_free(ptr); } |
201 | |
202 | _LIBCPP_WEAK void operator delete(void* ptr, std::align_val_t alignment, const std::nothrow_t&) noexcept { |
203 | ::operator delete(ptr, alignment); |
204 | } |
205 | |
206 | _LIBCPP_WEAK void operator delete(void* ptr, size_t, std::align_val_t alignment) noexcept { |
207 | ::operator delete(ptr, alignment); |
208 | } |
209 | |
210 | _LIBCPP_WEAK void operator delete[](void* ptr, std::align_val_t alignment) noexcept { |
211 | ::operator delete(ptr, alignment); |
212 | } |
213 | |
214 | _LIBCPP_WEAK void operator delete[](void* ptr, std::align_val_t alignment, const std::nothrow_t&) noexcept { |
215 | ::operator delete[](ptr, alignment); |
216 | } |
217 | |
218 | _LIBCPP_WEAK void operator delete[](void* ptr, size_t, std::align_val_t alignment) noexcept { |
219 | ::operator delete[](ptr, alignment); |
220 | } |
221 | |
222 | # endif // !_LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION |
223 | // ------------------ END COPY ------------------ |
224 | |
225 | #endif // !__GLIBCXX__ && !_LIBCPP_ABI_VCRUNTIME |
226 | |