From 42da1d385de8559710e04b5a05234f2dd8bb347e Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 4 Aug 2020 17:30:57 -0700 Subject: [PATCH] libcxxabi: upgrade from llvm 10 to 11rc1 --- lib/libcxxabi/include/__cxxabi_config.h | 8 + lib/libcxxabi/src/abort_message.cpp | 70 ++--- lib/libcxxabi/src/abort_message.h | 11 +- lib/libcxxabi/src/cxa_guard_impl.h | 29 +- lib/libcxxabi/src/cxa_handlers.h | 2 +- lib/libcxxabi/src/cxa_unexpected.cpp | 22 -- lib/libcxxabi/src/cxa_vector.cpp | 12 +- lib/libcxxabi/src/demangle/ItaniumDemangle.h | 47 +++- lib/libcxxabi/src/include/atomic_support.h | 30 --- lib/libcxxabi/src/private_typeinfo.cpp | 47 ++-- lib/libcxxabi/src/stdlib_new_delete.cpp | 262 +++++++++++++++++++ 11 files changed, 406 insertions(+), 134 deletions(-) delete mode 100644 lib/libcxxabi/src/cxa_unexpected.cpp create mode 100644 lib/libcxxabi/src/stdlib_new_delete.cpp diff --git a/lib/libcxxabi/include/__cxxabi_config.h b/lib/libcxxabi/include/__cxxabi_config.h index cbbb1c10c1..b5444d67ee 100644 --- a/lib/libcxxabi/include/__cxxabi_config.h +++ b/lib/libcxxabi/include/__cxxabi_config.h @@ -76,4 +76,12 @@ # define _LIBCXXABI_GUARD_ABI_ARM #endif +#if defined(_LIBCXXABI_COMPILER_CLANG) +# if !__has_feature(cxx_exceptions) +# define _LIBCXXABI_NO_EXCEPTIONS +# endif +#elif defined(_LIBCXXABI_COMPILER_GCC) && !__EXCEPTIONS +# define _LIBCXXABI_NO_EXCEPTIONS +#endif + #endif // ____CXXABI_CONFIG_H diff --git a/lib/libcxxabi/src/abort_message.cpp b/lib/libcxxabi/src/abort_message.cpp index d556af1c90..ad44063fac 100644 --- a/lib/libcxxabi/src/abort_message.cpp +++ b/lib/libcxxabi/src/abort_message.cpp @@ -12,52 +12,54 @@ #include "abort_message.h" #ifdef __BIONIC__ -#include -#if __ANDROID_API__ >= 21 -#include -extern "C" void android_set_abort_message(const char* msg); -#else -#include -#endif // __ANDROID_API__ >= 21 +# include +# if __ANDROID_API__ >= 21 +# include + extern "C" void android_set_abort_message(const char* msg); +# else +# include +# endif // __ANDROID_API__ >= 21 #endif // __BIONIC__ -#ifdef __APPLE__ -# if defined(__has_include) && __has_include() -# define HAVE_CRASHREPORTERCLIENT_H -# include -# endif +#if defined(__APPLE__) && __has_include() +# include +# define _LIBCXXABI_USE_CRASHREPORTER_CLIENT #endif void abort_message(const char* format, ...) { - // write message to stderr + // Write message to stderr. We do this before formatting into a + // variable-size buffer so that we still get some information if + // formatting into the variable-sized buffer fails. #if !defined(NDEBUG) || !defined(LIBCXXABI_BAREMETAL) -#ifdef __APPLE__ - fprintf(stderr, "libc++abi.dylib: "); -#endif - va_list list; - va_start(list, format); - vfprintf(stderr, format, list); - va_end(list); - fprintf(stderr, "\n"); + { + fprintf(stderr, "libc++abi: "); + va_list list; + va_start(list, format); + vfprintf(stderr, format, list); + va_end(list); + fprintf(stderr, "\n"); + } #endif -#if defined(__APPLE__) && defined(HAVE_CRASHREPORTERCLIENT_H) - // record message in crash report + // Format the arguments into an allocated buffer. We leak the buffer on + // purpose, since we're about to abort() anyway. +#if defined(_LIBCXXABI_USE_CRASHREPORTER_CLIENT) char* buffer; - va_list list2; - va_start(list2, format); - vasprintf(&buffer, format, list2); - va_end(list2); + va_list list; + va_start(list, format); + vasprintf(&buffer, format, list); + va_end(list); + CRSetCrashLogMessage(buffer); #elif defined(__BIONIC__) char* buffer; - va_list list2; - va_start(list2, format); - vasprintf(&buffer, format, list2); - va_end(list2); + va_list list; + va_start(list, format); + vasprintf(&buffer, format, list); + va_end(list); -#if __ANDROID_API__ >= 21 +# if __ANDROID_API__ >= 21 // Show error in tombstone. android_set_abort_message(buffer); @@ -65,12 +67,12 @@ void abort_message(const char* format, ...) openlog("libc++abi", 0, 0); syslog(LOG_CRIT, "%s", buffer); closelog(); -#else +# else // The good error reporting wasn't available in Android until L. Since we're // about to abort anyway, just call __assert2, which will log _somewhere_ // (tombstone and/or logcat) in older releases. __assert2(__FILE__, __LINE__, __func__, buffer); -#endif // __ANDROID_API__ >= 21 +# endif // __ANDROID_API__ >= 21 #endif // __BIONIC__ abort(); diff --git a/lib/libcxxabi/src/abort_message.h b/lib/libcxxabi/src/abort_message.h index 7cb11f4c2f..83f956f74f 100644 --- a/lib/libcxxabi/src/abort_message.h +++ b/lib/libcxxabi/src/abort_message.h @@ -11,16 +11,7 @@ #include "cxxabi.h" -#ifdef __cplusplus -extern "C" { -#endif - -_LIBCXXABI_HIDDEN _LIBCXXABI_NORETURN void +extern "C" _LIBCXXABI_HIDDEN _LIBCXXABI_NORETURN void abort_message(const char *format, ...) __attribute__((format(printf, 1, 2))); -#ifdef __cplusplus -} #endif - -#endif - diff --git a/lib/libcxxabi/src/cxa_guard_impl.h b/lib/libcxxabi/src/cxa_guard_impl.h index a8ec0b72fe..f6a698e23a 100644 --- a/lib/libcxxabi/src/cxa_guard_impl.h +++ b/lib/libcxxabi/src/cxa_guard_impl.h @@ -40,7 +40,6 @@ #include "__cxxabi_config.h" #include "include/atomic_support.h" #include -#include #if defined(__has_include) # if __has_include() # include @@ -108,6 +107,32 @@ struct LazyValue { bool is_init = false; }; +template +class AtomicInt { +public: + using MemoryOrder = std::__libcpp_atomic_order; + + explicit AtomicInt(IntType *b) : b(b) {} + AtomicInt(AtomicInt const&) = delete; + AtomicInt& operator=(AtomicInt const&) = delete; + + IntType load(MemoryOrder ord) { + return std::__libcpp_atomic_load(b, ord); + } + void store(IntType val, MemoryOrder ord) { + std::__libcpp_atomic_store(b, val, ord); + } + IntType exchange(IntType new_val, MemoryOrder ord) { + return std::__libcpp_atomic_exchange(b, new_val, ord); + } + bool compare_exchange(IntType *expected, IntType desired, MemoryOrder ord_success, MemoryOrder ord_failure) { + return std::__libcpp_atomic_compare_exchange(b, expected, desired, ord_success, ord_failure); + } + +private: + IntType *b; +}; + //===----------------------------------------------------------------------===// // PlatformGetThreadID //===----------------------------------------------------------------------===// @@ -195,7 +220,7 @@ public: public: /// base_address - the address of the original guard object. void* const base_address; - /// The address of the guord byte at offset 0. + /// The address of the guard byte at offset 0. uint8_t* const guard_byte_address; /// The address of the byte used by the implementation during initialization. uint8_t* const init_byte_address; diff --git a/lib/libcxxabi/src/cxa_handlers.h b/lib/libcxxabi/src/cxa_handlers.h index c8e2e44aee..a96d7e5bcf 100644 --- a/lib/libcxxabi/src/cxa_handlers.h +++ b/lib/libcxxabi/src/cxa_handlers.h @@ -12,7 +12,7 @@ #ifndef _CXA_HANDLERS_H #define _CXA_HANDLERS_H -#include <__cxxabi_config.h> +#include "__cxxabi_config.h" #include diff --git a/lib/libcxxabi/src/cxa_unexpected.cpp b/lib/libcxxabi/src/cxa_unexpected.cpp deleted file mode 100644 index bbfa6684ef..0000000000 --- a/lib/libcxxabi/src/cxa_unexpected.cpp +++ /dev/null @@ -1,22 +0,0 @@ -//===------------------------- cxa_unexpected.cpp -------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include -#include "cxxabi.h" -#include "cxa_exception.h" - -namespace __cxxabiv1 -{ - -extern "C" -{ - -} - -} // namespace __cxxabiv1 - diff --git a/lib/libcxxabi/src/cxa_vector.cpp b/lib/libcxxabi/src/cxa_vector.cpp index f20e978d36..325bbf22d2 100644 --- a/lib/libcxxabi/src/cxa_vector.cpp +++ b/lib/libcxxabi/src/cxa_vector.cpp @@ -24,9 +24,9 @@ namespace __cxxabiv1 { -#if 0 -#pragma mark --Helper routines and classes -- -#endif +// +// Helper routines and classes +// namespace { inline static size_t __get_element_count ( void *p ) { @@ -111,9 +111,9 @@ namespace { }; } -#if 0 -#pragma mark --Externally visible routines-- -#endif +// +// Externally visible routines +// namespace { _LIBCXXABI_NORETURN diff --git a/lib/libcxxabi/src/demangle/ItaniumDemangle.h b/lib/libcxxabi/src/demangle/ItaniumDemangle.h index 376e0efea4..6ab8732183 100644 --- a/lib/libcxxabi/src/demangle/ItaniumDemangle.h +++ b/lib/libcxxabi/src/demangle/ItaniumDemangle.h @@ -98,7 +98,7 @@ X(BoolExpr) \ X(StringLiteral) \ X(LambdaExpr) \ - X(IntegerCastExpr) \ + X(EnumLiteral) \ X(IntegerLiteral) \ X(FloatLiteral) \ X(DoubleLiteral) \ @@ -2036,22 +2036,26 @@ public: } }; -class IntegerCastExpr : public Node { +class EnumLiteral : public Node { // ty(integer) const Node *Ty; StringView Integer; public: - IntegerCastExpr(const Node *Ty_, StringView Integer_) - : Node(KIntegerCastExpr), Ty(Ty_), Integer(Integer_) {} + EnumLiteral(const Node *Ty_, StringView Integer_) + : Node(KEnumLiteral), Ty(Ty_), Integer(Integer_) {} template void match(Fn F) const { F(Ty, Integer); } void printLeft(OutputStream &S) const override { - S += "("; + S << "("; Ty->print(S); - S += ")"; - S += Integer; + S << ")"; + + if (Integer[0] == 'n') + S << "-" << Integer.dropFront(1); + else + S << Integer; } }; @@ -4064,8 +4068,11 @@ Qualifiers AbstractManglingParser::parseCVQualifiers() { // ::= fp _ # L == 0, second and later parameters // ::= fL p _ # L > 0, first parameter // ::= fL p _ # L > 0, second and later parameters +// ::= fpT # 'this' expression (not part of standard?) template Node *AbstractManglingParser::parseFunctionParam() { + if (consumeIf("fpT")) + return make("this"); if (consumeIf("fp")) { parseCVQualifiers(); StringView Num = parseNumber(); @@ -4225,7 +4232,13 @@ Node *AbstractManglingParser::parseExprPrimary() { return getDerived().template parseFloatingLiteral(); case 'e': ++First; +#if defined(__powerpc__) || defined(__s390__) + // Handle cases where long doubles encoded with e have the same size + // and representation as doubles. + return getDerived().template parseFloatingLiteral(); +#else return getDerived().template parseFloatingLiteral(); +#endif case '_': if (consumeIf("_Z")) { Node *R = getDerived().parseEncoding(); @@ -4264,12 +4277,12 @@ Node *AbstractManglingParser::parseExprPrimary() { Node *T = getDerived().parseType(); if (T == nullptr) return nullptr; - StringView N = parseNumber(); + StringView N = parseNumber(/*AllowNegative=*/true); if (N.empty()) return nullptr; if (!consumeIf('E')) return nullptr; - return make(T, N); + return make(T, N); } } } @@ -5083,6 +5096,22 @@ Node *AbstractManglingParser::parseSpecialName() { // ::= template Node *AbstractManglingParser::parseEncoding() { + // The template parameters of an encoding are unrelated to those of the + // enclosing context. + class SaveTemplateParams { + AbstractManglingParser *Parser; + decltype(TemplateParams) OldParams; + + public: + SaveTemplateParams(AbstractManglingParser *Parser) : Parser(Parser) { + OldParams = std::move(Parser->TemplateParams); + Parser->TemplateParams.clear(); + } + ~SaveTemplateParams() { + Parser->TemplateParams = std::move(OldParams); + } + } SaveTemplateParams(this); + if (look() == 'G' || look() == 'T') return getDerived().parseSpecialName(); diff --git a/lib/libcxxabi/src/include/atomic_support.h b/lib/libcxxabi/src/include/atomic_support.h index 4ff45eb93a..6f9dbf4360 100644 --- a/lib/libcxxabi/src/include/atomic_support.h +++ b/lib/libcxxabi/src/include/atomic_support.h @@ -177,34 +177,4 @@ bool __libcpp_atomic_compare_exchange(_ValueType* __val, _LIBCPP_END_NAMESPACE_STD -namespace { - -template -class AtomicInt { -public: - using MemoryOrder = std::__libcpp_atomic_order; - - explicit AtomicInt(IntType *b) : b(b) {} - AtomicInt(AtomicInt const&) = delete; - AtomicInt& operator=(AtomicInt const&) = delete; - - IntType load(MemoryOrder ord) { - return std::__libcpp_atomic_load(b, ord); - } - void store(IntType val, MemoryOrder ord) { - std::__libcpp_atomic_store(b, val, ord); - } - IntType exchange(IntType new_val, MemoryOrder ord) { - return std::__libcpp_atomic_exchange(b, new_val, ord); - } - bool compare_exchange(IntType *expected, IntType desired, MemoryOrder ord_success, MemoryOrder ord_failure) { - return std::__libcpp_atomic_compare_exchange(b, expected, desired, ord_success, ord_failure); - } - -private: - IntType *b; -}; - -} // end namespace - #endif // ATOMIC_SUPPORT_H diff --git a/lib/libcxxabi/src/private_typeinfo.cpp b/lib/libcxxabi/src/private_typeinfo.cpp index 5ce762a22b..55a90b3ae1 100644 --- a/lib/libcxxabi/src/private_typeinfo.cpp +++ b/lib/libcxxabi/src/private_typeinfo.cpp @@ -8,11 +8,11 @@ #include "private_typeinfo.h" -// The flag _LIBCXX_DYNAMIC_FALLBACK is used to make dynamic_cast more -// forgiving when type_info's mistakenly have hidden visibility and thus -// multiple type_infos can exist for a single type. +// The flag _LIBCXXABI_FORGIVING_DYNAMIC_CAST is used to make dynamic_cast +// more forgiving when type_info's mistakenly have hidden visibility and +// thus multiple type_infos can exist for a single type. // -// When _LIBCXX_DYNAMIC_FALLBACK is defined, and only in the case where +// When _LIBCXXABI_FORGIVING_DYNAMIC_CAST is defined, and only in the case where // there is a detected inconsistency in the type_info hierarchy during a // dynamic_cast, then the equality operation will fall back to using strcmp // on type_info names to determine type_info equality. @@ -23,7 +23,7 @@ // algorithm and an inconsistency is still detected, dynamic_cast will call // abort with an appropriate message. // -// The current implementation of _LIBCXX_DYNAMIC_FALLBACK requires a +// The current implementation of _LIBCXXABI_FORGIVING_DYNAMIC_CAST requires a // printf-like function called syslog: // // void syslog(int facility_priority, const char* format, ...); @@ -31,21 +31,22 @@ // If you want this functionality but your platform doesn't have syslog, // just implement it in terms of fprintf(stderr, ...). // -// _LIBCXX_DYNAMIC_FALLBACK is currently off by default. +// _LIBCXXABI_FORGIVING_DYNAMIC_CAST is currently off by default. // On Windows, typeids are different between DLLs and EXEs, so comparing // type_info* will work for typeids from the same compiled file but fail // for typeids from a DLL and an executable. Among other things, exceptions // are not caught by handlers since can_catch() returns false. // -// Defining _LIBCXX_DYNAMIC_FALLBACK does not help since can_catch() calls +// Defining _LIBCXXABI_FORGIVING_DYNAMIC_CAST does not help since can_catch() calls // is_equal() with use_strcmp=false so the string names are not compared. #include -#ifdef _LIBCXX_DYNAMIC_FALLBACK +#ifdef _LIBCXXABI_FORGIVING_DYNAMIC_CAST #include "abort_message.h" #include +#include #endif static inline @@ -633,22 +634,25 @@ __dynamic_cast(const void *static_ptr, const __class_type_info *static_type, info.number_of_dst_type = 1; // Do the search dynamic_type->search_above_dst(&info, dynamic_ptr, dynamic_ptr, public_path, false); -#ifdef _LIBCXX_DYNAMIC_FALLBACK +#ifdef _LIBCXXABI_FORGIVING_DYNAMIC_CAST // The following if should always be false because we should definitely // find (static_ptr, static_type), either on a public or private path if (info.path_dst_ptr_to_static_ptr == unknown) { // We get here only if there is some kind of visibility problem // in client code. - syslog(LOG_ERR, "dynamic_cast error 1: Both of the following type_info's " - "should have public visibility. At least one of them is hidden. %s" - ", %s.\n", static_type->name(), dynamic_type->name()); + static std::atomic error_count(0); + size_t error_count_snapshot = error_count.fetch_add(1, std::memory_order_relaxed); + if ((error_count_snapshot & (error_count_snapshot-1)) == 0) + syslog(LOG_ERR, "dynamic_cast error 1: Both of the following type_info's " + "should have public visibility. At least one of them is hidden. %s" + ", %s.\n", static_type->name(), dynamic_type->name()); // Redo the search comparing type_info's using strcmp info = {dst_type, static_ptr, static_type, src2dst_offset, 0}; info.number_of_dst_type = 1; dynamic_type->search_above_dst(&info, dynamic_ptr, dynamic_ptr, public_path, true); } -#endif // _LIBCXX_DYNAMIC_FALLBACK +#endif // _LIBCXXABI_FORGIVING_DYNAMIC_CAST // Query the search. if (info.path_dst_ptr_to_static_ptr == public_path) dst_ptr = dynamic_ptr; @@ -657,22 +661,25 @@ __dynamic_cast(const void *static_ptr, const __class_type_info *static_type, { // Not using giant short cut. Do the search dynamic_type->search_below_dst(&info, dynamic_ptr, public_path, false); - #ifdef _LIBCXX_DYNAMIC_FALLBACK + #ifdef _LIBCXXABI_FORGIVING_DYNAMIC_CAST // The following if should always be false because we should definitely // find (static_ptr, static_type), either on a public or private path if (info.path_dst_ptr_to_static_ptr == unknown && info.path_dynamic_ptr_to_static_ptr == unknown) { - syslog(LOG_ERR, "dynamic_cast error 2: One or more of the following type_info's " - "has hidden visibility or is defined in more than one translation " - "unit. They should all have public visibility. " - "%s, %s, %s.\n", static_type->name(), dynamic_type->name(), - dst_type->name()); + static std::atomic error_count(0); + size_t error_count_snapshot = error_count.fetch_add(1, std::memory_order_relaxed); + if ((error_count_snapshot & (error_count_snapshot-1)) == 0) + syslog(LOG_ERR, "dynamic_cast error 2: One or more of the following type_info's " + "has hidden visibility or is defined in more than one translation " + "unit. They should all have public visibility. " + "%s, %s, %s.\n", static_type->name(), dynamic_type->name(), + dst_type->name()); // Redo the search comparing type_info's using strcmp info = {dst_type, static_ptr, static_type, src2dst_offset, 0}; dynamic_type->search_below_dst(&info, dynamic_ptr, public_path, true); } -#endif // _LIBCXX_DYNAMIC_FALLBACK +#endif // _LIBCXXABI_FORGIVING_DYNAMIC_CAST // Query the search. switch (info.number_to_static_ptr) { diff --git a/lib/libcxxabi/src/stdlib_new_delete.cpp b/lib/libcxxabi/src/stdlib_new_delete.cpp new file mode 100644 index 0000000000..698c5f7c29 --- /dev/null +++ b/lib/libcxxabi/src/stdlib_new_delete.cpp @@ -0,0 +1,262 @@ +//===--------------------- stdlib_new_delete.cpp --------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// +// This file implements the new and delete operators. +//===----------------------------------------------------------------------===// + +#define _LIBCPP_BUILDING_LIBRARY +#include "__cxxabi_config.h" +#include +#include + +#if !defined(_THROW_BAD_ALLOC) || !defined(_NOEXCEPT) || !defined(_LIBCXXABI_WEAK) +#error The _THROW_BAD_ALLOC, _NOEXCEPT, and _LIBCXXABI_WEAK libc++ macros must \ + already be defined by libc++. +#endif +// 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. + +_LIBCXXABI_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 _LIBCXXABI_NO_EXCEPTIONS + throw std::bad_alloc(); +#else + break; +#endif + } + return p; +} + +_LIBCXXABI_WEAK +void* +operator new(size_t size, const std::nothrow_t&) _NOEXCEPT +{ + void* p = 0; +#ifndef _LIBCXXABI_NO_EXCEPTIONS + try + { +#endif // _LIBCXXABI_NO_EXCEPTIONS + p = ::operator new(size); +#ifndef _LIBCXXABI_NO_EXCEPTIONS + } + catch (...) + { + } +#endif // _LIBCXXABI_NO_EXCEPTIONS + return p; +} + +_LIBCXXABI_WEAK +void* +operator new[](size_t size) _THROW_BAD_ALLOC +{ + return ::operator new(size); +} + +_LIBCXXABI_WEAK +void* +operator new[](size_t size, const std::nothrow_t&) _NOEXCEPT +{ + void* p = 0; +#ifndef _LIBCXXABI_NO_EXCEPTIONS + try + { +#endif // _LIBCXXABI_NO_EXCEPTIONS + p = ::operator new[](size); +#ifndef _LIBCXXABI_NO_EXCEPTIONS + } + catch (...) + { + } +#endif // _LIBCXXABI_NO_EXCEPTIONS + return p; +} + +_LIBCXXABI_WEAK +void +operator delete(void* ptr) _NOEXCEPT +{ + if (ptr) + ::free(ptr); +} + +_LIBCXXABI_WEAK +void +operator delete(void* ptr, const std::nothrow_t&) _NOEXCEPT +{ + ::operator delete(ptr); +} + +_LIBCXXABI_WEAK +void +operator delete(void* ptr, size_t) _NOEXCEPT +{ + ::operator delete(ptr); +} + +_LIBCXXABI_WEAK +void +operator delete[] (void* ptr) _NOEXCEPT +{ + ::operator delete(ptr); +} + +_LIBCXXABI_WEAK +void +operator delete[] (void* ptr, const std::nothrow_t&) _NOEXCEPT +{ + ::operator delete[](ptr); +} + +_LIBCXXABI_WEAK +void +operator delete[] (void* ptr, size_t) _NOEXCEPT +{ + ::operator delete[](ptr); +} + +#if !defined(_LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION) + +_LIBCXXABI_WEAK +void * +operator new(std::size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC +{ + if (size == 0) + size = 1; + if (static_cast(alignment) < sizeof(void*)) + alignment = std::align_val_t(sizeof(void*)); + void* p; +#if defined(_LIBCPP_WIN32API) + while ((p = _aligned_malloc(size, static_cast(alignment))) == nullptr) +#else + while (::posix_memalign(&p, static_cast(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 _LIBCXXABI_NO_EXCEPTIONS + throw std::bad_alloc(); +#else + p = nullptr; // posix_memalign doesn't initialize 'p' on failure + break; +#endif + } + } + return p; +} + +_LIBCXXABI_WEAK +void* +operator new(size_t size, std::align_val_t alignment, const std::nothrow_t&) _NOEXCEPT +{ + void* p = 0; +#ifndef _LIBCXXABI_NO_EXCEPTIONS + try + { +#endif // _LIBCXXABI_NO_EXCEPTIONS + p = ::operator new(size, alignment); +#ifndef _LIBCXXABI_NO_EXCEPTIONS + } + catch (...) + { + } +#endif // _LIBCXXABI_NO_EXCEPTIONS + return p; +} + +_LIBCXXABI_WEAK +void* +operator new[](size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC +{ + return ::operator new(size, alignment); +} + +_LIBCXXABI_WEAK +void* +operator new[](size_t size, std::align_val_t alignment, const std::nothrow_t&) _NOEXCEPT +{ + void* p = 0; +#ifndef _LIBCXXABI_NO_EXCEPTIONS + try + { +#endif // _LIBCXXABI_NO_EXCEPTIONS + p = ::operator new[](size, alignment); +#ifndef _LIBCXXABI_NO_EXCEPTIONS + } + catch (...) + { + } +#endif // _LIBCXXABI_NO_EXCEPTIONS + return p; +} + +_LIBCXXABI_WEAK +void +operator delete(void* ptr, std::align_val_t) _NOEXCEPT +{ + if (ptr) +#if defined(_LIBCPP_WIN32API) + ::_aligned_free(ptr); +#else + ::free(ptr); +#endif +} + +_LIBCXXABI_WEAK +void +operator delete(void* ptr, std::align_val_t alignment, const std::nothrow_t&) _NOEXCEPT +{ + ::operator delete(ptr, alignment); +} + +_LIBCXXABI_WEAK +void +operator delete(void* ptr, size_t, std::align_val_t alignment) _NOEXCEPT +{ + ::operator delete(ptr, alignment); +} + +_LIBCXXABI_WEAK +void +operator delete[] (void* ptr, std::align_val_t alignment) _NOEXCEPT +{ + ::operator delete(ptr, alignment); +} + +_LIBCXXABI_WEAK +void +operator delete[] (void* ptr, std::align_val_t alignment, const std::nothrow_t&) _NOEXCEPT +{ + ::operator delete[](ptr, alignment); +} + +_LIBCXXABI_WEAK +void +operator delete[] (void* ptr, size_t, std::align_val_t alignment) _NOEXCEPT +{ + ::operator delete[](ptr, alignment); +} + +#endif // !_LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION