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_OVERRIDABLE_FUNCTION(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 | # if !_LIBCPP_HAS_EXCEPTIONS |
55 | # if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION |
56 | _LIBCPP_ASSERT_SHIM( |
57 | (!std::__is_function_overridden < 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_OVERRIDABLE_FUNCTION(void*, operator new[], (size_t size)) _THROW_BAD_ALLOC { return ::operator new(size); } |
78 | |
79 | _LIBCPP_WEAK void* operator new[](size_t size, const std::nothrow_t&) noexcept { |
80 | # if !_LIBCPP_HAS_EXCEPTIONS |
81 | # if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION |
82 | _LIBCPP_ASSERT_SHIM( |
83 | (!std::__is_function_overridden < void*(std::size_t), &operator new[]>()), |
84 | "libc++ was configured with exceptions disabled and `operator new[](size_t)` has been overridden, " |
85 | "but `operator new[](size_t, nothrow_t)` has not been overridden. This is problematic because " |
86 | "`operator new[](size_t, nothrow_t)` must call `operator new[](size_t)`, which will terminate in case " |
87 | "it fails to allocate, making it impossible for `operator new[](size_t, nothrow_t)` to fulfill its " |
88 | "contract (since it should return nullptr upon failure). Please make sure you override " |
89 | "`operator new[](size_t, nothrow_t)` as well." ); |
90 | # endif |
91 | |
92 | return operator_new_impl(size); |
93 | # else |
94 | void* p = nullptr; |
95 | try { |
96 | p = ::operator new[](size); |
97 | } catch (...) { |
98 | } |
99 | return p; |
100 | # endif |
101 | } |
102 | |
103 | _LIBCPP_WEAK void operator delete(void* ptr) noexcept { std::free(ptr); } |
104 | |
105 | _LIBCPP_WEAK void operator delete(void* ptr, const std::nothrow_t&) noexcept { ::operator delete(ptr); } |
106 | |
107 | _LIBCPP_WEAK void operator delete(void* ptr, size_t) noexcept { ::operator delete(ptr); } |
108 | |
109 | _LIBCPP_WEAK void operator delete[](void* ptr) noexcept { ::operator delete(ptr); } |
110 | |
111 | _LIBCPP_WEAK void operator delete[](void* ptr, const std::nothrow_t&) noexcept { ::operator delete[](ptr); } |
112 | |
113 | _LIBCPP_WEAK void operator delete[](void* ptr, size_t) noexcept { ::operator delete[](ptr); } |
114 | |
115 | # if _LIBCPP_HAS_LIBRARY_ALIGNED_ALLOCATION |
116 | |
117 | static void* operator_new_aligned_impl(std::size_t size, std::align_val_t alignment) { |
118 | if (size == 0) |
119 | size = 1; |
120 | if (static_cast<size_t>(alignment) < sizeof(void*)) |
121 | alignment = std::align_val_t(sizeof(void*)); |
122 | |
123 | // Try allocating memory. If allocation fails and there is a new_handler, |
124 | // call it to try free up memory, and try again until it succeeds, or until |
125 | // the new_handler decides to terminate. |
126 | void* p; |
127 | while ((p = std::__libcpp_aligned_alloc(static_cast<std::size_t>(alignment), size)) == nullptr) { |
128 | std::new_handler nh = std::get_new_handler(); |
129 | if (nh) |
130 | nh(); |
131 | else |
132 | break; |
133 | } |
134 | return p; |
135 | } |
136 | |
137 | _LIBCPP_OVERRIDABLE_FUNCTION(void*, operator new, (std::size_t size, std::align_val_t alignment)) _THROW_BAD_ALLOC { |
138 | void* p = operator_new_aligned_impl(size, alignment); |
139 | if (p == nullptr) |
140 | __throw_bad_alloc_shim(); |
141 | return p; |
142 | } |
143 | |
144 | _LIBCPP_WEAK void* operator new(size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept { |
145 | # if !_LIBCPP_HAS_EXCEPTIONS |
146 | # if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION |
147 | _LIBCPP_ASSERT_SHIM( |
148 | (!std::__is_function_overridden < void*(std::size_t, std::align_val_t), &operator new>()), |
149 | "libc++ was configured with exceptions disabled and `operator new(size_t, align_val_t)` has been overridden, " |
150 | "but `operator new(size_t, align_val_t, nothrow_t)` has not been overridden. This is problematic because " |
151 | "`operator new(size_t, align_val_t, nothrow_t)` must call `operator new(size_t, align_val_t)`, which will " |
152 | "terminate in case it fails to allocate, making it impossible for `operator new(size_t, align_val_t, nothrow_t)` " |
153 | "to fulfill its contract (since it should return nullptr upon failure). Please make sure you override " |
154 | "`operator new(size_t, align_val_t, nothrow_t)` as well." ); |
155 | # endif |
156 | |
157 | return operator_new_aligned_impl(size, alignment); |
158 | # else |
159 | void* p = nullptr; |
160 | try { |
161 | p = ::operator new(size, alignment); |
162 | } catch (...) { |
163 | } |
164 | return p; |
165 | # endif |
166 | } |
167 | |
168 | _LIBCPP_OVERRIDABLE_FUNCTION(void*, operator new[], (size_t size, std::align_val_t alignment)) _THROW_BAD_ALLOC { |
169 | return ::operator new(size, alignment); |
170 | } |
171 | |
172 | _LIBCPP_WEAK void* operator new[](size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept { |
173 | # if !_LIBCPP_HAS_EXCEPTIONS |
174 | # if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION |
175 | _LIBCPP_ASSERT_SHIM( |
176 | (!std::__is_function_overridden < void*(std::size_t, std::align_val_t), &operator new[]>()), |
177 | "libc++ was configured with exceptions disabled and `operator new[](size_t, align_val_t)` has been overridden, " |
178 | "but `operator new[](size_t, align_val_t, nothrow_t)` has not been overridden. This is problematic because " |
179 | "`operator new[](size_t, align_val_t, nothrow_t)` must call `operator new[](size_t, align_val_t)`, which will " |
180 | "terminate in case it fails to allocate, making it impossible for `operator new[](size_t, align_val_t, " |
181 | "nothrow_t)` to fulfill its contract (since it should return nullptr upon failure). Please make sure you " |
182 | "override `operator new[](size_t, align_val_t, nothrow_t)` as well." ); |
183 | # endif |
184 | |
185 | return operator_new_aligned_impl(size, alignment); |
186 | # else |
187 | void* p = nullptr; |
188 | try { |
189 | p = ::operator new[](size, alignment); |
190 | } catch (...) { |
191 | } |
192 | return p; |
193 | # endif |
194 | } |
195 | |
196 | _LIBCPP_WEAK void operator delete(void* ptr, std::align_val_t) noexcept { std::__libcpp_aligned_free(ptr); } |
197 | |
198 | _LIBCPP_WEAK void operator delete(void* ptr, std::align_val_t alignment, const std::nothrow_t&) noexcept { |
199 | ::operator delete(ptr, alignment); |
200 | } |
201 | |
202 | _LIBCPP_WEAK void operator delete(void* ptr, size_t, std::align_val_t alignment) noexcept { |
203 | ::operator delete(ptr, alignment); |
204 | } |
205 | |
206 | _LIBCPP_WEAK void operator delete[](void* ptr, 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, const std::nothrow_t&) noexcept { |
211 | ::operator delete[](ptr, alignment); |
212 | } |
213 | |
214 | _LIBCPP_WEAK void operator delete[](void* ptr, size_t, std::align_val_t alignment) noexcept { |
215 | ::operator delete[](ptr, alignment); |
216 | } |
217 | |
218 | # endif // _LIBCPP_HAS_LIBRARY_ALIGNED_ALLOCATION |
219 | // ------------------ END COPY ------------------ |
220 | |
221 | #endif // !__GLIBCXX__ && !_LIBCPP_ABI_VCRUNTIME |
222 | |