| //===------------------------ cxa_new_delete.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. |
| // |
| // |
| // This file implements the new and delete operators. |
| //===----------------------------------------------------------------------===// |
| |
| #define _LIBCPP_BUILDING_NEW |
| |
| #include <new> |
| #include <cstdlib> |
| |
| /* |
| [new.delete.single] |
| |
| * Executes a loop: Within the loop, the function first attempts to allocate |
| the requested storage. Whether the attempt involves a call to the Standard C |
| library function malloc is unspecified. |
| |
| * Returns a pointer to the allocated storage if the attempt is successful. |
| Otherwise, if the current new_handler (18.6.2.5) is a null pointer value, |
| throws bad_alloc. |
| |
| * Otherwise, the function calls the current new_handler function (18.6.2.3). |
| If the called function returns, the loop repeats. |
| |
| * The loop terminates when an attempt to allocate the requested storage is |
| successful or when a called new_handler function does not return. |
| */ |
| __attribute__((__weak__, __visibility__("default"))) |
| void * |
| operator new(std::size_t size) |
| #if !__has_feature(cxx_noexcept) |
| throw(std::bad_alloc) |
| #endif |
| { |
| if (size == 0) |
| size = 1; |
| void* p; |
| while ((p = std::malloc(size)) == 0) |
| { |
| std::new_handler nh = std::get_new_handler(); |
| if (nh) |
| nh(); |
| else |
| throw std::bad_alloc(); |
| } |
| return p; |
| } |
| |
| /* |
| Note: The relationships among these operators is both carefully considered |
| and standard in C++11. Please do not change them without fully understanding |
| the consequences of doing so. Reference: |
| http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2158.html |
| */ |
| /* |
| [new.delete.single] |
| |
| Calls operator new(size). If the call returns normally, returns the result of |
| that call. Otherwise, returns a null pointer. |
| */ |
| __attribute__((__weak__, __visibility__("default"))) |
| void* |
| operator new(size_t size, const std::nothrow_t&) |
| #if __has_feature(cxx_noexcept) |
| noexcept |
| #else |
| throw() |
| #endif |
| { |
| void* p = 0; |
| try |
| { |
| p = ::operator new(size); |
| } |
| catch (...) |
| { |
| } |
| return p; |
| } |
| |
| /* |
| [new.delete.array] |
| |
| Returns operator new(size). |
| */ |
| __attribute__((__weak__, __visibility__("default"))) |
| void* |
| operator new[](size_t size) |
| #if !__has_feature(cxx_noexcept) |
| throw(std::bad_alloc) |
| #endif |
| { |
| return ::operator new(size); |
| } |
| |
| /* |
| [new.delete.array] |
| |
| Calls operator new[](size). If the call returns normally, returns the result |
| of that call. Otherwise, returns a null pointer. |
| */ |
| __attribute__((__weak__, __visibility__("default"))) |
| void* |
| operator new[](size_t size, const std::nothrow_t&) |
| #if __has_feature(cxx_noexcept) |
| noexcept |
| #else |
| throw() |
| #endif |
| { |
| void* p = 0; |
| try |
| { |
| p = ::operator new[](size); |
| } |
| catch (...) |
| { |
| } |
| return p; |
| } |
| |
| /* |
| [new.delete.single] |
| |
| If ptr is null, does nothing. Otherwise, reclaims the storage allocated by the |
| earlier call to operator new. |
| */ |
| __attribute__((__weak__, __visibility__("default"))) |
| void |
| operator delete(void* ptr) |
| #if __has_feature(cxx_noexcept) |
| noexcept |
| #else |
| throw() |
| #endif |
| { |
| if (ptr) |
| std::free(ptr); |
| } |
| |
| /* |
| [new.delete.single] |
| |
| calls operator delete(ptr) |
| */ |
| __attribute__((__weak__, __visibility__("default"))) |
| void |
| operator delete(void* ptr, const std::nothrow_t&) |
| #if __has_feature(cxx_noexcept) |
| noexcept |
| #else |
| throw() |
| #endif |
| { |
| ::operator delete(ptr); |
| } |
| |
| /* |
| [new.delete.array] |
| |
| Calls operator delete(ptr) |
| */ |
| __attribute__((__weak__, __visibility__("default"))) |
| void |
| operator delete[] (void* ptr) |
| #if __has_feature(cxx_noexcept) |
| noexcept |
| #else |
| throw() |
| #endif |
| { |
| ::operator delete(ptr); |
| } |
| |
| /* |
| [new.delete.array] |
| |
| calls operator delete[](ptr) |
| */ |
| __attribute__((__weak__, __visibility__("default"))) |
| void |
| operator delete[] (void* ptr, const std::nothrow_t&) |
| #if __has_feature(cxx_noexcept) |
| noexcept |
| #else |
| throw() |
| #endif |
| { |
| ::operator delete[](ptr); |
| } |
| |
| namespace std |
| { |
| |
| // bad_alloc |
| |
| bad_alloc::bad_alloc() _NOEXCEPT |
| { |
| } |
| |
| bad_alloc::~bad_alloc() _NOEXCEPT |
| { |
| } |
| |
| const char* |
| bad_alloc::what() const _NOEXCEPT |
| { |
| return "std::bad_alloc"; |
| } |
| |
| // bad_array_new_length |
| |
| bad_array_new_length::bad_array_new_length() _NOEXCEPT |
| { |
| } |
| |
| bad_array_new_length::~bad_array_new_length() _NOEXCEPT |
| { |
| } |
| |
| const char* |
| bad_array_new_length::what() const _NOEXCEPT |
| { |
| return "bad_array_new_length"; |
| } |
| |
| // bad_array_length |
| |
| #ifndef _LIBCPP_BAD_ARRAY_LENGTH_DEFINED |
| |
| class _LIBCPP_EXCEPTION_ABI bad_array_length |
| : public bad_alloc |
| { |
| public: |
| bad_array_length() _NOEXCEPT; |
| virtual ~bad_array_length() _NOEXCEPT; |
| virtual const char* what() const _NOEXCEPT; |
| }; |
| |
| #endif // _LIBCPP_BAD_ARRAY_LENGTH_DEFINED |
| |
| bad_array_length::bad_array_length() _NOEXCEPT |
| { |
| } |
| |
| bad_array_length::~bad_array_length() _NOEXCEPT |
| { |
| } |
| |
| const char* |
| bad_array_length::what() const _NOEXCEPT |
| { |
| return "bad_array_length"; |
| } |
| |
| } // std |