master
  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) != !_LIBCPP_HAS_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#if _LIBCPP_HAS_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)) == 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_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_EXCEPTIONS
 75#  if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION
 76  _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#  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_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_EXCEPTIONS
101#  if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION
102  _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#  endif
111
112  return operator_new_impl(size);
113#else
114  void* p = nullptr;
115  try {
116    p = ::operator new[](size);
117  } catch (...) {
118  }
119  return p;
120#endif
121}
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_ALLOCATION
136
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 until
145  // 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    else
152      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_EXCEPTIONS
166#    if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION
167  _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#    endif
176
177  return operator_new_aligned_impl(size, alignment);
178#  else
179  void* p = nullptr;
180  try {
181    p = ::operator new(size, alignment);
182  } catch (...) {
183  }
184  return p;
185#  endif
186}
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_EXCEPTIONS
194#    if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION
195  _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#    endif
204
205  return operator_new_aligned_impl(size, alignment);
206#  else
207  void* p = nullptr;
208  try {
209    p = ::operator new[](size, alignment);
210  } catch (...) {
211  }
212  return p;
213#  endif
214}
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_ALLOCATION
239// ------------------ END COPY ------------------