libcxxabi: update to LLVM 17

release/17.x branch, commit 8f4dd44097c9ae25dd203d5ac87f3b48f854bba8
This commit is contained in:
Andrew Kelley 2023-08-11 17:22:29 -07:00
parent 571a4c86c3
commit 9ddfacd8e6
13 changed files with 461 additions and 408 deletions

View File

@ -32,7 +32,7 @@
#endif #endif
#if defined(_WIN32) #if defined(_WIN32)
#if defined(_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS) #if defined(_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS) || (defined(__MINGW32__) && !defined(_LIBCXXABI_BUILDING_LIBRARY))
#define _LIBCXXABI_HIDDEN #define _LIBCXXABI_HIDDEN
#define _LIBCXXABI_DATA_VIS #define _LIBCXXABI_DATA_VIS
#define _LIBCXXABI_FUNC_VIS #define _LIBCXXABI_FUNC_VIS

View File

@ -14,10 +14,6 @@
#include <stdio.h> #include <stdio.h>
#include <sys/debug.h> #include <sys/debug.h>
#if !__has_cpp_attribute(clang::optnone)
#error This file requires clang::optnone attribute support
#endif
/* /*
The legacy IBM xlC and xlclang++ compilers use the state table for EH The legacy IBM xlC and xlclang++ compilers use the state table for EH
instead of the range table. Destructors, or addresses of the possible catch instead of the range table. Destructors, or addresses of the possible catch
@ -563,7 +559,8 @@ __xlcxx_personality_v0(int version, _Unwind_Action actions, uint64_t exceptionCl
uintptr_t *currentSP = reinterpret_cast<uintptr_t*>(_Unwind_GetGR(context, 1)); uintptr_t *currentSP = reinterpret_cast<uintptr_t*>(_Unwind_GetGR(context, 1));
uintptr_t *callersSP = reinterpret_cast<uintptr_t*>(currentSP[0]); uintptr_t *callersSP = reinterpret_cast<uintptr_t*>(currentSP[0]);
callersSP[3] = reinterpret_cast<uintptr_t>(unwind_exception); callersSP[3] = reinterpret_cast<uintptr_t>(unwind_exception);
_LIBCXXABI_TRACE_STATETAB("Handshake: set unwind_exception=%p in stack=%p\n", reinterpret_cast<void*>(unwind_exception), reinterpret_cast<void*>(callersSP)); _LIBCXXABI_TRACE_STATETAB("Handshake: save unwind_exception=%p in stack=%p\n",
reinterpret_cast<void*>(unwind_exception), reinterpret_cast<void*>(callersSP));
// Jump to the handler. // Jump to the handler.
_Unwind_SetIP(context, results.landingPad); _Unwind_SetIP(context, results.landingPad);
return _URC_INSTALL_CONTEXT; return _URC_INSTALL_CONTEXT;
@ -641,38 +638,68 @@ _LIBCXXABI_FUNC_VIS void __xlc_throw_badexception() {
__cxa_throw(newexception, const_cast<std::type_info*>(&typeid(std::bad_exception)), 0); __cxa_throw(newexception, const_cast<std::type_info*>(&typeid(std::bad_exception)), 0);
} }
// force_a_stackframe // skip_non_cxx_eh_aware_frames
// This function is called by __xlc_exception_handle() to ensure a stack frame // This function skips non-C++ EH aware stack frames by unwinding from the
// is created for __xlc_exception_handle(). // stack frame pointed by 'Sp' and returns the first C++ EH aware stack frame
__attribute__((noinline, optnone)) // found. 'Pc' is an instruction address inside the function that owns the
static void force_a_stackframe() {} // stack frame pointed to by 'Sp'.
static uintptr_t* skip_non_cxx_eh_aware_frames(uint32_t* Pc, uintptr_t* Sp) {
uint32_t* currentPc = Pc;
uintptr_t* currentStack = Sp;
// Loop until a C++ EH aware frame is found or the return address is 0,
// which is the return address of the startup function '__start'.
while (currentPc != 0) {
uint32_t* p = currentPc;
// Keep looking forward until a word of 0 is found. The traceback
// table starts at the following word.
while (*p)
++p;
tbtable* TBTable = reinterpret_cast<tbtable*>(p + 1);
// A stack frame with a C++ state table is C++ EH aware.
if (TBTable->tb.lang == TB_CPLUSPLUS && TBTable->tb.has_ctl)
return currentStack;
// Move up one stack frame.
currentStack = reinterpret_cast<uintptr_t*>(currentStack[0]);
// Get the value of the LR (saved, prior to incrementing the SP, by the
// prolog of the function just inspected) from the frame.
currentPc = reinterpret_cast<uint32_t*>(currentStack[2]);
}
// This should not happen.
_LIBCXXABI_TRACE_STATETAB0("skip_non_cxx_eh_aware_frames() reached the end of stack frames, aborting\n");
abort();
}
// __xlc_exception_handle // __xlc_exception_handle
// This function is for xlclang++. It returns the address of the exception // This function is for xlclang++. It returns the address of the exception
// object stored in the reserved field in the stack of the caller of the // object stored in the reserved field in the stack of the caller of the
// function that calls __xlc_exception_handle() (within the link area for the // function that calls __xlc_exception_handle() (within the link area for the
// call to the latter). The address is stored by the personality routine for // call to the latter). The address is stored by the personality routine for
// xlclang++ compiled code. The implementation of __xlc_exception_handle() // xlclang++ compiled code. If __xlc_exception_handle() is called by
// assumes a stack frame is created for it. The following ensures this // non-C++ EH aware functions, their frames are skipped until a C++ EH aware
// assumption holds true: 1) a call to force_a_stackframe() is made inside // frame is found.
// __xlc_exception_handle() to make it non-leaf; and 2) optimizations are // Note: make sure __xlc_excpetion_handle() is a non-leaf function. Currently
// disabled for this function with attribute 'optnone'. Note: this function // it calls skip_non_cxx_eh_aware_frames(), which in turn calls abort().
// may not work as expected if these are changed.
__attribute__((optnone))
_LIBCXXABI_FUNC_VIS uintptr_t __xlc_exception_handle() { _LIBCXXABI_FUNC_VIS uintptr_t __xlc_exception_handle() {
// Make a call to force_a_stackframe() so that the compiler creates a stack
// frame for this function.
force_a_stackframe();
// Get the SP of this function, i.e., __xlc_exception_handle(). // Get the SP of this function, i.e., __xlc_exception_handle().
uintptr_t *lastStack; uintptr_t* lastStack = reinterpret_cast<uintptr_t*>(__builtin_frame_address(0));
asm("mr %0, 1" : "=r"(lastStack)); // Move one frame up to the frame of the caller of __xlc_exception_handle().
// Get the SP of the caller of __xlc_exception_handle(). lastStack = reinterpret_cast<uintptr_t*>(lastStack[0]);
uintptr_t *callerStack = reinterpret_cast<uintptr_t*>(lastStack[0]); // Get the return address of this function, i.e., __xlc_exception_handle().
// Get the SP of the caller of the caller. uint32_t* returnAddress = reinterpret_cast<uint32_t*>(__builtin_return_address(0));
uintptr_t *callerStack2 = reinterpret_cast<uintptr_t*>(callerStack[0]);
uintptr_t exceptionObject = callerStack2[3]; // Skip non-C++ EH aware frames and get the first C++ EH aware frame.
_LIBCXXABI_TRACE_STATETAB("Handshake: exceptionObject=%p from stack=%p\n", reinterpret_cast<void*>(exceptionObject), reinterpret_cast<void*>(callerStack2)); uintptr_t* callerStack = skip_non_cxx_eh_aware_frames(returnAddress, lastStack);
// Get the SP of the caller of the C++ EH aware caller.
callerStack = reinterpret_cast<uintptr_t*>(callerStack[0]);
// Retrieve the exception object in the stack slot saved by the personality.
uintptr_t exceptionObject = callerStack[3];
_LIBCXXABI_TRACE_STATETAB("Handshake: retrieve exceptionObject=%p from stack=%p\n",
reinterpret_cast<void*>(exceptionObject), reinterpret_cast<void*>(callerStack));
return exceptionObject; return exceptionObject;
} }

View File

@ -10,6 +10,7 @@
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "cxxabi.h" #include "cxxabi.h"
#include <exception>
#include <new> #include <new>
#include <typeinfo> #include <typeinfo>

View File

@ -10,6 +10,7 @@
// file does not yet support: // file does not yet support:
// - C++ modules TS // - C++ modules TS
#include "demangle/DemangleConfig.h"
#include "demangle/ItaniumDemangle.h" #include "demangle/ItaniumDemangle.h"
#include "__cxxabi_config.h" #include "__cxxabi_config.h"
#include <cassert> #include <cassert>
@ -19,6 +20,7 @@
#include <cstring> #include <cstring>
#include <functional> #include <functional>
#include <numeric> #include <numeric>
#include <string_view>
#include <utility> #include <utility>
using namespace itanium_demangle; using namespace itanium_demangle;
@ -77,8 +79,8 @@ struct DumpVisitor {
} }
void printStr(const char *S) { fprintf(stderr, "%s", S); } void printStr(const char *S) { fprintf(stderr, "%s", S); }
void print(StringView SV) { void print(std::string_view SV) {
fprintf(stderr, "\"%.*s\"", (int)SV.size(), SV.begin()); fprintf(stderr, "\"%.*s\"", (int)SV.size(), &*SV.begin());
} }
void print(const Node *N) { void print(const Node *N) {
if (N) if (N)

View File

@ -255,7 +255,7 @@ struct InitByteNoThreads {
if (*init_byte_address == COMPLETE_BIT) if (*init_byte_address == COMPLETE_BIT)
return true; return true;
if (*init_byte_address & PENDING_BIT) if (*init_byte_address & PENDING_BIT)
ABORT_WITH_MESSAGE("__cxa_guard_acquire detected recursive initialization"); ABORT_WITH_MESSAGE("__cxa_guard_acquire detected recursive initialization: do you have a function-local static variable whose initialization depends on that function?");
*init_byte_address = PENDING_BIT; *init_byte_address = PENDING_BIT;
return false; return false;
} }
@ -325,7 +325,7 @@ public:
// Check for possible recursive initialization. // Check for possible recursive initialization.
if (has_thread_id_support && (*init_byte_address & PENDING_BIT)) { if (has_thread_id_support && (*init_byte_address & PENDING_BIT)) {
if (*thread_id_address == current_thread_id.get()) if (*thread_id_address == current_thread_id.get())
ABORT_WITH_MESSAGE("__cxa_guard_acquire detected recursive initialization"); ABORT_WITH_MESSAGE("__cxa_guard_acquire detected recursive initialization: do you have a function-local static variable whose initialization depends on that function?");
} }
// Wait until the pending bit is not set. // Wait until the pending bit is not set.
@ -460,7 +460,7 @@ public:
// Check for recursive initialization // Check for recursive initialization
if (has_thread_id_support && thread_id.load(std::_AO_Relaxed) == current_thread_id.get()) { if (has_thread_id_support && thread_id.load(std::_AO_Relaxed) == current_thread_id.get()) {
ABORT_WITH_MESSAGE("__cxa_guard_acquire detected recursive initialization"); ABORT_WITH_MESSAGE("__cxa_guard_acquire detected recursive initialization: do you have a function-local static variable whose initialization depends on that function?");
} }
if ((last_val & WAITING_BIT) == 0) { if ((last_val & WAITING_BIT) == 0) {

View File

@ -11,6 +11,14 @@
#ifndef LIBCXXABI_DEMANGLE_DEMANGLE_CONFIG_H #ifndef LIBCXXABI_DEMANGLE_DEMANGLE_CONFIG_H
#define LIBCXXABI_DEMANGLE_DEMANGLE_CONFIG_H #define LIBCXXABI_DEMANGLE_DEMANGLE_CONFIG_H
// Must be defined before pulling in headers from libc++. Allow downstream
// build systems to override this value.
// https://libcxx.llvm.org/UsingLibcxx.html#enabling-the-safe-libc-mode
#ifndef _LIBCPP_VERBOSE_ABORT
#define _LIBCPP_VERBOSE_ABORT(...) abort_message(__VA_ARGS__)
#include "../abort_message.h"
#endif
#include <ciso646> #include <ciso646>
#ifdef _MSC_VER #ifdef _MSC_VER

View File

@ -17,8 +17,9 @@
#define DEMANGLE_ITANIUMDEMANGLE_H #define DEMANGLE_ITANIUMDEMANGLE_H
#include "DemangleConfig.h" #include "DemangleConfig.h"
#include "StringView.h" #include "StringViewExtras.h"
#include "Utility.h" #include "Utility.h"
#include <__cxxabi_config.h>
#include <algorithm> #include <algorithm>
#include <cassert> #include <cassert>
#include <cctype> #include <cctype>
@ -27,8 +28,15 @@
#include <cstring> #include <cstring>
#include <limits> #include <limits>
#include <new> #include <new>
#include <string_view>
#include <type_traits>
#include <utility> #include <utility>
#ifdef _LIBCXXABI_COMPILER_CLANG
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-template"
#endif
DEMANGLE_NAMESPACE_BEGIN DEMANGLE_NAMESPACE_BEGIN
template <class T, size_t N> class PODSmallVector { template <class T, size_t N> class PODSmallVector {
@ -286,7 +294,7 @@ public:
// implementation. // implementation.
virtual void printRight(OutputBuffer &) const {} virtual void printRight(OutputBuffer &) const {}
virtual StringView getBaseName() const { return StringView(); } virtual std::string_view getBaseName() const { return {}; }
// Silence compiler warnings, this dtor will never be called. // Silence compiler warnings, this dtor will never be called.
virtual ~Node() = default; virtual ~Node() = default;
@ -345,10 +353,10 @@ struct NodeArrayNode : Node {
class DotSuffix final : public Node { class DotSuffix final : public Node {
const Node *Prefix; const Node *Prefix;
const StringView Suffix; const std::string_view Suffix;
public: public:
DotSuffix(const Node *Prefix_, StringView Suffix_) DotSuffix(const Node *Prefix_, std::string_view Suffix_)
: Node(KDotSuffix), Prefix(Prefix_), Suffix(Suffix_) {} : Node(KDotSuffix), Prefix(Prefix_), Suffix(Suffix_) {}
template<typename Fn> void match(Fn F) const { F(Prefix, Suffix); } template<typename Fn> void match(Fn F) const { F(Prefix, Suffix); }
@ -363,15 +371,15 @@ public:
class VendorExtQualType final : public Node { class VendorExtQualType final : public Node {
const Node *Ty; const Node *Ty;
StringView Ext; std::string_view Ext;
const Node *TA; const Node *TA;
public: public:
VendorExtQualType(const Node *Ty_, StringView Ext_, const Node *TA_) VendorExtQualType(const Node *Ty_, std::string_view Ext_, const Node *TA_)
: Node(KVendorExtQualType), Ty(Ty_), Ext(Ext_), TA(TA_) {} : Node(KVendorExtQualType), Ty(Ty_), Ext(Ext_), TA(TA_) {}
const Node *getTy() const { return Ty; } const Node *getTy() const { return Ty; }
StringView getExt() const { return Ext; } std::string_view getExt() const { return Ext; }
const Node *getTA() const { return TA; } const Node *getTA() const { return TA; }
template <typename Fn> void match(Fn F) const { F(Ty, Ext, TA); } template <typename Fn> void match(Fn F) const { F(Ty, Ext, TA); }
@ -462,10 +470,10 @@ public:
class PostfixQualifiedType final : public Node { class PostfixQualifiedType final : public Node {
const Node *Ty; const Node *Ty;
const StringView Postfix; const std::string_view Postfix;
public: public:
PostfixQualifiedType(const Node *Ty_, StringView Postfix_) PostfixQualifiedType(const Node *Ty_, std::string_view Postfix_)
: Node(KPostfixQualifiedType), Ty(Ty_), Postfix(Postfix_) {} : Node(KPostfixQualifiedType), Ty(Ty_), Postfix(Postfix_) {}
template<typename Fn> void match(Fn F) const { F(Ty, Postfix); } template<typename Fn> void match(Fn F) const { F(Ty, Postfix); }
@ -477,15 +485,15 @@ public:
}; };
class NameType final : public Node { class NameType final : public Node {
const StringView Name; const std::string_view Name;
public: public:
NameType(StringView Name_) : Node(KNameType), Name(Name_) {} NameType(std::string_view Name_) : Node(KNameType), Name(Name_) {}
template<typename Fn> void match(Fn F) const { F(Name); } template<typename Fn> void match(Fn F) const { F(Name); }
StringView getName() const { return Name; } std::string_view getName() const { return Name; }
StringView getBaseName() const override { return Name; } std::string_view getBaseName() const override { return Name; }
void printLeft(OutputBuffer &OB) const override { OB += Name; } void printLeft(OutputBuffer &OB) const override { OB += Name; }
}; };
@ -511,10 +519,10 @@ public:
}; };
class ElaboratedTypeSpefType : public Node { class ElaboratedTypeSpefType : public Node {
StringView Kind; std::string_view Kind;
Node *Child; Node *Child;
public: public:
ElaboratedTypeSpefType(StringView Kind_, Node *Child_) ElaboratedTypeSpefType(std::string_view Kind_, Node *Child_)
: Node(KElaboratedTypeSpefType), Kind(Kind_), Child(Child_) {} : Node(KElaboratedTypeSpefType), Kind(Kind_), Child(Child_) {}
template<typename Fn> void match(Fn F) const { F(Kind, Child); } template<typename Fn> void match(Fn F) const { F(Kind, Child); }
@ -528,15 +536,17 @@ public:
struct AbiTagAttr : Node { struct AbiTagAttr : Node {
Node *Base; Node *Base;
StringView Tag; std::string_view Tag;
AbiTagAttr(Node* Base_, StringView Tag_) AbiTagAttr(Node *Base_, std::string_view Tag_)
: Node(KAbiTagAttr, Base_->RHSComponentCache, : Node(KAbiTagAttr, Base_->RHSComponentCache, Base_->ArrayCache,
Base_->ArrayCache, Base_->FunctionCache), Base_->FunctionCache),
Base(Base_), Tag(Tag_) {} Base(Base_), Tag(Tag_) {}
template<typename Fn> void match(Fn F) const { F(Base, Tag); } template<typename Fn> void match(Fn F) const { F(Base, Tag); }
std::string_view getBaseName() const override { return Base->getBaseName(); }
void printLeft(OutputBuffer &OB) const override { void printLeft(OutputBuffer &OB) const override {
Base->printLeft(OB); Base->printLeft(OB);
OB += "[abi:"; OB += "[abi:";
@ -562,12 +572,12 @@ public:
class ObjCProtoName : public Node { class ObjCProtoName : public Node {
const Node *Ty; const Node *Ty;
StringView Protocol; std::string_view Protocol;
friend class PointerType; friend class PointerType;
public: public:
ObjCProtoName(const Node *Ty_, StringView Protocol_) ObjCProtoName(const Node *Ty_, std::string_view Protocol_)
: Node(KObjCProtoName), Ty(Ty_), Protocol(Protocol_) {} : Node(KObjCProtoName), Ty(Ty_), Protocol(Protocol_) {}
template<typename Fn> void match(Fn F) const { F(Ty, Protocol); } template<typename Fn> void match(Fn F) const { F(Ty, Protocol); }
@ -944,11 +954,11 @@ public:
}; };
class SpecialName final : public Node { class SpecialName final : public Node {
const StringView Special; const std::string_view Special;
const Node *Child; const Node *Child;
public: public:
SpecialName(StringView Special_, const Node *Child_) SpecialName(std::string_view Special_, const Node *Child_)
: Node(KSpecialName), Special(Special_), Child(Child_) {} : Node(KSpecialName), Special(Special_), Child(Child_) {}
template<typename Fn> void match(Fn F) const { F(Special, Child); } template<typename Fn> void match(Fn F) const { F(Special, Child); }
@ -987,7 +997,7 @@ struct NestedName : Node {
template<typename Fn> void match(Fn F) const { F(Qual, Name); } template<typename Fn> void match(Fn F) const { F(Qual, Name); }
StringView getBaseName() const override { return Name->getBaseName(); } std::string_view getBaseName() const override { return Name->getBaseName(); }
void printLeft(OutputBuffer &OB) const override { void printLeft(OutputBuffer &OB) const override {
Qual->print(OB); Qual->print(OB);
@ -1027,7 +1037,7 @@ struct ModuleEntity : Node {
template <typename Fn> void match(Fn F) const { F(Module, Name); } template <typename Fn> void match(Fn F) const { F(Module, Name); }
StringView getBaseName() const override { return Name->getBaseName(); } std::string_view getBaseName() const override { return Name->getBaseName(); }
void printLeft(OutputBuffer &OB) const override { void printLeft(OutputBuffer &OB) const override {
Name->print(OB); Name->print(OB);
@ -1063,7 +1073,7 @@ public:
template<typename Fn> void match(Fn F) const { F(Qualifier, Name); } template<typename Fn> void match(Fn F) const { F(Qualifier, Name); }
StringView getBaseName() const override { return Name->getBaseName(); } std::string_view getBaseName() const override { return Name->getBaseName(); }
void printLeft(OutputBuffer &OB) const override { void printLeft(OutputBuffer &OB) const override {
Qualifier->print(OB); Qualifier->print(OB);
@ -1485,7 +1495,7 @@ struct NameWithTemplateArgs : Node {
template<typename Fn> void match(Fn F) const { F(Name, TemplateArgs); } template<typename Fn> void match(Fn F) const { F(Name, TemplateArgs); }
StringView getBaseName() const override { return Name->getBaseName(); } std::string_view getBaseName() const override { return Name->getBaseName(); }
void printLeft(OutputBuffer &OB) const override { void printLeft(OutputBuffer &OB) const override {
Name->print(OB); Name->print(OB);
@ -1502,7 +1512,7 @@ public:
template<typename Fn> void match(Fn F) const { F(Child); } template<typename Fn> void match(Fn F) const { F(Child); }
StringView getBaseName() const override { return Child->getBaseName(); } std::string_view getBaseName() const override { return Child->getBaseName(); }
void printLeft(OutputBuffer &OB) const override { void printLeft(OutputBuffer &OB) const override {
OB += "::"; OB += "::";
@ -1538,20 +1548,20 @@ protected:
return unsigned(SSK) >= unsigned(SpecialSubKind::string); return unsigned(SSK) >= unsigned(SpecialSubKind::string);
} }
StringView getBaseName() const override { std::string_view getBaseName() const override {
switch (SSK) { switch (SSK) {
case SpecialSubKind::allocator: case SpecialSubKind::allocator:
return StringView("allocator"); return {"allocator"};
case SpecialSubKind::basic_string: case SpecialSubKind::basic_string:
return StringView("basic_string"); return {"basic_string"};
case SpecialSubKind::string: case SpecialSubKind::string:
return StringView("basic_string"); return {"basic_string"};
case SpecialSubKind::istream: case SpecialSubKind::istream:
return StringView("basic_istream"); return {"basic_istream"};
case SpecialSubKind::ostream: case SpecialSubKind::ostream:
return StringView("basic_ostream"); return {"basic_ostream"};
case SpecialSubKind::iostream: case SpecialSubKind::iostream:
return StringView("basic_iostream"); return {"basic_iostream"};
} }
DEMANGLE_UNREACHABLE; DEMANGLE_UNREACHABLE;
} }
@ -1575,12 +1585,12 @@ public:
template<typename Fn> void match(Fn F) const { F(SSK); } template<typename Fn> void match(Fn F) const { F(SSK); }
StringView getBaseName() const override { std::string_view getBaseName() const override {
auto SV = ExpandedSpecialSubstitution::getBaseName (); std::string_view SV = ExpandedSpecialSubstitution::getBaseName();
if (isInstantiation()) { if (isInstantiation()) {
// The instantiations are typedefs that drop the "basic_" prefix. // The instantiations are typedefs that drop the "basic_" prefix.
assert(SV.startsWith("basic_")); assert(starts_with(SV, "basic_"));
SV = SV.dropFront(sizeof("basic_") - 1); SV.remove_prefix(sizeof("basic_") - 1);
} }
return SV; return SV;
} }
@ -1628,10 +1638,11 @@ public:
}; };
class UnnamedTypeName : public Node { class UnnamedTypeName : public Node {
const StringView Count; const std::string_view Count;
public: public:
UnnamedTypeName(StringView Count_) : Node(KUnnamedTypeName), Count(Count_) {} UnnamedTypeName(std::string_view Count_)
: Node(KUnnamedTypeName), Count(Count_) {}
template<typename Fn> void match(Fn F) const { F(Count); } template<typename Fn> void match(Fn F) const { F(Count); }
@ -1645,11 +1656,11 @@ public:
class ClosureTypeName : public Node { class ClosureTypeName : public Node {
NodeArray TemplateParams; NodeArray TemplateParams;
NodeArray Params; NodeArray Params;
StringView Count; std::string_view Count;
public: public:
ClosureTypeName(NodeArray TemplateParams_, NodeArray Params_, ClosureTypeName(NodeArray TemplateParams_, NodeArray Params_,
StringView Count_) std::string_view Count_)
: Node(KClosureTypeName), TemplateParams(TemplateParams_), : Node(KClosureTypeName), TemplateParams(TemplateParams_),
Params(Params_), Count(Count_) {} Params(Params_), Count(Count_) {}
@ -1696,12 +1707,12 @@ public:
class BinaryExpr : public Node { class BinaryExpr : public Node {
const Node *LHS; const Node *LHS;
const StringView InfixOperator; const std::string_view InfixOperator;
const Node *RHS; const Node *RHS;
public: public:
BinaryExpr(const Node *LHS_, StringView InfixOperator_, const Node *RHS_, BinaryExpr(const Node *LHS_, std::string_view InfixOperator_,
Prec Prec_) const Node *RHS_, Prec Prec_)
: Node(KBinaryExpr, Prec_), LHS(LHS_), InfixOperator(InfixOperator_), : Node(KBinaryExpr, Prec_), LHS(LHS_), InfixOperator(InfixOperator_),
RHS(RHS_) {} RHS(RHS_) {}
@ -1750,10 +1761,10 @@ public:
class PostfixExpr : public Node { class PostfixExpr : public Node {
const Node *Child; const Node *Child;
const StringView Operator; const std::string_view Operator;
public: public:
PostfixExpr(const Node *Child_, StringView Operator_, Prec Prec_) PostfixExpr(const Node *Child_, std::string_view Operator_, Prec Prec_)
: Node(KPostfixExpr, Prec_), Child(Child_), Operator(Operator_) {} : Node(KPostfixExpr, Prec_), Child(Child_), Operator(Operator_) {}
template <typename Fn> void match(Fn F) const { template <typename Fn> void match(Fn F) const {
@ -1791,11 +1802,12 @@ public:
class MemberExpr : public Node { class MemberExpr : public Node {
const Node *LHS; const Node *LHS;
const StringView Kind; const std::string_view Kind;
const Node *RHS; const Node *RHS;
public: public:
MemberExpr(const Node *LHS_, StringView Kind_, const Node *RHS_, Prec Prec_) MemberExpr(const Node *LHS_, std::string_view Kind_, const Node *RHS_,
Prec Prec_)
: Node(KMemberExpr, Prec_), LHS(LHS_), Kind(Kind_), RHS(RHS_) {} : Node(KMemberExpr, Prec_), LHS(LHS_), Kind(Kind_), RHS(RHS_) {}
template <typename Fn> void match(Fn F) const { template <typename Fn> void match(Fn F) const {
@ -1812,13 +1824,14 @@ public:
class SubobjectExpr : public Node { class SubobjectExpr : public Node {
const Node *Type; const Node *Type;
const Node *SubExpr; const Node *SubExpr;
StringView Offset; std::string_view Offset;
NodeArray UnionSelectors; NodeArray UnionSelectors;
bool OnePastTheEnd; bool OnePastTheEnd;
public: public:
SubobjectExpr(const Node *Type_, const Node *SubExpr_, StringView Offset_, SubobjectExpr(const Node *Type_, const Node *SubExpr_,
NodeArray UnionSelectors_, bool OnePastTheEnd_) std::string_view Offset_, NodeArray UnionSelectors_,
bool OnePastTheEnd_)
: Node(KSubobjectExpr), Type(Type_), SubExpr(SubExpr_), Offset(Offset_), : Node(KSubobjectExpr), Type(Type_), SubExpr(SubExpr_), Offset(Offset_),
UnionSelectors(UnionSelectors_), OnePastTheEnd(OnePastTheEnd_) {} UnionSelectors(UnionSelectors_), OnePastTheEnd(OnePastTheEnd_) {}
@ -1835,7 +1848,7 @@ public:
OB += "0"; OB += "0";
} else if (Offset[0] == 'n') { } else if (Offset[0] == 'n') {
OB += "-"; OB += "-";
OB += Offset.dropFront(); OB += std::string_view(Offset.data() + 1, Offset.size() - 1);
} else { } else {
OB += Offset; OB += Offset;
} }
@ -1844,12 +1857,12 @@ public:
}; };
class EnclosingExpr : public Node { class EnclosingExpr : public Node {
const StringView Prefix; const std::string_view Prefix;
const Node *Infix; const Node *Infix;
const StringView Postfix; const std::string_view Postfix;
public: public:
EnclosingExpr(StringView Prefix_, const Node *Infix_, EnclosingExpr(std::string_view Prefix_, const Node *Infix_,
Prec Prec_ = Prec::Primary) Prec Prec_ = Prec::Primary)
: Node(KEnclosingExpr, Prec_), Prefix(Prefix_), Infix(Infix_) {} : Node(KEnclosingExpr, Prec_), Prefix(Prefix_), Infix(Infix_) {}
@ -1868,12 +1881,13 @@ public:
class CastExpr : public Node { class CastExpr : public Node {
// cast_kind<to>(from) // cast_kind<to>(from)
const StringView CastKind; const std::string_view CastKind;
const Node *To; const Node *To;
const Node *From; const Node *From;
public: public:
CastExpr(StringView CastKind_, const Node *To_, const Node *From_, Prec Prec_) CastExpr(std::string_view CastKind_, const Node *To_, const Node *From_,
Prec Prec_)
: Node(KCastExpr, Prec_), CastKind(CastKind_), To(To_), From(From_) {} : Node(KCastExpr, Prec_), CastKind(CastKind_), To(To_), From(From_) {}
template <typename Fn> void match(Fn F) const { template <typename Fn> void match(Fn F) const {
@ -1996,11 +2010,11 @@ public:
}; };
class PrefixExpr : public Node { class PrefixExpr : public Node {
StringView Prefix; std::string_view Prefix;
Node *Child; Node *Child;
public: public:
PrefixExpr(StringView Prefix_, Node *Child_, Prec Prec_) PrefixExpr(std::string_view Prefix_, Node *Child_, Prec Prec_)
: Node(KPrefixExpr, Prec_), Prefix(Prefix_), Child(Child_) {} : Node(KPrefixExpr, Prec_), Prefix(Prefix_), Child(Child_) {}
template <typename Fn> void match(Fn F) const { template <typename Fn> void match(Fn F) const {
@ -2014,10 +2028,11 @@ public:
}; };
class FunctionParam : public Node { class FunctionParam : public Node {
StringView Number; std::string_view Number;
public: public:
FunctionParam(StringView Number_) : Node(KFunctionParam), Number(Number_) {} FunctionParam(std::string_view Number_)
: Node(KFunctionParam), Number(Number_) {}
template<typename Fn> void match(Fn F) const { F(Number); } template<typename Fn> void match(Fn F) const { F(Number); }
@ -2052,11 +2067,11 @@ public:
class PointerToMemberConversionExpr : public Node { class PointerToMemberConversionExpr : public Node {
const Node *Type; const Node *Type;
const Node *SubExpr; const Node *SubExpr;
StringView Offset; std::string_view Offset;
public: public:
PointerToMemberConversionExpr(const Node *Type_, const Node *SubExpr_, PointerToMemberConversionExpr(const Node *Type_, const Node *SubExpr_,
StringView Offset_, Prec Prec_) std::string_view Offset_, Prec Prec_)
: Node(KPointerToMemberConversionExpr, Prec_), Type(Type_), : Node(KPointerToMemberConversionExpr, Prec_), Type(Type_),
SubExpr(SubExpr_), Offset(Offset_) {} SubExpr(SubExpr_), Offset(Offset_) {}
@ -2141,11 +2156,11 @@ public:
class FoldExpr : public Node { class FoldExpr : public Node {
const Node *Pack, *Init; const Node *Pack, *Init;
StringView OperatorName; std::string_view OperatorName;
bool IsLeftFold; bool IsLeftFold;
public: public:
FoldExpr(bool IsLeftFold_, StringView OperatorName_, const Node *Pack_, FoldExpr(bool IsLeftFold_, std::string_view OperatorName_, const Node *Pack_,
const Node *Init_) const Node *Init_)
: Node(KFoldExpr), Pack(Pack_), Init(Init_), OperatorName(OperatorName_), : Node(KFoldExpr), Pack(Pack_), Init(Init_), OperatorName(OperatorName_),
IsLeftFold(IsLeftFold_) {} IsLeftFold(IsLeftFold_) {}
@ -2209,7 +2224,7 @@ public:
template<typename Fn> void match(Fn F) const { F(Value); } template<typename Fn> void match(Fn F) const { F(Value); }
void printLeft(OutputBuffer &OB) const override { void printLeft(OutputBuffer &OB) const override {
OB += Value ? StringView("true") : StringView("false"); OB += Value ? std::string_view("true") : std::string_view("false");
} }
}; };
@ -2247,10 +2262,10 @@ public:
class EnumLiteral : public Node { class EnumLiteral : public Node {
// ty(integer) // ty(integer)
const Node *Ty; const Node *Ty;
StringView Integer; std::string_view Integer;
public: public:
EnumLiteral(const Node *Ty_, StringView Integer_) EnumLiteral(const Node *Ty_, std::string_view Integer_)
: Node(KEnumLiteral), Ty(Ty_), Integer(Integer_) {} : Node(KEnumLiteral), Ty(Ty_), Integer(Integer_) {}
template<typename Fn> void match(Fn F) const { F(Ty, Integer); } template<typename Fn> void match(Fn F) const { F(Ty, Integer); }
@ -2261,18 +2276,18 @@ public:
OB.printClose(); OB.printClose();
if (Integer[0] == 'n') if (Integer[0] == 'n')
OB << "-" << Integer.dropFront(1); OB << '-' << std::string_view(Integer.data() + 1, Integer.size() - 1);
else else
OB << Integer; OB << Integer;
} }
}; };
class IntegerLiteral : public Node { class IntegerLiteral : public Node {
StringView Type; std::string_view Type;
StringView Value; std::string_view Value;
public: public:
IntegerLiteral(StringView Type_, StringView Value_) IntegerLiteral(std::string_view Type_, std::string_view Value_)
: Node(KIntegerLiteral), Type(Type_), Value(Value_) {} : Node(KIntegerLiteral), Type(Type_), Value(Value_) {}
template<typename Fn> void match(Fn F) const { F(Type, Value); } template<typename Fn> void match(Fn F) const { F(Type, Value); }
@ -2284,10 +2299,9 @@ public:
OB.printClose(); OB.printClose();
} }
if (Value[0] == 'n') { if (Value[0] == 'n')
OB += '-'; OB << '-' << std::string_view(Value.data() + 1, Value.size() - 1);
OB += Value.dropFront(1); else
} else
OB += Value; OB += Value;
if (Type.size() <= 3) if (Type.size() <= 3)
@ -2310,29 +2324,26 @@ constexpr Node::Kind getFloatLiteralKind(long double *) {
} }
template <class Float> class FloatLiteralImpl : public Node { template <class Float> class FloatLiteralImpl : public Node {
const StringView Contents; const std::string_view Contents;
static constexpr Kind KindForClass = static constexpr Kind KindForClass =
float_literal_impl::getFloatLiteralKind((Float *)nullptr); float_literal_impl::getFloatLiteralKind((Float *)nullptr);
public: public:
FloatLiteralImpl(StringView Contents_) FloatLiteralImpl(std::string_view Contents_)
: Node(KindForClass), Contents(Contents_) {} : Node(KindForClass), Contents(Contents_) {}
template<typename Fn> void match(Fn F) const { F(Contents); } template<typename Fn> void match(Fn F) const { F(Contents); }
void printLeft(OutputBuffer &OB) const override { void printLeft(OutputBuffer &OB) const override {
const char *first = Contents.begin();
const char *last = Contents.end() + 1;
const size_t N = FloatData<Float>::mangled_size; const size_t N = FloatData<Float>::mangled_size;
if (static_cast<std::size_t>(last - first) > N) { if (Contents.size() >= N) {
last = first + N;
union { union {
Float value; Float value;
char buf[sizeof(Float)]; char buf[sizeof(Float)];
}; };
const char *t = first; const char *t = Contents.data();
const char *last = t + N;
char *e = buf; char *e = buf;
for (; t != last; ++t, ++e) { for (; t != last; ++t, ++e) {
unsigned d1 = isdigit(*t) ? static_cast<unsigned>(*t - '0') unsigned d1 = isdigit(*t) ? static_cast<unsigned>(*t - '0')
@ -2347,7 +2358,7 @@ public:
#endif #endif
char num[FloatData<Float>::max_demangled_size] = {0}; char num[FloatData<Float>::max_demangled_size] = {0};
int n = snprintf(num, sizeof(num), FloatData<Float>::spec, value); int n = snprintf(num, sizeof(num), FloatData<Float>::spec, value);
OB += StringView(num, num + n); OB += std::string_view(num, n);
} }
} }
}; };
@ -2474,8 +2485,8 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {
return res; return res;
} }
bool consumeIf(StringView S) { bool consumeIf(std::string_view S) {
if (StringView(First, Last).startsWith(S)) { if (starts_with(std::string_view(First, Last - First), S)) {
First += S.size(); First += S.size();
return true; return true;
} }
@ -2500,10 +2511,10 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {
size_t numLeft() const { return static_cast<size_t>(Last - First); } size_t numLeft() const { return static_cast<size_t>(Last - First); }
StringView parseNumber(bool AllowNegative = false); std::string_view parseNumber(bool AllowNegative = false);
Qualifiers parseCVQualifiers(); Qualifiers parseCVQualifiers();
bool parsePositiveInteger(size_t *Out); bool parsePositiveInteger(size_t *Out);
StringView parseBareSourceName(); std::string_view parseBareSourceName();
bool parseSeqId(size_t *Out); bool parseSeqId(size_t *Out);
Node *parseSubstitution(); Node *parseSubstitution();
@ -2514,9 +2525,9 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {
/// Parse the <expr> production. /// Parse the <expr> production.
Node *parseExpr(); Node *parseExpr();
Node *parsePrefixExpr(StringView Kind, Node::Prec Prec); Node *parsePrefixExpr(std::string_view Kind, Node::Prec Prec);
Node *parseBinaryExpr(StringView Kind, Node::Prec Prec); Node *parseBinaryExpr(std::string_view Kind, Node::Prec Prec);
Node *parseIntegerLiteral(StringView Lit); Node *parseIntegerLiteral(std::string_view Lit);
Node *parseExprPrimary(); Node *parseExprPrimary();
template <class Float> Node *parseFloatingLiteral(); template <class Float> Node *parseFloatingLiteral();
Node *parseFunctionParam(); Node *parseFunctionParam();
@ -2624,17 +2635,18 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {
bool operator!=(const char *Peek) const { return !this->operator==(Peek); } bool operator!=(const char *Peek) const { return !this->operator==(Peek); }
public: public:
StringView getSymbol() const { std::string_view getSymbol() const {
StringView Res = Name; std::string_view Res = Name;
if (Kind < Unnameable) { if (Kind < Unnameable) {
assert(Res.startsWith("operator") && assert(starts_with(Res, "operator") &&
"operator name does not start with 'operator'"); "operator name does not start with 'operator'");
Res = Res.dropFront(sizeof("operator") - 1); Res.remove_prefix(sizeof("operator") - 1);
Res.consumeFront(' '); if (starts_with(Res, ' '))
Res.remove_prefix(1);
} }
return Res; return Res;
} }
StringView getName() const { return Name; } std::string_view getName() const { return Name; }
OIKind getKind() const { return Kind; } OIKind getKind() const { return Kind; }
bool getFlag() const { return Flag; } bool getFlag() const { return Flag; }
Node::Prec getPrecedence() const { return Prec; } Node::Prec getPrecedence() const { return Prec; }
@ -2854,7 +2866,7 @@ AbstractManglingParser<Derived, Alloc>::parseUnnamedTypeName(NameState *State) {
TemplateParams.clear(); TemplateParams.clear();
if (consumeIf("Ut")) { if (consumeIf("Ut")) {
StringView Count = parseNumber(); std::string_view Count = parseNumber();
if (!consumeIf('_')) if (!consumeIf('_'))
return nullptr; return nullptr;
return make<UnnamedTypeName>(Count); return make<UnnamedTypeName>(Count);
@ -2866,7 +2878,7 @@ AbstractManglingParser<Derived, Alloc>::parseUnnamedTypeName(NameState *State) {
size_t ParamsBegin = Names.size(); size_t ParamsBegin = Names.size();
while (look() == 'T' && while (look() == 'T' &&
StringView("yptn").find(look(1)) != StringView::npos) { std::string_view("yptn").find(look(1)) != std::string_view::npos) {
Node *T = parseTemplateParamDecl(); Node *T = parseTemplateParamDecl();
if (!T) if (!T)
return nullptr; return nullptr;
@ -2909,7 +2921,7 @@ AbstractManglingParser<Derived, Alloc>::parseUnnamedTypeName(NameState *State) {
} }
NodeArray Params = popTrailingNodeArray(ParamsBegin); NodeArray Params = popTrailingNodeArray(ParamsBegin);
StringView Count = parseNumber(); std::string_view Count = parseNumber();
if (!consumeIf('_')) if (!consumeIf('_'))
return nullptr; return nullptr;
return make<ClosureTypeName>(TempParams, Params, Count); return make<ClosureTypeName>(TempParams, Params, Count);
@ -2931,9 +2943,9 @@ Node *AbstractManglingParser<Derived, Alloc>::parseSourceName(NameState *) {
return nullptr; return nullptr;
if (numLeft() < Length || Length == 0) if (numLeft() < Length || Length == 0)
return nullptr; return nullptr;
StringView Name(First, First + Length); std::string_view Name(First, Length);
First += Length; First += Length;
if (Name.startsWith("_GLOBAL__N")) if (starts_with(Name, "_GLOBAL__N"))
return make<NameType>("(anonymous namespace)"); return make<NameType>("(anonymous namespace)");
return make<NameType>(Name); return make<NameType>(Name);
} }
@ -3447,7 +3459,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseUnresolvedName(bool Global) {
template <typename Derived, typename Alloc> template <typename Derived, typename Alloc>
Node *AbstractManglingParser<Derived, Alloc>::parseAbiTags(Node *N) { Node *AbstractManglingParser<Derived, Alloc>::parseAbiTags(Node *N) {
while (consumeIf('B')) { while (consumeIf('B')) {
StringView SN = parseBareSourceName(); std::string_view SN = parseBareSourceName();
if (SN.empty()) if (SN.empty())
return nullptr; return nullptr;
N = make<AbiTagAttr>(N, SN); N = make<AbiTagAttr>(N, SN);
@ -3459,16 +3471,16 @@ Node *AbstractManglingParser<Derived, Alloc>::parseAbiTags(Node *N) {
// <number> ::= [n] <non-negative decimal integer> // <number> ::= [n] <non-negative decimal integer>
template <typename Alloc, typename Derived> template <typename Alloc, typename Derived>
StringView std::string_view
AbstractManglingParser<Alloc, Derived>::parseNumber(bool AllowNegative) { AbstractManglingParser<Alloc, Derived>::parseNumber(bool AllowNegative) {
const char *Tmp = First; const char *Tmp = First;
if (AllowNegative) if (AllowNegative)
consumeIf('n'); consumeIf('n');
if (numLeft() == 0 || !std::isdigit(*First)) if (numLeft() == 0 || !std::isdigit(*First))
return StringView(); return std::string_view();
while (numLeft() != 0 && std::isdigit(*First)) while (numLeft() != 0 && std::isdigit(*First))
++First; ++First;
return StringView(Tmp, First); return std::string_view(Tmp, First - Tmp);
} }
// <positive length number> ::= [0-9]* // <positive length number> ::= [0-9]*
@ -3485,11 +3497,11 @@ bool AbstractManglingParser<Alloc, Derived>::parsePositiveInteger(size_t *Out) {
} }
template <typename Alloc, typename Derived> template <typename Alloc, typename Derived>
StringView AbstractManglingParser<Alloc, Derived>::parseBareSourceName() { std::string_view AbstractManglingParser<Alloc, Derived>::parseBareSourceName() {
size_t Int = 0; size_t Int = 0;
if (parsePositiveInteger(&Int) || numLeft() < Int) if (parsePositiveInteger(&Int) || numLeft() < Int)
return StringView(); return {};
StringView R(First, First + Int); std::string_view R(First, Int);
First += Int; First += Int;
return R; return R;
} }
@ -3673,7 +3685,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parsePointerToMemberType() {
// ::= Te <name> # dependent elaborated type specifier using 'enum' // ::= Te <name> # dependent elaborated type specifier using 'enum'
template <typename Derived, typename Alloc> template <typename Derived, typename Alloc>
Node *AbstractManglingParser<Derived, Alloc>::parseClassEnumType() { Node *AbstractManglingParser<Derived, Alloc>::parseClassEnumType() {
StringView ElabSpef; std::string_view ElabSpef;
if (consumeIf("Ts")) if (consumeIf("Ts"))
ElabSpef = "struct"; ElabSpef = "struct";
else if (consumeIf("Tu")) else if (consumeIf("Tu"))
@ -3697,17 +3709,18 @@ Node *AbstractManglingParser<Derived, Alloc>::parseClassEnumType() {
template <typename Derived, typename Alloc> template <typename Derived, typename Alloc>
Node *AbstractManglingParser<Derived, Alloc>::parseQualifiedType() { Node *AbstractManglingParser<Derived, Alloc>::parseQualifiedType() {
if (consumeIf('U')) { if (consumeIf('U')) {
StringView Qual = parseBareSourceName(); std::string_view Qual = parseBareSourceName();
if (Qual.empty()) if (Qual.empty())
return nullptr; return nullptr;
// extension ::= U <objc-name> <objc-type> # objc-type<identifier> // extension ::= U <objc-name> <objc-type> # objc-type<identifier>
if (Qual.startsWith("objcproto")) { if (starts_with(Qual, "objcproto")) {
StringView ProtoSourceName = Qual.dropFront(std::strlen("objcproto")); constexpr size_t Len = sizeof("objcproto") - 1;
StringView Proto; std::string_view ProtoSourceName(Qual.data() + Len, Qual.size() - Len);
std::string_view Proto;
{ {
ScopedOverride<const char *> SaveFirst(First, ProtoSourceName.begin()), ScopedOverride<const char *> SaveFirst(First, ProtoSourceName.data()),
SaveLast(Last, ProtoSourceName.end()); SaveLast(Last, &*ProtoSourceName.rbegin() + 1);
Proto = parseBareSourceName(); Proto = parseBareSourceName();
} }
if (Proto.empty()) if (Proto.empty())
@ -3875,7 +3888,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseType() {
// <builtin-type> ::= u <source-name> # vendor extended type // <builtin-type> ::= u <source-name> # vendor extended type
case 'u': { case 'u': {
++First; ++First;
StringView Res = parseBareSourceName(); std::string_view Res = parseBareSourceName();
if (Res.empty()) if (Res.empty())
return nullptr; return nullptr;
// Typically, <builtin-type>s are not considered substitution candidates, // Typically, <builtin-type>s are not considered substitution candidates,
@ -4123,7 +4136,8 @@ Node *AbstractManglingParser<Derived, Alloc>::parseType() {
} }
template <typename Derived, typename Alloc> template <typename Derived, typename Alloc>
Node *AbstractManglingParser<Derived, Alloc>::parsePrefixExpr(StringView Kind, Node *
AbstractManglingParser<Derived, Alloc>::parsePrefixExpr(std::string_view Kind,
Node::Prec Prec) { Node::Prec Prec) {
Node *E = getDerived().parseExpr(); Node *E = getDerived().parseExpr();
if (E == nullptr) if (E == nullptr)
@ -4132,7 +4146,8 @@ Node *AbstractManglingParser<Derived, Alloc>::parsePrefixExpr(StringView Kind,
} }
template <typename Derived, typename Alloc> template <typename Derived, typename Alloc>
Node *AbstractManglingParser<Derived, Alloc>::parseBinaryExpr(StringView Kind, Node *
AbstractManglingParser<Derived, Alloc>::parseBinaryExpr(std::string_view Kind,
Node::Prec Prec) { Node::Prec Prec) {
Node *LHS = getDerived().parseExpr(); Node *LHS = getDerived().parseExpr();
if (LHS == nullptr) if (LHS == nullptr)
@ -4144,9 +4159,9 @@ Node *AbstractManglingParser<Derived, Alloc>::parseBinaryExpr(StringView Kind,
} }
template <typename Derived, typename Alloc> template <typename Derived, typename Alloc>
Node * Node *AbstractManglingParser<Derived, Alloc>::parseIntegerLiteral(
AbstractManglingParser<Derived, Alloc>::parseIntegerLiteral(StringView Lit) { std::string_view Lit) {
StringView Tmp = parseNumber(true); std::string_view Tmp = parseNumber(true);
if (!Tmp.empty() && consumeIf('E')) if (!Tmp.empty() && consumeIf('E'))
return make<IntegerLiteral>(Lit, Tmp); return make<IntegerLiteral>(Lit, Tmp);
return nullptr; return nullptr;
@ -4176,7 +4191,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseFunctionParam() {
return make<NameType>("this"); return make<NameType>("this");
if (consumeIf("fp")) { if (consumeIf("fp")) {
parseCVQualifiers(); parseCVQualifiers();
StringView Num = parseNumber(); std::string_view Num = parseNumber();
if (!consumeIf('_')) if (!consumeIf('_'))
return nullptr; return nullptr;
return make<FunctionParam>(Num); return make<FunctionParam>(Num);
@ -4187,7 +4202,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseFunctionParam() {
if (!consumeIf('p')) if (!consumeIf('p'))
return nullptr; return nullptr;
parseCVQualifiers(); parseCVQualifiers();
StringView Num = parseNumber(); std::string_view Num = parseNumber();
if (!consumeIf('_')) if (!consumeIf('_'))
return nullptr; return nullptr;
return make<FunctionParam>(Num); return make<FunctionParam>(Num);
@ -4341,7 +4356,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseExprPrimary() {
Node *T = getDerived().parseType(); Node *T = getDerived().parseType();
if (T == nullptr) if (T == nullptr)
return nullptr; return nullptr;
StringView N = parseNumber(/*AllowNegative=*/true); std::string_view N = parseNumber(/*AllowNegative=*/true);
if (N.empty()) if (N.empty())
return nullptr; return nullptr;
if (!consumeIf('E')) if (!consumeIf('E'))
@ -4464,7 +4479,7 @@ AbstractManglingParser<Derived, Alloc>::parsePointerToMemberConversionExpr(
Node *Expr = getDerived().parseExpr(); Node *Expr = getDerived().parseExpr();
if (!Expr) if (!Expr)
return nullptr; return nullptr;
StringView Offset = getDerived().parseNumber(true); std::string_view Offset = getDerived().parseNumber(true);
if (!consumeIf('E')) if (!consumeIf('E'))
return nullptr; return nullptr;
return make<PointerToMemberConversionExpr>(Ty, Expr, Offset, Prec); return make<PointerToMemberConversionExpr>(Ty, Expr, Offset, Prec);
@ -4482,7 +4497,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseSubobjectExpr() {
Node *Expr = getDerived().parseExpr(); Node *Expr = getDerived().parseExpr();
if (!Expr) if (!Expr)
return nullptr; return nullptr;
StringView Offset = getDerived().parseNumber(true); std::string_view Offset = getDerived().parseNumber(true);
size_t SelectorsBegin = Names.size(); size_t SelectorsBegin = Names.size();
while (consumeIf('_')) { while (consumeIf('_')) {
Node *Selector = make<NameType>(parseNumber()); Node *Selector = make<NameType>(parseNumber());
@ -5141,7 +5156,7 @@ Node *AbstractManglingParser<Alloc, Derived>::parseFloatingLiteral() {
const size_t N = FloatData<Float>::mangled_size; const size_t N = FloatData<Float>::mangled_size;
if (numLeft() <= N) if (numLeft() <= N)
return nullptr; return nullptr;
StringView Data(First, First + N); std::string_view Data(First, N);
for (char C : Data) for (char C : Data)
if (!std::isxdigit(C)) if (!std::isxdigit(C))
return nullptr; return nullptr;
@ -5461,7 +5476,8 @@ Node *AbstractManglingParser<Derived, Alloc>::parse() {
if (Encoding == nullptr) if (Encoding == nullptr)
return nullptr; return nullptr;
if (look() == '.') { if (look() == '.') {
Encoding = make<DotSuffix>(Encoding, StringView(First, Last)); Encoding =
make<DotSuffix>(Encoding, std::string_view(First, Last - First));
First = Last; First = Last;
} }
if (numLeft() != 0) if (numLeft() != 0)
@ -5497,4 +5513,8 @@ struct ManglingParser : AbstractManglingParser<ManglingParser<Alloc>, Alloc> {
DEMANGLE_NAMESPACE_END DEMANGLE_NAMESPACE_END
#ifdef _LIBCXXABI_COMPILER_CLANG
#pragma clang diagnostic pop
#endif
#endif // DEMANGLE_ITANIUMDEMANGLE_H #endif // DEMANGLE_ITANIUMDEMANGLE_H

View File

@ -1,122 +0,0 @@
//===--- StringView.h -------------------------------------------*- C++ -*-===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// FIXME: Use std::string_view instead when we support C++17.
// There are two copies of this file in the source tree. The one under
// libcxxabi is the original and the one under llvm is the copy. Use
// cp-to-llvm.sh to update the copy. See README.txt for more details.
//
//===----------------------------------------------------------------------===//
#ifndef DEMANGLE_STRINGVIEW_H
#define DEMANGLE_STRINGVIEW_H
#include "DemangleConfig.h"
#include <cassert>
#include <cstring>
DEMANGLE_NAMESPACE_BEGIN
class StringView {
const char *First;
const char *Last;
public:
static const size_t npos = ~size_t(0);
template <size_t N>
StringView(const char (&Str)[N]) : First(Str), Last(Str + N - 1) {}
StringView(const char *First_, const char *Last_)
: First(First_), Last(Last_) {}
StringView(const char *First_, size_t Len)
: First(First_), Last(First_ + Len) {}
StringView(const char *Str) : First(Str), Last(Str + std::strlen(Str)) {}
StringView() : First(nullptr), Last(nullptr) {}
StringView substr(size_t Pos, size_t Len = npos) const {
assert(Pos <= size());
if (Len > size() - Pos)
Len = size() - Pos;
return StringView(begin() + Pos, Len);
}
size_t find(char C, size_t From = 0) const {
// Avoid calling memchr with nullptr.
if (From < size()) {
// Just forward to memchr, which is faster than a hand-rolled loop.
if (const void *P = ::memchr(First + From, C, size() - From))
return size_t(static_cast<const char *>(P) - First);
}
return npos;
}
StringView dropFront(size_t N = 1) const {
if (N >= size())
N = size();
return StringView(First + N, Last);
}
StringView dropBack(size_t N = 1) const {
if (N >= size())
N = size();
return StringView(First, Last - N);
}
char front() const {
assert(!empty());
return *begin();
}
char back() const {
assert(!empty());
return *(end() - 1);
}
char popFront() {
assert(!empty());
return *First++;
}
bool consumeFront(char C) {
if (!startsWith(C))
return false;
*this = dropFront(1);
return true;
}
bool consumeFront(StringView S) {
if (!startsWith(S))
return false;
*this = dropFront(S.size());
return true;
}
bool startsWith(char C) const { return !empty() && *begin() == C; }
bool startsWith(StringView Str) const {
if (Str.size() > size())
return false;
return std::strncmp(Str.begin(), begin(), Str.size()) == 0;
}
const char &operator[](size_t Idx) const { return *(begin() + Idx); }
const char *begin() const { return First; }
const char *end() const { return Last; }
size_t size() const { return static_cast<size_t>(Last - First); }
bool empty() const { return First == Last; }
};
inline bool operator==(const StringView &LHS, const StringView &RHS) {
return LHS.size() == RHS.size() &&
std::strncmp(LHS.begin(), RHS.begin(), LHS.size()) == 0;
}
DEMANGLE_NAMESPACE_END
#endif

View File

@ -0,0 +1,38 @@
//===--- StringViewExtras.h -------------------------------------*- C++ -*-===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// There are two copies of this file in the source tree. The one under
// libcxxabi is the original and the one under llvm is the copy. Use
// cp-to-llvm.sh to update the copy. See README.txt for more details.
//
//===----------------------------------------------------------------------===//
#ifndef DEMANGLE_STRINGVIEW_H
#define DEMANGLE_STRINGVIEW_H
#include "DemangleConfig.h"
#include <string_view>
DEMANGLE_NAMESPACE_BEGIN
inline bool starts_with(std::string_view self, char C) noexcept {
return !self.empty() && *self.begin() == C;
}
inline bool starts_with(std::string_view haystack,
std::string_view needle) noexcept {
if (needle.size() > haystack.size())
return false;
haystack.remove_suffix(haystack.size() - needle.size());
return haystack == needle;
}
DEMANGLE_NAMESPACE_END
#endif

View File

@ -16,13 +16,16 @@
#ifndef DEMANGLE_UTILITY_H #ifndef DEMANGLE_UTILITY_H
#define DEMANGLE_UTILITY_H #define DEMANGLE_UTILITY_H
#include "StringView.h" #include "DemangleConfig.h"
#include <array> #include <array>
#include <cassert>
#include <cstdint> #include <cstdint>
#include <cstdlib> #include <cstdlib>
#include <cstring> #include <cstring>
#include <exception> #include <exception>
#include <limits> #include <limits>
#include <string_view>
DEMANGLE_NAMESPACE_BEGIN DEMANGLE_NAMESPACE_BEGIN
@ -64,7 +67,8 @@ class OutputBuffer {
if (isNeg) if (isNeg)
*--TempPtr = '-'; *--TempPtr = '-';
return operator+=(StringView(TempPtr, Temp.data() + Temp.size())); return operator+=(
std::string_view(TempPtr, Temp.data() + Temp.size() - TempPtr));
} }
public: public:
@ -77,7 +81,9 @@ public:
OutputBuffer(const OutputBuffer &) = delete; OutputBuffer(const OutputBuffer &) = delete;
OutputBuffer &operator=(const OutputBuffer &) = delete; OutputBuffer &operator=(const OutputBuffer &) = delete;
operator StringView() const { return StringView(Buffer, CurrentPosition); } operator std::string_view() const {
return std::string_view(Buffer, CurrentPosition);
}
/// If a ParameterPackExpansion (or similar type) is encountered, the offset /// If a ParameterPackExpansion (or similar type) is encountered, the offset
/// into the pack that we're currently printing. /// into the pack that we're currently printing.
@ -99,10 +105,10 @@ public:
*this += Close; *this += Close;
} }
OutputBuffer &operator+=(StringView R) { OutputBuffer &operator+=(std::string_view R) {
if (size_t Size = R.size()) { if (size_t Size = R.size()) {
grow(Size); grow(Size);
std::memcpy(Buffer + CurrentPosition, R.begin(), Size); std::memcpy(Buffer + CurrentPosition, &*R.begin(), Size);
CurrentPosition += Size; CurrentPosition += Size;
} }
return *this; return *this;
@ -114,18 +120,18 @@ public:
return *this; return *this;
} }
OutputBuffer &prepend(StringView R) { OutputBuffer &prepend(std::string_view R) {
size_t Size = R.size(); size_t Size = R.size();
grow(Size); grow(Size);
std::memmove(Buffer + Size, Buffer, CurrentPosition); std::memmove(Buffer + Size, Buffer, CurrentPosition);
std::memcpy(Buffer, R.begin(), Size); std::memcpy(Buffer, &*R.begin(), Size);
CurrentPosition += Size; CurrentPosition += Size;
return *this; return *this;
} }
OutputBuffer &operator<<(StringView R) { return (*this += R); } OutputBuffer &operator<<(std::string_view R) { return (*this += R); }
OutputBuffer &operator<<(char C) { return (*this += C); } OutputBuffer &operator<<(char C) { return (*this += C); }

View File

@ -15,10 +15,10 @@
#endif #endif
#endif #endif
#include <__memory/aligned_alloc.h>
#include <assert.h> #include <assert.h>
#include <stdlib.h> // for malloc, calloc, free #include <stdlib.h> // for malloc, calloc, free
#include <string.h> // for memset #include <string.h> // for memset
#include <new> // for std::__libcpp_aligned_{alloc,free}
// A small, simple heap manager based (loosely) on // A small, simple heap manager based (loosely) on
// the startup heap manager from FreeBSD, optimized for space. // the startup heap manager from FreeBSD, optimized for space.

View File

@ -41,6 +41,7 @@
// Defining _LIBCXXABI_FORGIVING_DYNAMIC_CAST 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. // is_equal() with use_strcmp=false so the string names are not compared.
#include <cstdint>
#include <string.h> #include <string.h>
#ifdef _LIBCXXABI_FORGIVING_DYNAMIC_CAST #ifdef _LIBCXXABI_FORGIVING_DYNAMIC_CAST
@ -656,13 +657,47 @@ __dynamic_cast(const void *static_ptr, const __class_type_info *static_type,
// Find out if we can use a giant short cut in the search // Find out if we can use a giant short cut in the search
if (is_equal(dynamic_type, dst_type, false)) if (is_equal(dynamic_type, dst_type, false))
{ {
// We're downcasting from src_type to the complete object's dynamic
// type. This is a really hot path that can be further optimized
// with the `src2dst_offset` hint.
// In such a case, dynamic_ptr already gives the casting result if the
// casting ever succeeds. All we have to do now is to check
// static_ptr points to a public base sub-object of dynamic_ptr.
if (src2dst_offset >= 0)
{
// The static type is a unique public non-virtual base type of
// dst_type at offset `src2dst_offset` from the origin of dst.
// Note that there might be other non-public static_type bases. The
// hint only guarantees that the public base is non-virtual and
// unique. So we have to check whether static_ptr points to that
// unique public base sub-object.
if (offset_to_derived == -src2dst_offset)
dst_ptr = dynamic_ptr;
}
else if (src2dst_offset == -2)
{
// static_type is not a public base of dst_type.
dst_ptr = nullptr;
}
else
{
// If src2dst_offset == -3, then:
// src_type is a multiple public base type but never a virtual
// base type. We can't conclude that static_ptr points to those
// public base sub-objects because there might be other non-
// public static_type bases. The search is inevitable.
// Fallback to the slow path to check that static_type is a public
// base type of dynamic_type.
// Using giant short cut. Add that information to info. // Using giant short cut. Add that information to info.
info.number_of_dst_type = 1; info.number_of_dst_type = 1;
// Do the search // Do the search
dynamic_type->search_above_dst(&info, dynamic_ptr, dynamic_ptr, public_path, false); dynamic_type->search_above_dst(&info, dynamic_ptr, dynamic_ptr, public_path, false);
#ifdef _LIBCXXABI_FORGIVING_DYNAMIC_CAST #ifdef _LIBCXXABI_FORGIVING_DYNAMIC_CAST
// The following if should always be false because we should definitely // The following if should always be false because we should
// find (static_ptr, static_type), either on a public or private path // definitely find (static_ptr, static_type), either on a public
// or private path
if (info.path_dst_ptr_to_static_ptr == unknown) if (info.path_dst_ptr_to_static_ptr == unknown)
{ {
// We get here only if there is some kind of visibility problem // We get here only if there is some kind of visibility problem
@ -684,13 +719,39 @@ __dynamic_cast(const void *static_ptr, const __class_type_info *static_type,
if (info.path_dst_ptr_to_static_ptr == public_path) if (info.path_dst_ptr_to_static_ptr == public_path)
dst_ptr = dynamic_ptr; dst_ptr = dynamic_ptr;
} }
}
else else
{
if (src2dst_offset >= 0)
{
// Optimize toward downcasting: dst_type has one unique public
// static_type bases. Let's first try to do a downcast before
// falling back to the slow path. The downcast succeeds if there
// is at least one path regardless of visibility from
// dynamic_type to dst_type.
const void* dst_ptr_to_static = reinterpret_cast<const char*>(static_ptr) - src2dst_offset;
if (reinterpret_cast<std::intptr_t>(dst_ptr_to_static) >= reinterpret_cast<std::intptr_t>(dynamic_ptr))
{
// Try to search a path from dynamic_type to dst_type.
__dynamic_cast_info dynamic_to_dst_info = {dynamic_type, dst_ptr_to_static, dst_type, src2dst_offset};
dynamic_to_dst_info.number_of_dst_type = 1;
dynamic_type->search_above_dst(&dynamic_to_dst_info, dynamic_ptr, dynamic_ptr, public_path, false);
if (dynamic_to_dst_info.path_dst_ptr_to_static_ptr != unknown) {
// We have found at least one path from dynamic_ptr to
// dst_ptr. The downcast can succeed.
dst_ptr = dst_ptr_to_static;
}
}
}
if (!dst_ptr)
{ {
// Not using giant short cut. Do the search // Not using giant short cut. Do the search
dynamic_type->search_below_dst(&info, dynamic_ptr, public_path, false); dynamic_type->search_below_dst(&info, dynamic_ptr, public_path, false);
#ifdef _LIBCXXABI_FORGIVING_DYNAMIC_CAST #ifdef _LIBCXXABI_FORGIVING_DYNAMIC_CAST
// The following if should always be false because we should definitely // The following if should always be false because we should
// find (static_ptr, static_type), either on a public or private path // definitely find (static_ptr, static_type), either on a public
// or private path
if (info.path_dst_ptr_to_static_ptr == unknown && if (info.path_dst_ptr_to_static_ptr == unknown &&
info.path_dynamic_ptr_to_static_ptr == unknown) info.path_dynamic_ptr_to_static_ptr == unknown)
{ {
@ -729,6 +790,7 @@ __dynamic_cast(const void *static_ptr, const __class_type_info *static_type,
break; break;
} }
} }
}
return const_cast<void*>(dst_ptr); return const_cast<void*>(dst_ptr);
} }

View File

@ -4,30 +4,40 @@
// See https://llvm.org/LICENSE.txt for license information. // See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
// //
//
// This file implements the new and delete operators.
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "__cxxabi_config.h" #include "__cxxabi_config.h"
#include <new> #include <__memory/aligned_alloc.h>
#include <cstdlib> #include <cstdlib>
#include <new>
#if !defined(_THROW_BAD_ALLOC) || !defined(_LIBCXXABI_WEAK) // Perform a few sanity checks on libc++ and libc++abi macros to ensure that
#error The _THROW_BAD_ALLOC and _LIBCXXABI_WEAK libc++ macros must \ // the code below can be an exact copy of the code in libcxx/src/new.cpp.
already be defined by libc++. #if !defined(_THROW_BAD_ALLOC)
# error The _THROW_BAD_ALLOC macro should be already defined by libc++
#endif #endif
#ifndef _LIBCPP_WEAK
# error The _LIBCPP_WEAK macro should be already defined by libc++
#endif
#if defined(_LIBCXXABI_NO_EXCEPTIONS) != defined(_LIBCPP_HAS_NO_EXCEPTIONS)
# error libc++ and libc++abi seem to disagree on whether exceptions are enabled
#endif
// ------------------ BEGIN COPY ------------------
// Implement all new and delete operators as weak definitions // Implement all new and delete operators as weak definitions
// in this shared library, so that they can be overridden by programs // in this shared library, so that they can be overridden by programs
// that define non-weak copies of the functions. // that define non-weak copies of the functions.
_LIBCXXABI_WEAK _LIBCPP_WEAK
void * void *
operator new(std::size_t size) _THROW_BAD_ALLOC operator new(std::size_t size) _THROW_BAD_ALLOC
{ {
if (size == 0) if (size == 0)
size = 1; size = 1;
void* p; void* p;
while ((p = ::malloc(size)) == nullptr) while ((p = std::malloc(size)) == nullptr)
{ {
// If malloc fails and there is a new_handler, // If malloc fails and there is a new_handler,
// call it to try free up memory. // call it to try free up memory.
@ -35,7 +45,7 @@ operator new(std::size_t size) _THROW_BAD_ALLOC
if (nh) if (nh)
nh(); nh();
else else
#ifndef _LIBCXXABI_NO_EXCEPTIONS #ifndef _LIBCPP_HAS_NO_EXCEPTIONS
throw std::bad_alloc(); throw std::bad_alloc();
#else #else
break; break;
@ -44,87 +54,87 @@ operator new(std::size_t size) _THROW_BAD_ALLOC
return p; return p;
} }
_LIBCXXABI_WEAK _LIBCPP_WEAK
void* void*
operator new(size_t size, const std::nothrow_t&) noexcept operator new(size_t size, const std::nothrow_t&) noexcept
{ {
void* p = nullptr; void* p = nullptr;
#ifndef _LIBCXXABI_NO_EXCEPTIONS #ifndef _LIBCPP_HAS_NO_EXCEPTIONS
try try
{ {
#endif // _LIBCXXABI_NO_EXCEPTIONS #endif // _LIBCPP_HAS_NO_EXCEPTIONS
p = ::operator new(size); p = ::operator new(size);
#ifndef _LIBCXXABI_NO_EXCEPTIONS #ifndef _LIBCPP_HAS_NO_EXCEPTIONS
} }
catch (...) catch (...)
{ {
} }
#endif // _LIBCXXABI_NO_EXCEPTIONS #endif // _LIBCPP_HAS_NO_EXCEPTIONS
return p; return p;
} }
_LIBCXXABI_WEAK _LIBCPP_WEAK
void* void*
operator new[](size_t size) _THROW_BAD_ALLOC operator new[](size_t size) _THROW_BAD_ALLOC
{ {
return ::operator new(size); return ::operator new(size);
} }
_LIBCXXABI_WEAK _LIBCPP_WEAK
void* void*
operator new[](size_t size, const std::nothrow_t&) noexcept operator new[](size_t size, const std::nothrow_t&) noexcept
{ {
void* p = nullptr; void* p = nullptr;
#ifndef _LIBCXXABI_NO_EXCEPTIONS #ifndef _LIBCPP_HAS_NO_EXCEPTIONS
try try
{ {
#endif // _LIBCXXABI_NO_EXCEPTIONS #endif // _LIBCPP_HAS_NO_EXCEPTIONS
p = ::operator new[](size); p = ::operator new[](size);
#ifndef _LIBCXXABI_NO_EXCEPTIONS #ifndef _LIBCPP_HAS_NO_EXCEPTIONS
} }
catch (...) catch (...)
{ {
} }
#endif // _LIBCXXABI_NO_EXCEPTIONS #endif // _LIBCPP_HAS_NO_EXCEPTIONS
return p; return p;
} }
_LIBCXXABI_WEAK _LIBCPP_WEAK
void void
operator delete(void* ptr) noexcept operator delete(void* ptr) noexcept
{ {
::free(ptr); std::free(ptr);
} }
_LIBCXXABI_WEAK _LIBCPP_WEAK
void void
operator delete(void* ptr, const std::nothrow_t&) noexcept operator delete(void* ptr, const std::nothrow_t&) noexcept
{ {
::operator delete(ptr); ::operator delete(ptr);
} }
_LIBCXXABI_WEAK _LIBCPP_WEAK
void void
operator delete(void* ptr, size_t) noexcept operator delete(void* ptr, size_t) noexcept
{ {
::operator delete(ptr); ::operator delete(ptr);
} }
_LIBCXXABI_WEAK _LIBCPP_WEAK
void void
operator delete[] (void* ptr) noexcept operator delete[] (void* ptr) noexcept
{ {
::operator delete(ptr); ::operator delete(ptr);
} }
_LIBCXXABI_WEAK _LIBCPP_WEAK
void void
operator delete[] (void* ptr, const std::nothrow_t&) noexcept operator delete[] (void* ptr, const std::nothrow_t&) noexcept
{ {
::operator delete[](ptr); ::operator delete[](ptr);
} }
_LIBCXXABI_WEAK _LIBCPP_WEAK
void void
operator delete[] (void* ptr, size_t) noexcept operator delete[] (void* ptr, size_t) noexcept
{ {
@ -133,7 +143,7 @@ operator delete[] (void* ptr, size_t) noexcept
#if !defined(_LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION) #if !defined(_LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION)
_LIBCXXABI_WEAK _LIBCPP_WEAK
void * void *
operator new(std::size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC operator new(std::size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC
{ {
@ -155,7 +165,7 @@ operator new(std::size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC
if (nh) if (nh)
nh(); nh();
else { else {
#ifndef _LIBCXXABI_NO_EXCEPTIONS #ifndef _LIBCPP_HAS_NO_EXCEPTIONS
throw std::bad_alloc(); throw std::bad_alloc();
#else #else
break; break;
@ -165,87 +175,87 @@ operator new(std::size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC
return p; return p;
} }
_LIBCXXABI_WEAK _LIBCPP_WEAK
void* void*
operator new(size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept operator new(size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept
{ {
void* p = nullptr; void* p = nullptr;
#ifndef _LIBCXXABI_NO_EXCEPTIONS #ifndef _LIBCPP_HAS_NO_EXCEPTIONS
try try
{ {
#endif // _LIBCXXABI_NO_EXCEPTIONS #endif // _LIBCPP_HAS_NO_EXCEPTIONS
p = ::operator new(size, alignment); p = ::operator new(size, alignment);
#ifndef _LIBCXXABI_NO_EXCEPTIONS #ifndef _LIBCPP_HAS_NO_EXCEPTIONS
} }
catch (...) catch (...)
{ {
} }
#endif // _LIBCXXABI_NO_EXCEPTIONS #endif // _LIBCPP_HAS_NO_EXCEPTIONS
return p; return p;
} }
_LIBCXXABI_WEAK _LIBCPP_WEAK
void* void*
operator new[](size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC operator new[](size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC
{ {
return ::operator new(size, alignment); return ::operator new(size, alignment);
} }
_LIBCXXABI_WEAK _LIBCPP_WEAK
void* void*
operator new[](size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept operator new[](size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept
{ {
void* p = nullptr; void* p = nullptr;
#ifndef _LIBCXXABI_NO_EXCEPTIONS #ifndef _LIBCPP_HAS_NO_EXCEPTIONS
try try
{ {
#endif // _LIBCXXABI_NO_EXCEPTIONS #endif // _LIBCPP_HAS_NO_EXCEPTIONS
p = ::operator new[](size, alignment); p = ::operator new[](size, alignment);
#ifndef _LIBCXXABI_NO_EXCEPTIONS #ifndef _LIBCPP_HAS_NO_EXCEPTIONS
} }
catch (...) catch (...)
{ {
} }
#endif // _LIBCXXABI_NO_EXCEPTIONS #endif // _LIBCPP_HAS_NO_EXCEPTIONS
return p; return p;
} }
_LIBCXXABI_WEAK _LIBCPP_WEAK
void void
operator delete(void* ptr, std::align_val_t) noexcept operator delete(void* ptr, std::align_val_t) noexcept
{ {
std::__libcpp_aligned_free(ptr); std::__libcpp_aligned_free(ptr);
} }
_LIBCXXABI_WEAK _LIBCPP_WEAK
void void
operator delete(void* ptr, std::align_val_t alignment, const std::nothrow_t&) noexcept operator delete(void* ptr, std::align_val_t alignment, const std::nothrow_t&) noexcept
{ {
::operator delete(ptr, alignment); ::operator delete(ptr, alignment);
} }
_LIBCXXABI_WEAK _LIBCPP_WEAK
void void
operator delete(void* ptr, size_t, std::align_val_t alignment) noexcept operator delete(void* ptr, size_t, std::align_val_t alignment) noexcept
{ {
::operator delete(ptr, alignment); ::operator delete(ptr, alignment);
} }
_LIBCXXABI_WEAK _LIBCPP_WEAK
void void
operator delete[] (void* ptr, std::align_val_t alignment) noexcept operator delete[] (void* ptr, std::align_val_t alignment) noexcept
{ {
::operator delete(ptr, alignment); ::operator delete(ptr, alignment);
} }
_LIBCXXABI_WEAK _LIBCPP_WEAK
void void
operator delete[] (void* ptr, std::align_val_t alignment, const std::nothrow_t&) noexcept operator delete[] (void* ptr, std::align_val_t alignment, const std::nothrow_t&) noexcept
{ {
::operator delete[](ptr, alignment); ::operator delete[](ptr, alignment);
} }
_LIBCXXABI_WEAK _LIBCPP_WEAK
void void
operator delete[] (void* ptr, size_t, std::align_val_t alignment) noexcept operator delete[] (void* ptr, size_t, std::align_val_t alignment) noexcept
{ {
@ -253,3 +263,4 @@ operator delete[] (void* ptr, size_t, std::align_val_t alignment) noexcept
} }
#endif // !_LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION #endif // !_LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION
// ------------------ END COPY ------------------