The vcruntime headers are hairy and clash with both libc++ headers themselves and other libraries. libc++ normally deals with the clashes by deferring to the vcruntime headers and silencing its own definitions, but for clients which don't want to depend on vcruntime headers, it's desirable to support the opposite, i.e. have libc++ provide its own definitions. Certain operator new/delete replacement scenarios are not currently supported in this mode, which requires some tests to be marked XFAIL. The added documentation has more details. Differential Revision: https://reviews.llvm.org/D38522 git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@315234 91177308-0d34-0410-b5e6-96231b3b80d8
307 lines
6.2 KiB
C++
307 lines
6.2 KiB
C++
//===--------------------------- new.cpp ----------------------------------===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is dual licensed under the MIT and the University of Illinois Open
|
|
// Source Licenses. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#define _LIBCPP_BUILDING_NEW
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include "new"
|
|
#include "include/atomic_support.h"
|
|
|
|
#if defined(_LIBCPP_ABI_MICROSOFT)
|
|
#if defined(_LIBCPP_NO_VCRUNTIME)
|
|
#include "support/runtime/new_handler_fallback.ipp"
|
|
#endif
|
|
#elif defined(LIBCXX_BUILDING_LIBCXXABI)
|
|
#include <cxxabi.h>
|
|
#elif defined(LIBCXXRT)
|
|
#include <cxxabi.h>
|
|
#include "support/runtime/new_handler_fallback.ipp"
|
|
#elif defined(__GLIBCXX__)
|
|
// nothing todo
|
|
#else
|
|
# if defined(__APPLE__) && !defined(_LIBCPP_BUILDING_HAS_NO_ABI_LIBRARY)
|
|
# include <cxxabi.h> // FIXME: remove this once buildit is gone.
|
|
# else
|
|
# include "support/runtime/new_handler_fallback.ipp"
|
|
# endif
|
|
#endif
|
|
|
|
namespace std
|
|
{
|
|
|
|
#ifndef __GLIBCXX__
|
|
const nothrow_t nothrow = {};
|
|
#endif
|
|
|
|
#ifndef LIBSTDCXX
|
|
|
|
void
|
|
__throw_bad_alloc()
|
|
{
|
|
#ifndef _LIBCPP_NO_EXCEPTIONS
|
|
throw bad_alloc();
|
|
#else
|
|
_VSTD::abort();
|
|
#endif
|
|
}
|
|
|
|
#endif // !LIBSTDCXX
|
|
|
|
} // std
|
|
|
|
#if !defined(__GLIBCXX__) && \
|
|
(!defined(_LIBCPP_ABI_MICROSOFT) || defined(_LIBCPP_NO_VCRUNTIME)) && \
|
|
!defined(_LIBCPP_DISABLE_NEW_DELETE_DEFINITIONS)
|
|
|
|
// Implement all new and delete operators as weak definitions
|
|
// in this shared library, so that they can be overridden by programs
|
|
// that define non-weak copies of the functions.
|
|
|
|
_LIBCPP_WEAK
|
|
void *
|
|
operator new(std::size_t size) _THROW_BAD_ALLOC
|
|
{
|
|
if (size == 0)
|
|
size = 1;
|
|
void* p;
|
|
while ((p = ::malloc(size)) == 0)
|
|
{
|
|
// If malloc fails and there is a new_handler,
|
|
// call it to try free up memory.
|
|
std::new_handler nh = std::get_new_handler();
|
|
if (nh)
|
|
nh();
|
|
else
|
|
#ifndef _LIBCPP_NO_EXCEPTIONS
|
|
throw std::bad_alloc();
|
|
#else
|
|
break;
|
|
#endif
|
|
}
|
|
return p;
|
|
}
|
|
|
|
_LIBCPP_WEAK
|
|
void*
|
|
operator new(size_t size, const std::nothrow_t&) _NOEXCEPT
|
|
{
|
|
void* p = 0;
|
|
#ifndef _LIBCPP_NO_EXCEPTIONS
|
|
try
|
|
{
|
|
#endif // _LIBCPP_NO_EXCEPTIONS
|
|
p = ::operator new(size);
|
|
#ifndef _LIBCPP_NO_EXCEPTIONS
|
|
}
|
|
catch (...)
|
|
{
|
|
}
|
|
#endif // _LIBCPP_NO_EXCEPTIONS
|
|
return p;
|
|
}
|
|
|
|
_LIBCPP_WEAK
|
|
void*
|
|
operator new[](size_t size) _THROW_BAD_ALLOC
|
|
{
|
|
return ::operator new(size);
|
|
}
|
|
|
|
_LIBCPP_WEAK
|
|
void*
|
|
operator new[](size_t size, const std::nothrow_t&) _NOEXCEPT
|
|
{
|
|
void* p = 0;
|
|
#ifndef _LIBCPP_NO_EXCEPTIONS
|
|
try
|
|
{
|
|
#endif // _LIBCPP_NO_EXCEPTIONS
|
|
p = ::operator new[](size);
|
|
#ifndef _LIBCPP_NO_EXCEPTIONS
|
|
}
|
|
catch (...)
|
|
{
|
|
}
|
|
#endif // _LIBCPP_NO_EXCEPTIONS
|
|
return p;
|
|
}
|
|
|
|
_LIBCPP_WEAK
|
|
void
|
|
operator delete(void* ptr) _NOEXCEPT
|
|
{
|
|
if (ptr)
|
|
::free(ptr);
|
|
}
|
|
|
|
_LIBCPP_WEAK
|
|
void
|
|
operator delete(void* ptr, const std::nothrow_t&) _NOEXCEPT
|
|
{
|
|
::operator delete(ptr);
|
|
}
|
|
|
|
_LIBCPP_WEAK
|
|
void
|
|
operator delete(void* ptr, size_t) _NOEXCEPT
|
|
{
|
|
::operator delete(ptr);
|
|
}
|
|
|
|
_LIBCPP_WEAK
|
|
void
|
|
operator delete[] (void* ptr) _NOEXCEPT
|
|
{
|
|
::operator delete(ptr);
|
|
}
|
|
|
|
_LIBCPP_WEAK
|
|
void
|
|
operator delete[] (void* ptr, const std::nothrow_t&) _NOEXCEPT
|
|
{
|
|
::operator delete[](ptr);
|
|
}
|
|
|
|
_LIBCPP_WEAK
|
|
void
|
|
operator delete[] (void* ptr, size_t) _NOEXCEPT
|
|
{
|
|
::operator delete[](ptr);
|
|
}
|
|
|
|
#if !defined(_LIBCPP_HAS_NO_ALIGNED_ALLOCATION)
|
|
|
|
_LIBCPP_WEAK
|
|
void *
|
|
operator new(std::size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC
|
|
{
|
|
if (size == 0)
|
|
size = 1;
|
|
if (static_cast<size_t>(alignment) < sizeof(void*))
|
|
alignment = std::align_val_t(sizeof(void*));
|
|
void* p;
|
|
#if defined(_LIBCPP_MSVCRT_LIKE)
|
|
while ((p = _aligned_malloc(size, static_cast<size_t>(alignment))) == nullptr)
|
|
#else
|
|
while (::posix_memalign(&p, static_cast<size_t>(alignment), size) != 0)
|
|
#endif
|
|
{
|
|
// If posix_memalign fails and there is a new_handler,
|
|
// call it to try free up memory.
|
|
std::new_handler nh = std::get_new_handler();
|
|
if (nh)
|
|
nh();
|
|
else {
|
|
#ifndef _LIBCPP_NO_EXCEPTIONS
|
|
throw std::bad_alloc();
|
|
#else
|
|
p = nullptr; // posix_memalign doesn't initialize 'p' on failure
|
|
break;
|
|
#endif
|
|
}
|
|
}
|
|
return p;
|
|
}
|
|
|
|
_LIBCPP_WEAK
|
|
void*
|
|
operator new(size_t size, std::align_val_t alignment, const std::nothrow_t&) _NOEXCEPT
|
|
{
|
|
void* p = 0;
|
|
#ifndef _LIBCPP_NO_EXCEPTIONS
|
|
try
|
|
{
|
|
#endif // _LIBCPP_NO_EXCEPTIONS
|
|
p = ::operator new(size, alignment);
|
|
#ifndef _LIBCPP_NO_EXCEPTIONS
|
|
}
|
|
catch (...)
|
|
{
|
|
}
|
|
#endif // _LIBCPP_NO_EXCEPTIONS
|
|
return p;
|
|
}
|
|
|
|
_LIBCPP_WEAK
|
|
void*
|
|
operator new[](size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC
|
|
{
|
|
return ::operator new(size, alignment);
|
|
}
|
|
|
|
_LIBCPP_WEAK
|
|
void*
|
|
operator new[](size_t size, std::align_val_t alignment, const std::nothrow_t&) _NOEXCEPT
|
|
{
|
|
void* p = 0;
|
|
#ifndef _LIBCPP_NO_EXCEPTIONS
|
|
try
|
|
{
|
|
#endif // _LIBCPP_NO_EXCEPTIONS
|
|
p = ::operator new[](size, alignment);
|
|
#ifndef _LIBCPP_NO_EXCEPTIONS
|
|
}
|
|
catch (...)
|
|
{
|
|
}
|
|
#endif // _LIBCPP_NO_EXCEPTIONS
|
|
return p;
|
|
}
|
|
|
|
_LIBCPP_WEAK
|
|
void
|
|
operator delete(void* ptr, std::align_val_t) _NOEXCEPT
|
|
{
|
|
if (ptr)
|
|
#if defined(_LIBCPP_MSVCRT_LIKE)
|
|
::_aligned_free(ptr);
|
|
#else
|
|
::free(ptr);
|
|
#endif
|
|
}
|
|
|
|
_LIBCPP_WEAK
|
|
void
|
|
operator delete(void* ptr, std::align_val_t alignment, const std::nothrow_t&) _NOEXCEPT
|
|
{
|
|
::operator delete(ptr, alignment);
|
|
}
|
|
|
|
_LIBCPP_WEAK
|
|
void
|
|
operator delete(void* ptr, size_t, std::align_val_t alignment) _NOEXCEPT
|
|
{
|
|
::operator delete(ptr, alignment);
|
|
}
|
|
|
|
_LIBCPP_WEAK
|
|
void
|
|
operator delete[] (void* ptr, std::align_val_t alignment) _NOEXCEPT
|
|
{
|
|
::operator delete(ptr, alignment);
|
|
}
|
|
|
|
_LIBCPP_WEAK
|
|
void
|
|
operator delete[] (void* ptr, std::align_val_t alignment, const std::nothrow_t&) _NOEXCEPT
|
|
{
|
|
::operator delete[](ptr, alignment);
|
|
}
|
|
|
|
_LIBCPP_WEAK
|
|
void
|
|
operator delete[] (void* ptr, size_t, std::align_val_t alignment) _NOEXCEPT
|
|
{
|
|
::operator delete[](ptr, alignment);
|
|
}
|
|
|
|
#endif // !_LIBCPP_HAS_NO_ALIGNED_ALLOCATION
|
|
#endif // !__GLIBCXX__ && (!_LIBCPP_ABI_MICROSOFT || _LIBCPP_NO_VCRUNTIME) && !_LIBCPP_DISABLE_NEW_DELETE_DEFINITIONS
|