brintos

brintos / llvm-project-archived public Read only

0
0
Text · 9.2 KiB · dbb75b1 Raw
240 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9#include "__cxxabi_config.h"10#include "abort_message.h"11#include "include/aligned_alloc.h"        // from libc++12#include "include/overridable_function.h" // from libc++13#include <cstddef>14#include <cstdlib>15#include <new>16 17// Perform a few sanity checks on libc++ and libc++abi macros to ensure that18// 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#endif22 23#ifndef _LIBCPP_WEAK24#  error The _LIBCPP_WEAK macro should be already defined by libc++25#endif26 27#if defined(_LIBCXXABI_NO_EXCEPTIONS) != !_LIBCPP_HAS_EXCEPTIONS28#  error libc++ and libc++abi seem to disagree on whether exceptions are enabled29#endif30 31inline void __throw_bad_alloc_shim() {32#if _LIBCPP_HAS_EXCEPTIONS33  throw std::bad_alloc();34#else35  __abort_message("bad_alloc was thrown in -fno-exceptions mode");36#endif37}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 definitions47// in this shared library, so that they can be overridden by programs48// 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    else61      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_EXCEPTIONS75#  if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION76  _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#  endif85 86  return operator_new_impl(size);87#else88  void* p = nullptr;89  try {90    p = ::operator new(size);91  } catch (...) {92  }93  return p;94#endif95}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_EXCEPTIONS101#  if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION102  _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#  endif111 112  return operator_new_impl(size);113#else114  void* p = nullptr;115  try {116    p = ::operator new[](size);117  } catch (...) {118  }119  return p;120#endif121}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_ALLOCATION136 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 until145  // 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    else152      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_EXCEPTIONS166#    if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION167  _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#    endif176 177  return operator_new_aligned_impl(size, alignment);178#  else179  void* p = nullptr;180  try {181    p = ::operator new(size, alignment);182  } catch (...) {183  }184  return p;185#  endif186}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_EXCEPTIONS194#    if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION195  _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#    endif204 205  return operator_new_aligned_impl(size, alignment);206#  else207  void* p = nullptr;208  try {209    p = ::operator new[](size, alignment);210  } catch (...) {211  }212  return p;213#  endif214}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_ALLOCATION239// ------------------ END COPY ------------------240