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