mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-06 13:54:21 +00:00
libcxxabi: update to LLVM 17
release/17.x branch, commit 8f4dd44097c9ae25dd203d5ac87f3b48f854bba8
This commit is contained in:
parent
571a4c86c3
commit
9ddfacd8e6
13 changed files with 461 additions and 408 deletions
2
lib/libcxxabi/include/__cxxabi_config.h
vendored
2
lib/libcxxabi/include/__cxxabi_config.h
vendored
|
|
@ -32,7 +32,7 @@
|
|||
#endif
|
||||
|
||||
#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_DATA_VIS
|
||||
#define _LIBCXXABI_FUNC_VIS
|
||||
|
|
|
|||
85
lib/libcxxabi/src/aix_state_tab_eh.inc
vendored
85
lib/libcxxabi/src/aix_state_tab_eh.inc
vendored
|
|
@ -14,10 +14,6 @@
|
|||
#include <stdio.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
|
||||
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 *callersSP = reinterpret_cast<uintptr_t*>(currentSP[0]);
|
||||
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.
|
||||
_Unwind_SetIP(context, results.landingPad);
|
||||
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);
|
||||
}
|
||||
|
||||
// force_a_stackframe
|
||||
// This function is called by __xlc_exception_handle() to ensure a stack frame
|
||||
// is created for __xlc_exception_handle().
|
||||
__attribute__((noinline, optnone))
|
||||
static void force_a_stackframe() {}
|
||||
// skip_non_cxx_eh_aware_frames
|
||||
// This function skips non-C++ EH aware stack frames by unwinding from the
|
||||
// stack frame pointed by 'Sp' and returns the first C++ EH aware stack frame
|
||||
// found. 'Pc' is an instruction address inside the function that owns the
|
||||
// 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
|
||||
// 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
|
||||
// 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
|
||||
// xlclang++ compiled code. The implementation of __xlc_exception_handle()
|
||||
// assumes a stack frame is created for it. The following ensures this
|
||||
// assumption holds true: 1) a call to force_a_stackframe() is made inside
|
||||
// __xlc_exception_handle() to make it non-leaf; and 2) optimizations are
|
||||
// disabled for this function with attribute 'optnone'. Note: this function
|
||||
// may not work as expected if these are changed.
|
||||
__attribute__((optnone))
|
||||
// xlclang++ compiled code. If __xlc_exception_handle() is called by
|
||||
// non-C++ EH aware functions, their frames are skipped until a C++ EH aware
|
||||
// frame is found.
|
||||
// Note: make sure __xlc_excpetion_handle() is a non-leaf function. Currently
|
||||
// it calls skip_non_cxx_eh_aware_frames(), which in turn calls abort().
|
||||
_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().
|
||||
uintptr_t *lastStack;
|
||||
asm("mr %0, 1" : "=r"(lastStack));
|
||||
// Get the SP of the caller of __xlc_exception_handle().
|
||||
uintptr_t *callerStack = reinterpret_cast<uintptr_t*>(lastStack[0]);
|
||||
// Get the SP of the caller of the caller.
|
||||
uintptr_t *callerStack2 = reinterpret_cast<uintptr_t*>(callerStack[0]);
|
||||
uintptr_t exceptionObject = callerStack2[3];
|
||||
_LIBCXXABI_TRACE_STATETAB("Handshake: exceptionObject=%p from stack=%p\n", reinterpret_cast<void*>(exceptionObject), reinterpret_cast<void*>(callerStack2));
|
||||
uintptr_t* lastStack = reinterpret_cast<uintptr_t*>(__builtin_frame_address(0));
|
||||
// Move one frame up to the frame of the caller of __xlc_exception_handle().
|
||||
lastStack = reinterpret_cast<uintptr_t*>(lastStack[0]);
|
||||
// Get the return address of this function, i.e., __xlc_exception_handle().
|
||||
uint32_t* returnAddress = reinterpret_cast<uint32_t*>(__builtin_return_address(0));
|
||||
|
||||
// Skip non-C++ EH aware frames and get the first C++ EH aware frame.
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
|||
1
lib/libcxxabi/src/cxa_aux_runtime.cpp
vendored
1
lib/libcxxabi/src/cxa_aux_runtime.cpp
vendored
|
|
@ -10,6 +10,7 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "cxxabi.h"
|
||||
#include <exception>
|
||||
#include <new>
|
||||
#include <typeinfo>
|
||||
|
||||
|
|
|
|||
6
lib/libcxxabi/src/cxa_demangle.cpp
vendored
6
lib/libcxxabi/src/cxa_demangle.cpp
vendored
|
|
@ -10,6 +10,7 @@
|
|||
// file does not yet support:
|
||||
// - C++ modules TS
|
||||
|
||||
#include "demangle/DemangleConfig.h"
|
||||
#include "demangle/ItaniumDemangle.h"
|
||||
#include "__cxxabi_config.h"
|
||||
#include <cassert>
|
||||
|
|
@ -19,6 +20,7 @@
|
|||
#include <cstring>
|
||||
#include <functional>
|
||||
#include <numeric>
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
|
||||
using namespace itanium_demangle;
|
||||
|
|
@ -77,8 +79,8 @@ struct DumpVisitor {
|
|||
}
|
||||
|
||||
void printStr(const char *S) { fprintf(stderr, "%s", S); }
|
||||
void print(StringView SV) {
|
||||
fprintf(stderr, "\"%.*s\"", (int)SV.size(), SV.begin());
|
||||
void print(std::string_view SV) {
|
||||
fprintf(stderr, "\"%.*s\"", (int)SV.size(), &*SV.begin());
|
||||
}
|
||||
void print(const Node *N) {
|
||||
if (N)
|
||||
|
|
|
|||
6
lib/libcxxabi/src/cxa_guard_impl.h
vendored
6
lib/libcxxabi/src/cxa_guard_impl.h
vendored
|
|
@ -255,7 +255,7 @@ struct InitByteNoThreads {
|
|||
if (*init_byte_address == COMPLETE_BIT)
|
||||
return true;
|
||||
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;
|
||||
return false;
|
||||
}
|
||||
|
|
@ -325,7 +325,7 @@ public:
|
|||
// Check for possible recursive initialization.
|
||||
if (has_thread_id_support && (*init_byte_address & PENDING_BIT)) {
|
||||
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.
|
||||
|
|
@ -460,7 +460,7 @@ public:
|
|||
|
||||
// Check for recursive initialization
|
||||
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) {
|
||||
|
|
|
|||
8
lib/libcxxabi/src/demangle/DemangleConfig.h
vendored
8
lib/libcxxabi/src/demangle/DemangleConfig.h
vendored
|
|
@ -11,6 +11,14 @@
|
|||
#ifndef 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>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
|
|
|||
288
lib/libcxxabi/src/demangle/ItaniumDemangle.h
vendored
288
lib/libcxxabi/src/demangle/ItaniumDemangle.h
vendored
|
|
@ -17,8 +17,9 @@
|
|||
#define DEMANGLE_ITANIUMDEMANGLE_H
|
||||
|
||||
#include "DemangleConfig.h"
|
||||
#include "StringView.h"
|
||||
#include "StringViewExtras.h"
|
||||
#include "Utility.h"
|
||||
#include <__cxxabi_config.h>
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cctype>
|
||||
|
|
@ -27,8 +28,15 @@
|
|||
#include <cstring>
|
||||
#include <limits>
|
||||
#include <new>
|
||||
#include <string_view>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#ifdef _LIBCXXABI_COMPILER_CLANG
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wunused-template"
|
||||
#endif
|
||||
|
||||
DEMANGLE_NAMESPACE_BEGIN
|
||||
|
||||
template <class T, size_t N> class PODSmallVector {
|
||||
|
|
@ -286,7 +294,7 @@ public:
|
|||
// implementation.
|
||||
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.
|
||||
virtual ~Node() = default;
|
||||
|
|
@ -345,10 +353,10 @@ struct NodeArrayNode : Node {
|
|||
|
||||
class DotSuffix final : public Node {
|
||||
const Node *Prefix;
|
||||
const StringView Suffix;
|
||||
const std::string_view Suffix;
|
||||
|
||||
public:
|
||||
DotSuffix(const Node *Prefix_, StringView Suffix_)
|
||||
DotSuffix(const Node *Prefix_, std::string_view Suffix_)
|
||||
: Node(KDotSuffix), Prefix(Prefix_), Suffix(Suffix_) {}
|
||||
|
||||
template<typename Fn> void match(Fn F) const { F(Prefix, Suffix); }
|
||||
|
|
@ -363,15 +371,15 @@ public:
|
|||
|
||||
class VendorExtQualType final : public Node {
|
||||
const Node *Ty;
|
||||
StringView Ext;
|
||||
std::string_view Ext;
|
||||
const Node *TA;
|
||||
|
||||
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_) {}
|
||||
|
||||
const Node *getTy() const { return Ty; }
|
||||
StringView getExt() const { return Ext; }
|
||||
std::string_view getExt() const { return Ext; }
|
||||
const Node *getTA() const { return TA; }
|
||||
|
||||
template <typename Fn> void match(Fn F) const { F(Ty, Ext, TA); }
|
||||
|
|
@ -462,10 +470,10 @@ public:
|
|||
|
||||
class PostfixQualifiedType final : public Node {
|
||||
const Node *Ty;
|
||||
const StringView Postfix;
|
||||
const std::string_view Postfix;
|
||||
|
||||
public:
|
||||
PostfixQualifiedType(const Node *Ty_, StringView Postfix_)
|
||||
PostfixQualifiedType(const Node *Ty_, std::string_view Postfix_)
|
||||
: Node(KPostfixQualifiedType), Ty(Ty_), Postfix(Postfix_) {}
|
||||
|
||||
template<typename Fn> void match(Fn F) const { F(Ty, Postfix); }
|
||||
|
|
@ -477,15 +485,15 @@ public:
|
|||
};
|
||||
|
||||
class NameType final : public Node {
|
||||
const StringView Name;
|
||||
const std::string_view Name;
|
||||
|
||||
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); }
|
||||
|
||||
StringView getName() const { return Name; }
|
||||
StringView getBaseName() const override { return Name; }
|
||||
std::string_view getName() const { return Name; }
|
||||
std::string_view getBaseName() const override { return Name; }
|
||||
|
||||
void printLeft(OutputBuffer &OB) const override { OB += Name; }
|
||||
};
|
||||
|
|
@ -511,10 +519,10 @@ public:
|
|||
};
|
||||
|
||||
class ElaboratedTypeSpefType : public Node {
|
||||
StringView Kind;
|
||||
std::string_view Kind;
|
||||
Node *Child;
|
||||
public:
|
||||
ElaboratedTypeSpefType(StringView Kind_, Node *Child_)
|
||||
ElaboratedTypeSpefType(std::string_view Kind_, Node *Child_)
|
||||
: Node(KElaboratedTypeSpefType), Kind(Kind_), Child(Child_) {}
|
||||
|
||||
template<typename Fn> void match(Fn F) const { F(Kind, Child); }
|
||||
|
|
@ -528,15 +536,17 @@ public:
|
|||
|
||||
struct AbiTagAttr : Node {
|
||||
Node *Base;
|
||||
StringView Tag;
|
||||
std::string_view Tag;
|
||||
|
||||
AbiTagAttr(Node* Base_, StringView Tag_)
|
||||
: Node(KAbiTagAttr, Base_->RHSComponentCache,
|
||||
Base_->ArrayCache, Base_->FunctionCache),
|
||||
AbiTagAttr(Node *Base_, std::string_view Tag_)
|
||||
: Node(KAbiTagAttr, Base_->RHSComponentCache, Base_->ArrayCache,
|
||||
Base_->FunctionCache),
|
||||
Base(Base_), Tag(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 {
|
||||
Base->printLeft(OB);
|
||||
OB += "[abi:";
|
||||
|
|
@ -562,12 +572,12 @@ public:
|
|||
|
||||
class ObjCProtoName : public Node {
|
||||
const Node *Ty;
|
||||
StringView Protocol;
|
||||
std::string_view Protocol;
|
||||
|
||||
friend class PointerType;
|
||||
|
||||
public:
|
||||
ObjCProtoName(const Node *Ty_, StringView Protocol_)
|
||||
ObjCProtoName(const Node *Ty_, std::string_view Protocol_)
|
||||
: Node(KObjCProtoName), Ty(Ty_), Protocol(Protocol_) {}
|
||||
|
||||
template<typename Fn> void match(Fn F) const { F(Ty, Protocol); }
|
||||
|
|
@ -944,11 +954,11 @@ public:
|
|||
};
|
||||
|
||||
class SpecialName final : public Node {
|
||||
const StringView Special;
|
||||
const std::string_view Special;
|
||||
const Node *Child;
|
||||
|
||||
public:
|
||||
SpecialName(StringView Special_, const Node *Child_)
|
||||
SpecialName(std::string_view Special_, const Node *Child_)
|
||||
: Node(KSpecialName), Special(Special_), Child(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); }
|
||||
|
||||
StringView getBaseName() const override { return Name->getBaseName(); }
|
||||
std::string_view getBaseName() const override { return Name->getBaseName(); }
|
||||
|
||||
void printLeft(OutputBuffer &OB) const override {
|
||||
Qual->print(OB);
|
||||
|
|
@ -1027,7 +1037,7 @@ struct ModuleEntity : Node {
|
|||
|
||||
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 {
|
||||
Name->print(OB);
|
||||
|
|
@ -1063,7 +1073,7 @@ public:
|
|||
|
||||
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 {
|
||||
Qualifier->print(OB);
|
||||
|
|
@ -1485,7 +1495,7 @@ struct NameWithTemplateArgs : Node {
|
|||
|
||||
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 {
|
||||
Name->print(OB);
|
||||
|
|
@ -1502,7 +1512,7 @@ public:
|
|||
|
||||
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 {
|
||||
OB += "::";
|
||||
|
|
@ -1538,20 +1548,20 @@ protected:
|
|||
return unsigned(SSK) >= unsigned(SpecialSubKind::string);
|
||||
}
|
||||
|
||||
StringView getBaseName() const override {
|
||||
std::string_view getBaseName() const override {
|
||||
switch (SSK) {
|
||||
case SpecialSubKind::allocator:
|
||||
return StringView("allocator");
|
||||
return {"allocator"};
|
||||
case SpecialSubKind::basic_string:
|
||||
return StringView("basic_string");
|
||||
return {"basic_string"};
|
||||
case SpecialSubKind::string:
|
||||
return StringView("basic_string");
|
||||
return {"basic_string"};
|
||||
case SpecialSubKind::istream:
|
||||
return StringView("basic_istream");
|
||||
return {"basic_istream"};
|
||||
case SpecialSubKind::ostream:
|
||||
return StringView("basic_ostream");
|
||||
return {"basic_ostream"};
|
||||
case SpecialSubKind::iostream:
|
||||
return StringView("basic_iostream");
|
||||
return {"basic_iostream"};
|
||||
}
|
||||
DEMANGLE_UNREACHABLE;
|
||||
}
|
||||
|
|
@ -1575,12 +1585,12 @@ public:
|
|||
|
||||
template<typename Fn> void match(Fn F) const { F(SSK); }
|
||||
|
||||
StringView getBaseName() const override {
|
||||
auto SV = ExpandedSpecialSubstitution::getBaseName ();
|
||||
std::string_view getBaseName() const override {
|
||||
std::string_view SV = ExpandedSpecialSubstitution::getBaseName();
|
||||
if (isInstantiation()) {
|
||||
// The instantiations are typedefs that drop the "basic_" prefix.
|
||||
assert(SV.startsWith("basic_"));
|
||||
SV = SV.dropFront(sizeof("basic_") - 1);
|
||||
assert(starts_with(SV, "basic_"));
|
||||
SV.remove_prefix(sizeof("basic_") - 1);
|
||||
}
|
||||
return SV;
|
||||
}
|
||||
|
|
@ -1628,10 +1638,11 @@ public:
|
|||
};
|
||||
|
||||
class UnnamedTypeName : public Node {
|
||||
const StringView Count;
|
||||
const std::string_view Count;
|
||||
|
||||
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); }
|
||||
|
||||
|
|
@ -1645,11 +1656,11 @@ public:
|
|||
class ClosureTypeName : public Node {
|
||||
NodeArray TemplateParams;
|
||||
NodeArray Params;
|
||||
StringView Count;
|
||||
std::string_view Count;
|
||||
|
||||
public:
|
||||
ClosureTypeName(NodeArray TemplateParams_, NodeArray Params_,
|
||||
StringView Count_)
|
||||
std::string_view Count_)
|
||||
: Node(KClosureTypeName), TemplateParams(TemplateParams_),
|
||||
Params(Params_), Count(Count_) {}
|
||||
|
||||
|
|
@ -1696,12 +1707,12 @@ public:
|
|||
|
||||
class BinaryExpr : public Node {
|
||||
const Node *LHS;
|
||||
const StringView InfixOperator;
|
||||
const std::string_view InfixOperator;
|
||||
const Node *RHS;
|
||||
|
||||
public:
|
||||
BinaryExpr(const Node *LHS_, StringView InfixOperator_, const Node *RHS_,
|
||||
Prec Prec_)
|
||||
BinaryExpr(const Node *LHS_, std::string_view InfixOperator_,
|
||||
const Node *RHS_, Prec Prec_)
|
||||
: Node(KBinaryExpr, Prec_), LHS(LHS_), InfixOperator(InfixOperator_),
|
||||
RHS(RHS_) {}
|
||||
|
||||
|
|
@ -1750,10 +1761,10 @@ public:
|
|||
|
||||
class PostfixExpr : public Node {
|
||||
const Node *Child;
|
||||
const StringView Operator;
|
||||
const std::string_view Operator;
|
||||
|
||||
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_) {}
|
||||
|
||||
template <typename Fn> void match(Fn F) const {
|
||||
|
|
@ -1791,11 +1802,12 @@ public:
|
|||
|
||||
class MemberExpr : public Node {
|
||||
const Node *LHS;
|
||||
const StringView Kind;
|
||||
const std::string_view Kind;
|
||||
const Node *RHS;
|
||||
|
||||
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_) {}
|
||||
|
||||
template <typename Fn> void match(Fn F) const {
|
||||
|
|
@ -1812,13 +1824,14 @@ public:
|
|||
class SubobjectExpr : public Node {
|
||||
const Node *Type;
|
||||
const Node *SubExpr;
|
||||
StringView Offset;
|
||||
std::string_view Offset;
|
||||
NodeArray UnionSelectors;
|
||||
bool OnePastTheEnd;
|
||||
|
||||
public:
|
||||
SubobjectExpr(const Node *Type_, const Node *SubExpr_, StringView Offset_,
|
||||
NodeArray UnionSelectors_, bool OnePastTheEnd_)
|
||||
SubobjectExpr(const Node *Type_, const Node *SubExpr_,
|
||||
std::string_view Offset_, NodeArray UnionSelectors_,
|
||||
bool OnePastTheEnd_)
|
||||
: Node(KSubobjectExpr), Type(Type_), SubExpr(SubExpr_), Offset(Offset_),
|
||||
UnionSelectors(UnionSelectors_), OnePastTheEnd(OnePastTheEnd_) {}
|
||||
|
||||
|
|
@ -1835,7 +1848,7 @@ public:
|
|||
OB += "0";
|
||||
} else if (Offset[0] == 'n') {
|
||||
OB += "-";
|
||||
OB += Offset.dropFront();
|
||||
OB += std::string_view(Offset.data() + 1, Offset.size() - 1);
|
||||
} else {
|
||||
OB += Offset;
|
||||
}
|
||||
|
|
@ -1844,12 +1857,12 @@ public:
|
|||
};
|
||||
|
||||
class EnclosingExpr : public Node {
|
||||
const StringView Prefix;
|
||||
const std::string_view Prefix;
|
||||
const Node *Infix;
|
||||
const StringView Postfix;
|
||||
const std::string_view Postfix;
|
||||
|
||||
public:
|
||||
EnclosingExpr(StringView Prefix_, const Node *Infix_,
|
||||
EnclosingExpr(std::string_view Prefix_, const Node *Infix_,
|
||||
Prec Prec_ = Prec::Primary)
|
||||
: Node(KEnclosingExpr, Prec_), Prefix(Prefix_), Infix(Infix_) {}
|
||||
|
||||
|
|
@ -1868,12 +1881,13 @@ public:
|
|||
|
||||
class CastExpr : public Node {
|
||||
// cast_kind<to>(from)
|
||||
const StringView CastKind;
|
||||
const std::string_view CastKind;
|
||||
const Node *To;
|
||||
const Node *From;
|
||||
|
||||
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_) {}
|
||||
|
||||
template <typename Fn> void match(Fn F) const {
|
||||
|
|
@ -1996,11 +2010,11 @@ public:
|
|||
};
|
||||
|
||||
class PrefixExpr : public Node {
|
||||
StringView Prefix;
|
||||
std::string_view Prefix;
|
||||
Node *Child;
|
||||
|
||||
public:
|
||||
PrefixExpr(StringView Prefix_, Node *Child_, Prec Prec_)
|
||||
PrefixExpr(std::string_view Prefix_, Node *Child_, Prec Prec_)
|
||||
: Node(KPrefixExpr, Prec_), Prefix(Prefix_), Child(Child_) {}
|
||||
|
||||
template <typename Fn> void match(Fn F) const {
|
||||
|
|
@ -2014,10 +2028,11 @@ public:
|
|||
};
|
||||
|
||||
class FunctionParam : public Node {
|
||||
StringView Number;
|
||||
std::string_view Number;
|
||||
|
||||
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); }
|
||||
|
||||
|
|
@ -2052,11 +2067,11 @@ public:
|
|||
class PointerToMemberConversionExpr : public Node {
|
||||
const Node *Type;
|
||||
const Node *SubExpr;
|
||||
StringView Offset;
|
||||
std::string_view Offset;
|
||||
|
||||
public:
|
||||
PointerToMemberConversionExpr(const Node *Type_, const Node *SubExpr_,
|
||||
StringView Offset_, Prec Prec_)
|
||||
std::string_view Offset_, Prec Prec_)
|
||||
: Node(KPointerToMemberConversionExpr, Prec_), Type(Type_),
|
||||
SubExpr(SubExpr_), Offset(Offset_) {}
|
||||
|
||||
|
|
@ -2141,11 +2156,11 @@ public:
|
|||
|
||||
class FoldExpr : public Node {
|
||||
const Node *Pack, *Init;
|
||||
StringView OperatorName;
|
||||
std::string_view OperatorName;
|
||||
bool IsLeftFold;
|
||||
|
||||
public:
|
||||
FoldExpr(bool IsLeftFold_, StringView OperatorName_, const Node *Pack_,
|
||||
FoldExpr(bool IsLeftFold_, std::string_view OperatorName_, const Node *Pack_,
|
||||
const Node *Init_)
|
||||
: Node(KFoldExpr), Pack(Pack_), Init(Init_), OperatorName(OperatorName_),
|
||||
IsLeftFold(IsLeftFold_) {}
|
||||
|
|
@ -2209,7 +2224,7 @@ public:
|
|||
template<typename Fn> void match(Fn F) const { F(Value); }
|
||||
|
||||
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 {
|
||||
// ty(integer)
|
||||
const Node *Ty;
|
||||
StringView Integer;
|
||||
std::string_view Integer;
|
||||
|
||||
public:
|
||||
EnumLiteral(const Node *Ty_, StringView Integer_)
|
||||
EnumLiteral(const Node *Ty_, std::string_view Integer_)
|
||||
: Node(KEnumLiteral), Ty(Ty_), Integer(Integer_) {}
|
||||
|
||||
template<typename Fn> void match(Fn F) const { F(Ty, Integer); }
|
||||
|
|
@ -2261,18 +2276,18 @@ public:
|
|||
OB.printClose();
|
||||
|
||||
if (Integer[0] == 'n')
|
||||
OB << "-" << Integer.dropFront(1);
|
||||
OB << '-' << std::string_view(Integer.data() + 1, Integer.size() - 1);
|
||||
else
|
||||
OB << Integer;
|
||||
}
|
||||
};
|
||||
|
||||
class IntegerLiteral : public Node {
|
||||
StringView Type;
|
||||
StringView Value;
|
||||
std::string_view Type;
|
||||
std::string_view Value;
|
||||
|
||||
public:
|
||||
IntegerLiteral(StringView Type_, StringView Value_)
|
||||
IntegerLiteral(std::string_view Type_, std::string_view Value_)
|
||||
: Node(KIntegerLiteral), Type(Type_), Value(Value_) {}
|
||||
|
||||
template<typename Fn> void match(Fn F) const { F(Type, Value); }
|
||||
|
|
@ -2284,10 +2299,9 @@ public:
|
|||
OB.printClose();
|
||||
}
|
||||
|
||||
if (Value[0] == 'n') {
|
||||
OB += '-';
|
||||
OB += Value.dropFront(1);
|
||||
} else
|
||||
if (Value[0] == 'n')
|
||||
OB << '-' << std::string_view(Value.data() + 1, Value.size() - 1);
|
||||
else
|
||||
OB += Value;
|
||||
|
||||
if (Type.size() <= 3)
|
||||
|
|
@ -2310,29 +2324,26 @@ constexpr Node::Kind getFloatLiteralKind(long double *) {
|
|||
}
|
||||
|
||||
template <class Float> class FloatLiteralImpl : public Node {
|
||||
const StringView Contents;
|
||||
const std::string_view Contents;
|
||||
|
||||
static constexpr Kind KindForClass =
|
||||
float_literal_impl::getFloatLiteralKind((Float *)nullptr);
|
||||
|
||||
public:
|
||||
FloatLiteralImpl(StringView Contents_)
|
||||
FloatLiteralImpl(std::string_view Contents_)
|
||||
: Node(KindForClass), Contents(Contents_) {}
|
||||
|
||||
template<typename Fn> void match(Fn F) const { F(Contents); }
|
||||
|
||||
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;
|
||||
if (static_cast<std::size_t>(last - first) > N) {
|
||||
last = first + N;
|
||||
if (Contents.size() >= N) {
|
||||
union {
|
||||
Float value;
|
||||
char buf[sizeof(Float)];
|
||||
};
|
||||
const char *t = first;
|
||||
const char *t = Contents.data();
|
||||
const char *last = t + N;
|
||||
char *e = buf;
|
||||
for (; t != last; ++t, ++e) {
|
||||
unsigned d1 = isdigit(*t) ? static_cast<unsigned>(*t - '0')
|
||||
|
|
@ -2347,7 +2358,7 @@ public:
|
|||
#endif
|
||||
char num[FloatData<Float>::max_demangled_size] = {0};
|
||||
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;
|
||||
}
|
||||
|
||||
bool consumeIf(StringView S) {
|
||||
if (StringView(First, Last).startsWith(S)) {
|
||||
bool consumeIf(std::string_view S) {
|
||||
if (starts_with(std::string_view(First, Last - First), S)) {
|
||||
First += S.size();
|
||||
return true;
|
||||
}
|
||||
|
|
@ -2500,10 +2511,10 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {
|
|||
|
||||
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();
|
||||
bool parsePositiveInteger(size_t *Out);
|
||||
StringView parseBareSourceName();
|
||||
std::string_view parseBareSourceName();
|
||||
|
||||
bool parseSeqId(size_t *Out);
|
||||
Node *parseSubstitution();
|
||||
|
|
@ -2514,9 +2525,9 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {
|
|||
|
||||
/// Parse the <expr> production.
|
||||
Node *parseExpr();
|
||||
Node *parsePrefixExpr(StringView Kind, Node::Prec Prec);
|
||||
Node *parseBinaryExpr(StringView Kind, Node::Prec Prec);
|
||||
Node *parseIntegerLiteral(StringView Lit);
|
||||
Node *parsePrefixExpr(std::string_view Kind, Node::Prec Prec);
|
||||
Node *parseBinaryExpr(std::string_view Kind, Node::Prec Prec);
|
||||
Node *parseIntegerLiteral(std::string_view Lit);
|
||||
Node *parseExprPrimary();
|
||||
template <class Float> Node *parseFloatingLiteral();
|
||||
Node *parseFunctionParam();
|
||||
|
|
@ -2624,17 +2635,18 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {
|
|||
bool operator!=(const char *Peek) const { return !this->operator==(Peek); }
|
||||
|
||||
public:
|
||||
StringView getSymbol() const {
|
||||
StringView Res = Name;
|
||||
std::string_view getSymbol() const {
|
||||
std::string_view Res = Name;
|
||||
if (Kind < Unnameable) {
|
||||
assert(Res.startsWith("operator") &&
|
||||
assert(starts_with(Res, "operator") &&
|
||||
"operator name does not start with 'operator'");
|
||||
Res = Res.dropFront(sizeof("operator") - 1);
|
||||
Res.consumeFront(' ');
|
||||
Res.remove_prefix(sizeof("operator") - 1);
|
||||
if (starts_with(Res, ' '))
|
||||
Res.remove_prefix(1);
|
||||
}
|
||||
return Res;
|
||||
}
|
||||
StringView getName() const { return Name; }
|
||||
std::string_view getName() const { return Name; }
|
||||
OIKind getKind() const { return Kind; }
|
||||
bool getFlag() const { return Flag; }
|
||||
Node::Prec getPrecedence() const { return Prec; }
|
||||
|
|
@ -2854,7 +2866,7 @@ AbstractManglingParser<Derived, Alloc>::parseUnnamedTypeName(NameState *State) {
|
|||
TemplateParams.clear();
|
||||
|
||||
if (consumeIf("Ut")) {
|
||||
StringView Count = parseNumber();
|
||||
std::string_view Count = parseNumber();
|
||||
if (!consumeIf('_'))
|
||||
return nullptr;
|
||||
return make<UnnamedTypeName>(Count);
|
||||
|
|
@ -2866,7 +2878,7 @@ AbstractManglingParser<Derived, Alloc>::parseUnnamedTypeName(NameState *State) {
|
|||
|
||||
size_t ParamsBegin = Names.size();
|
||||
while (look() == 'T' &&
|
||||
StringView("yptn").find(look(1)) != StringView::npos) {
|
||||
std::string_view("yptn").find(look(1)) != std::string_view::npos) {
|
||||
Node *T = parseTemplateParamDecl();
|
||||
if (!T)
|
||||
return nullptr;
|
||||
|
|
@ -2909,7 +2921,7 @@ AbstractManglingParser<Derived, Alloc>::parseUnnamedTypeName(NameState *State) {
|
|||
}
|
||||
NodeArray Params = popTrailingNodeArray(ParamsBegin);
|
||||
|
||||
StringView Count = parseNumber();
|
||||
std::string_view Count = parseNumber();
|
||||
if (!consumeIf('_'))
|
||||
return nullptr;
|
||||
return make<ClosureTypeName>(TempParams, Params, Count);
|
||||
|
|
@ -2931,9 +2943,9 @@ Node *AbstractManglingParser<Derived, Alloc>::parseSourceName(NameState *) {
|
|||
return nullptr;
|
||||
if (numLeft() < Length || Length == 0)
|
||||
return nullptr;
|
||||
StringView Name(First, First + Length);
|
||||
std::string_view Name(First, Length);
|
||||
First += Length;
|
||||
if (Name.startsWith("_GLOBAL__N"))
|
||||
if (starts_with(Name, "_GLOBAL__N"))
|
||||
return make<NameType>("(anonymous namespace)");
|
||||
return make<NameType>(Name);
|
||||
}
|
||||
|
|
@ -3447,7 +3459,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseUnresolvedName(bool Global) {
|
|||
template <typename Derived, typename Alloc>
|
||||
Node *AbstractManglingParser<Derived, Alloc>::parseAbiTags(Node *N) {
|
||||
while (consumeIf('B')) {
|
||||
StringView SN = parseBareSourceName();
|
||||
std::string_view SN = parseBareSourceName();
|
||||
if (SN.empty())
|
||||
return nullptr;
|
||||
N = make<AbiTagAttr>(N, SN);
|
||||
|
|
@ -3459,16 +3471,16 @@ Node *AbstractManglingParser<Derived, Alloc>::parseAbiTags(Node *N) {
|
|||
|
||||
// <number> ::= [n] <non-negative decimal integer>
|
||||
template <typename Alloc, typename Derived>
|
||||
StringView
|
||||
std::string_view
|
||||
AbstractManglingParser<Alloc, Derived>::parseNumber(bool AllowNegative) {
|
||||
const char *Tmp = First;
|
||||
if (AllowNegative)
|
||||
consumeIf('n');
|
||||
if (numLeft() == 0 || !std::isdigit(*First))
|
||||
return StringView();
|
||||
return std::string_view();
|
||||
while (numLeft() != 0 && std::isdigit(*First))
|
||||
++First;
|
||||
return StringView(Tmp, First);
|
||||
return std::string_view(Tmp, First - Tmp);
|
||||
}
|
||||
|
||||
// <positive length number> ::= [0-9]*
|
||||
|
|
@ -3485,11 +3497,11 @@ bool AbstractManglingParser<Alloc, Derived>::parsePositiveInteger(size_t *Out) {
|
|||
}
|
||||
|
||||
template <typename Alloc, typename Derived>
|
||||
StringView AbstractManglingParser<Alloc, Derived>::parseBareSourceName() {
|
||||
std::string_view AbstractManglingParser<Alloc, Derived>::parseBareSourceName() {
|
||||
size_t Int = 0;
|
||||
if (parsePositiveInteger(&Int) || numLeft() < Int)
|
||||
return StringView();
|
||||
StringView R(First, First + Int);
|
||||
return {};
|
||||
std::string_view R(First, Int);
|
||||
First += Int;
|
||||
return R;
|
||||
}
|
||||
|
|
@ -3673,7 +3685,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parsePointerToMemberType() {
|
|||
// ::= Te <name> # dependent elaborated type specifier using 'enum'
|
||||
template <typename Derived, typename Alloc>
|
||||
Node *AbstractManglingParser<Derived, Alloc>::parseClassEnumType() {
|
||||
StringView ElabSpef;
|
||||
std::string_view ElabSpef;
|
||||
if (consumeIf("Ts"))
|
||||
ElabSpef = "struct";
|
||||
else if (consumeIf("Tu"))
|
||||
|
|
@ -3697,17 +3709,18 @@ Node *AbstractManglingParser<Derived, Alloc>::parseClassEnumType() {
|
|||
template <typename Derived, typename Alloc>
|
||||
Node *AbstractManglingParser<Derived, Alloc>::parseQualifiedType() {
|
||||
if (consumeIf('U')) {
|
||||
StringView Qual = parseBareSourceName();
|
||||
std::string_view Qual = parseBareSourceName();
|
||||
if (Qual.empty())
|
||||
return nullptr;
|
||||
|
||||
// extension ::= U <objc-name> <objc-type> # objc-type<identifier>
|
||||
if (Qual.startsWith("objcproto")) {
|
||||
StringView ProtoSourceName = Qual.dropFront(std::strlen("objcproto"));
|
||||
StringView Proto;
|
||||
if (starts_with(Qual, "objcproto")) {
|
||||
constexpr size_t Len = sizeof("objcproto") - 1;
|
||||
std::string_view ProtoSourceName(Qual.data() + Len, Qual.size() - Len);
|
||||
std::string_view Proto;
|
||||
{
|
||||
ScopedOverride<const char *> SaveFirst(First, ProtoSourceName.begin()),
|
||||
SaveLast(Last, ProtoSourceName.end());
|
||||
ScopedOverride<const char *> SaveFirst(First, ProtoSourceName.data()),
|
||||
SaveLast(Last, &*ProtoSourceName.rbegin() + 1);
|
||||
Proto = parseBareSourceName();
|
||||
}
|
||||
if (Proto.empty())
|
||||
|
|
@ -3875,7 +3888,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseType() {
|
|||
// <builtin-type> ::= u <source-name> # vendor extended type
|
||||
case 'u': {
|
||||
++First;
|
||||
StringView Res = parseBareSourceName();
|
||||
std::string_view Res = parseBareSourceName();
|
||||
if (Res.empty())
|
||||
return nullptr;
|
||||
// Typically, <builtin-type>s are not considered substitution candidates,
|
||||
|
|
@ -4123,8 +4136,9 @@ Node *AbstractManglingParser<Derived, Alloc>::parseType() {
|
|||
}
|
||||
|
||||
template <typename Derived, typename Alloc>
|
||||
Node *AbstractManglingParser<Derived, Alloc>::parsePrefixExpr(StringView Kind,
|
||||
Node::Prec Prec) {
|
||||
Node *
|
||||
AbstractManglingParser<Derived, Alloc>::parsePrefixExpr(std::string_view Kind,
|
||||
Node::Prec Prec) {
|
||||
Node *E = getDerived().parseExpr();
|
||||
if (E == nullptr)
|
||||
return nullptr;
|
||||
|
|
@ -4132,8 +4146,9 @@ Node *AbstractManglingParser<Derived, Alloc>::parsePrefixExpr(StringView Kind,
|
|||
}
|
||||
|
||||
template <typename Derived, typename Alloc>
|
||||
Node *AbstractManglingParser<Derived, Alloc>::parseBinaryExpr(StringView Kind,
|
||||
Node::Prec Prec) {
|
||||
Node *
|
||||
AbstractManglingParser<Derived, Alloc>::parseBinaryExpr(std::string_view Kind,
|
||||
Node::Prec Prec) {
|
||||
Node *LHS = getDerived().parseExpr();
|
||||
if (LHS == nullptr)
|
||||
return nullptr;
|
||||
|
|
@ -4144,9 +4159,9 @@ Node *AbstractManglingParser<Derived, Alloc>::parseBinaryExpr(StringView Kind,
|
|||
}
|
||||
|
||||
template <typename Derived, typename Alloc>
|
||||
Node *
|
||||
AbstractManglingParser<Derived, Alloc>::parseIntegerLiteral(StringView Lit) {
|
||||
StringView Tmp = parseNumber(true);
|
||||
Node *AbstractManglingParser<Derived, Alloc>::parseIntegerLiteral(
|
||||
std::string_view Lit) {
|
||||
std::string_view Tmp = parseNumber(true);
|
||||
if (!Tmp.empty() && consumeIf('E'))
|
||||
return make<IntegerLiteral>(Lit, Tmp);
|
||||
return nullptr;
|
||||
|
|
@ -4176,7 +4191,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseFunctionParam() {
|
|||
return make<NameType>("this");
|
||||
if (consumeIf("fp")) {
|
||||
parseCVQualifiers();
|
||||
StringView Num = parseNumber();
|
||||
std::string_view Num = parseNumber();
|
||||
if (!consumeIf('_'))
|
||||
return nullptr;
|
||||
return make<FunctionParam>(Num);
|
||||
|
|
@ -4187,7 +4202,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseFunctionParam() {
|
|||
if (!consumeIf('p'))
|
||||
return nullptr;
|
||||
parseCVQualifiers();
|
||||
StringView Num = parseNumber();
|
||||
std::string_view Num = parseNumber();
|
||||
if (!consumeIf('_'))
|
||||
return nullptr;
|
||||
return make<FunctionParam>(Num);
|
||||
|
|
@ -4341,7 +4356,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseExprPrimary() {
|
|||
Node *T = getDerived().parseType();
|
||||
if (T == nullptr)
|
||||
return nullptr;
|
||||
StringView N = parseNumber(/*AllowNegative=*/true);
|
||||
std::string_view N = parseNumber(/*AllowNegative=*/true);
|
||||
if (N.empty())
|
||||
return nullptr;
|
||||
if (!consumeIf('E'))
|
||||
|
|
@ -4464,7 +4479,7 @@ AbstractManglingParser<Derived, Alloc>::parsePointerToMemberConversionExpr(
|
|||
Node *Expr = getDerived().parseExpr();
|
||||
if (!Expr)
|
||||
return nullptr;
|
||||
StringView Offset = getDerived().parseNumber(true);
|
||||
std::string_view Offset = getDerived().parseNumber(true);
|
||||
if (!consumeIf('E'))
|
||||
return nullptr;
|
||||
return make<PointerToMemberConversionExpr>(Ty, Expr, Offset, Prec);
|
||||
|
|
@ -4482,7 +4497,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseSubobjectExpr() {
|
|||
Node *Expr = getDerived().parseExpr();
|
||||
if (!Expr)
|
||||
return nullptr;
|
||||
StringView Offset = getDerived().parseNumber(true);
|
||||
std::string_view Offset = getDerived().parseNumber(true);
|
||||
size_t SelectorsBegin = Names.size();
|
||||
while (consumeIf('_')) {
|
||||
Node *Selector = make<NameType>(parseNumber());
|
||||
|
|
@ -5141,7 +5156,7 @@ Node *AbstractManglingParser<Alloc, Derived>::parseFloatingLiteral() {
|
|||
const size_t N = FloatData<Float>::mangled_size;
|
||||
if (numLeft() <= N)
|
||||
return nullptr;
|
||||
StringView Data(First, First + N);
|
||||
std::string_view Data(First, N);
|
||||
for (char C : Data)
|
||||
if (!std::isxdigit(C))
|
||||
return nullptr;
|
||||
|
|
@ -5461,7 +5476,8 @@ Node *AbstractManglingParser<Derived, Alloc>::parse() {
|
|||
if (Encoding == nullptr)
|
||||
return nullptr;
|
||||
if (look() == '.') {
|
||||
Encoding = make<DotSuffix>(Encoding, StringView(First, Last));
|
||||
Encoding =
|
||||
make<DotSuffix>(Encoding, std::string_view(First, Last - First));
|
||||
First = Last;
|
||||
}
|
||||
if (numLeft() != 0)
|
||||
|
|
@ -5497,4 +5513,8 @@ struct ManglingParser : AbstractManglingParser<ManglingParser<Alloc>, Alloc> {
|
|||
|
||||
DEMANGLE_NAMESPACE_END
|
||||
|
||||
#ifdef _LIBCXXABI_COMPILER_CLANG
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
#endif // DEMANGLE_ITANIUMDEMANGLE_H
|
||||
|
|
|
|||
122
lib/libcxxabi/src/demangle/StringView.h
vendored
122
lib/libcxxabi/src/demangle/StringView.h
vendored
|
|
@ -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
|
||||
38
lib/libcxxabi/src/demangle/StringViewExtras.h
vendored
Normal file
38
lib/libcxxabi/src/demangle/StringViewExtras.h
vendored
Normal 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
|
||||
22
lib/libcxxabi/src/demangle/Utility.h
vendored
22
lib/libcxxabi/src/demangle/Utility.h
vendored
|
|
@ -16,13 +16,16 @@
|
|||
#ifndef DEMANGLE_UTILITY_H
|
||||
#define DEMANGLE_UTILITY_H
|
||||
|
||||
#include "StringView.h"
|
||||
#include "DemangleConfig.h"
|
||||
|
||||
#include <array>
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <exception>
|
||||
#include <limits>
|
||||
#include <string_view>
|
||||
|
||||
DEMANGLE_NAMESPACE_BEGIN
|
||||
|
||||
|
|
@ -64,7 +67,8 @@ class OutputBuffer {
|
|||
if (isNeg)
|
||||
*--TempPtr = '-';
|
||||
|
||||
return operator+=(StringView(TempPtr, Temp.data() + Temp.size()));
|
||||
return operator+=(
|
||||
std::string_view(TempPtr, Temp.data() + Temp.size() - TempPtr));
|
||||
}
|
||||
|
||||
public:
|
||||
|
|
@ -77,7 +81,9 @@ public:
|
|||
OutputBuffer(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
|
||||
/// into the pack that we're currently printing.
|
||||
|
|
@ -99,10 +105,10 @@ public:
|
|||
*this += Close;
|
||||
}
|
||||
|
||||
OutputBuffer &operator+=(StringView R) {
|
||||
OutputBuffer &operator+=(std::string_view R) {
|
||||
if (size_t Size = R.size()) {
|
||||
grow(Size);
|
||||
std::memcpy(Buffer + CurrentPosition, R.begin(), Size);
|
||||
std::memcpy(Buffer + CurrentPosition, &*R.begin(), Size);
|
||||
CurrentPosition += Size;
|
||||
}
|
||||
return *this;
|
||||
|
|
@ -114,18 +120,18 @@ public:
|
|||
return *this;
|
||||
}
|
||||
|
||||
OutputBuffer &prepend(StringView R) {
|
||||
OutputBuffer &prepend(std::string_view R) {
|
||||
size_t Size = R.size();
|
||||
|
||||
grow(Size);
|
||||
std::memmove(Buffer + Size, Buffer, CurrentPosition);
|
||||
std::memcpy(Buffer, R.begin(), Size);
|
||||
std::memcpy(Buffer, &*R.begin(), Size);
|
||||
CurrentPosition += Size;
|
||||
|
||||
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); }
|
||||
|
||||
|
|
|
|||
2
lib/libcxxabi/src/fallback_malloc.cpp
vendored
2
lib/libcxxabi/src/fallback_malloc.cpp
vendored
|
|
@ -15,10 +15,10 @@
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#include <__memory/aligned_alloc.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h> // for malloc, calloc, free
|
||||
#include <string.h> // for memset
|
||||
#include <new> // for std::__libcpp_aligned_{alloc,free}
|
||||
|
||||
// A small, simple heap manager based (loosely) on
|
||||
// the startup heap manager from FreeBSD, optimized for space.
|
||||
|
|
|
|||
186
lib/libcxxabi/src/private_typeinfo.cpp
vendored
186
lib/libcxxabi/src/private_typeinfo.cpp
vendored
|
|
@ -41,6 +41,7 @@
|
|||
// 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 <cstdint>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef _LIBCXXABI_FORGIVING_DYNAMIC_CAST
|
||||
|
|
@ -656,77 +657,138 @@ __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
|
||||
if (is_equal(dynamic_type, dst_type, false))
|
||||
{
|
||||
// Using giant short cut. Add that information to info.
|
||||
info.number_of_dst_type = 1;
|
||||
// Do the search
|
||||
dynamic_type->search_above_dst(&info, dynamic_ptr, dynamic_ptr, public_path, false);
|
||||
#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'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)
|
||||
{
|
||||
// We get here only if there is some kind of visibility problem
|
||||
// in client code.
|
||||
static_assert(std::atomic<size_t>::is_always_lock_free, "");
|
||||
static std::atomic<size_t> 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);
|
||||
// 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.
|
||||
info.number_of_dst_type = 1;
|
||||
// Do the search
|
||||
dynamic_type->search_above_dst(&info, dynamic_ptr, dynamic_ptr, public_path, false);
|
||||
#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.
|
||||
static_assert(std::atomic<size_t>::is_always_lock_free, "");
|
||||
static std::atomic<size_t> 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 // _LIBCXXABI_FORGIVING_DYNAMIC_CAST
|
||||
// Query the search.
|
||||
if (info.path_dst_ptr_to_static_ptr == public_path)
|
||||
dst_ptr = dynamic_ptr;
|
||||
// Query the search.
|
||||
if (info.path_dst_ptr_to_static_ptr == public_path)
|
||||
dst_ptr = dynamic_ptr;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Not using giant short cut. Do the search
|
||||
dynamic_type->search_below_dst(&info, dynamic_ptr, public_path, false);
|
||||
#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)
|
||||
if (src2dst_offset >= 0)
|
||||
{
|
||||
static_assert(std::atomic<size_t>::is_always_lock_free, "");
|
||||
static std::atomic<size_t> 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);
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // _LIBCXXABI_FORGIVING_DYNAMIC_CAST
|
||||
// Query the search.
|
||||
switch (info.number_to_static_ptr)
|
||||
|
||||
if (!dst_ptr)
|
||||
{
|
||||
case 0:
|
||||
if (info.number_to_dst_ptr == 1 &&
|
||||
info.path_dynamic_ptr_to_static_ptr == public_path &&
|
||||
info.path_dynamic_ptr_to_dst_ptr == public_path)
|
||||
dst_ptr = info.dst_ptr_not_leading_to_static_ptr;
|
||||
break;
|
||||
case 1:
|
||||
if (info.path_dst_ptr_to_static_ptr == public_path ||
|
||||
(
|
||||
info.number_to_dst_ptr == 0 &&
|
||||
info.path_dynamic_ptr_to_static_ptr == public_path &&
|
||||
info.path_dynamic_ptr_to_dst_ptr == public_path
|
||||
)
|
||||
)
|
||||
dst_ptr = info.dst_ptr_leading_to_static_ptr;
|
||||
break;
|
||||
// Not using giant short cut. Do the search
|
||||
dynamic_type->search_below_dst(&info, dynamic_ptr, public_path, false);
|
||||
#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)
|
||||
{
|
||||
static_assert(std::atomic<size_t>::is_always_lock_free, "");
|
||||
static std::atomic<size_t> 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 // _LIBCXXABI_FORGIVING_DYNAMIC_CAST
|
||||
// Query the search.
|
||||
switch (info.number_to_static_ptr)
|
||||
{
|
||||
case 0:
|
||||
if (info.number_to_dst_ptr == 1 &&
|
||||
info.path_dynamic_ptr_to_static_ptr == public_path &&
|
||||
info.path_dynamic_ptr_to_dst_ptr == public_path)
|
||||
dst_ptr = info.dst_ptr_not_leading_to_static_ptr;
|
||||
break;
|
||||
case 1:
|
||||
if (info.path_dst_ptr_to_static_ptr == public_path ||
|
||||
(
|
||||
info.number_to_dst_ptr == 0 &&
|
||||
info.path_dynamic_ptr_to_static_ptr == public_path &&
|
||||
info.path_dynamic_ptr_to_dst_ptr == public_path
|
||||
)
|
||||
)
|
||||
dst_ptr = info.dst_ptr_leading_to_static_ptr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return const_cast<void*>(dst_ptr);
|
||||
|
|
|
|||
103
lib/libcxxabi/src/stdlib_new_delete.cpp
vendored
103
lib/libcxxabi/src/stdlib_new_delete.cpp
vendored
|
|
@ -4,30 +4,40 @@
|
|||
// 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.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "__cxxabi_config.h"
|
||||
#include <new>
|
||||
#include <__memory/aligned_alloc.h>
|
||||
#include <cstdlib>
|
||||
#include <new>
|
||||
|
||||
#if !defined(_THROW_BAD_ALLOC) || !defined(_LIBCXXABI_WEAK)
|
||||
#error The _THROW_BAD_ALLOC and _LIBCXXABI_WEAK libc++ macros must \
|
||||
already be defined by libc++.
|
||||
// Perform a few sanity checks on libc++ and libc++abi macros to ensure that
|
||||
// the code below can be an exact copy of the code in libcxx/src/new.cpp.
|
||||
#if !defined(_THROW_BAD_ALLOC)
|
||||
# error The _THROW_BAD_ALLOC macro should be already defined by libc++
|
||||
#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
|
||||
// in this shared library, so that they can be overridden by programs
|
||||
// that define non-weak copies of the functions.
|
||||
|
||||
_LIBCXXABI_WEAK
|
||||
_LIBCPP_WEAK
|
||||
void *
|
||||
operator new(std::size_t size) _THROW_BAD_ALLOC
|
||||
{
|
||||
if (size == 0)
|
||||
size = 1;
|
||||
void* p;
|
||||
while ((p = ::malloc(size)) == nullptr)
|
||||
while ((p = std::malloc(size)) == nullptr)
|
||||
{
|
||||
// If malloc fails and there is a new_handler,
|
||||
// call it to try free up memory.
|
||||
|
|
@ -35,7 +45,7 @@ operator new(std::size_t size) _THROW_BAD_ALLOC
|
|||
if (nh)
|
||||
nh();
|
||||
else
|
||||
#ifndef _LIBCXXABI_NO_EXCEPTIONS
|
||||
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
|
||||
throw std::bad_alloc();
|
||||
#else
|
||||
break;
|
||||
|
|
@ -44,87 +54,87 @@ operator new(std::size_t size) _THROW_BAD_ALLOC
|
|||
return p;
|
||||
}
|
||||
|
||||
_LIBCXXABI_WEAK
|
||||
_LIBCPP_WEAK
|
||||
void*
|
||||
operator new(size_t size, const std::nothrow_t&) noexcept
|
||||
{
|
||||
void* p = nullptr;
|
||||
#ifndef _LIBCXXABI_NO_EXCEPTIONS
|
||||
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
|
||||
try
|
||||
{
|
||||
#endif // _LIBCXXABI_NO_EXCEPTIONS
|
||||
#endif // _LIBCPP_HAS_NO_EXCEPTIONS
|
||||
p = ::operator new(size);
|
||||
#ifndef _LIBCXXABI_NO_EXCEPTIONS
|
||||
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
}
|
||||
#endif // _LIBCXXABI_NO_EXCEPTIONS
|
||||
#endif // _LIBCPP_HAS_NO_EXCEPTIONS
|
||||
return p;
|
||||
}
|
||||
|
||||
_LIBCXXABI_WEAK
|
||||
_LIBCPP_WEAK
|
||||
void*
|
||||
operator new[](size_t size) _THROW_BAD_ALLOC
|
||||
{
|
||||
return ::operator new(size);
|
||||
}
|
||||
|
||||
_LIBCXXABI_WEAK
|
||||
_LIBCPP_WEAK
|
||||
void*
|
||||
operator new[](size_t size, const std::nothrow_t&) noexcept
|
||||
{
|
||||
void* p = nullptr;
|
||||
#ifndef _LIBCXXABI_NO_EXCEPTIONS
|
||||
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
|
||||
try
|
||||
{
|
||||
#endif // _LIBCXXABI_NO_EXCEPTIONS
|
||||
#endif // _LIBCPP_HAS_NO_EXCEPTIONS
|
||||
p = ::operator new[](size);
|
||||
#ifndef _LIBCXXABI_NO_EXCEPTIONS
|
||||
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
}
|
||||
#endif // _LIBCXXABI_NO_EXCEPTIONS
|
||||
#endif // _LIBCPP_HAS_NO_EXCEPTIONS
|
||||
return p;
|
||||
}
|
||||
|
||||
_LIBCXXABI_WEAK
|
||||
_LIBCPP_WEAK
|
||||
void
|
||||
operator delete(void* ptr) noexcept
|
||||
{
|
||||
::free(ptr);
|
||||
std::free(ptr);
|
||||
}
|
||||
|
||||
_LIBCXXABI_WEAK
|
||||
_LIBCPP_WEAK
|
||||
void
|
||||
operator delete(void* ptr, const std::nothrow_t&) noexcept
|
||||
{
|
||||
::operator delete(ptr);
|
||||
}
|
||||
|
||||
_LIBCXXABI_WEAK
|
||||
_LIBCPP_WEAK
|
||||
void
|
||||
operator delete(void* ptr, size_t) noexcept
|
||||
{
|
||||
::operator delete(ptr);
|
||||
}
|
||||
|
||||
_LIBCXXABI_WEAK
|
||||
_LIBCPP_WEAK
|
||||
void
|
||||
operator delete[] (void* ptr) noexcept
|
||||
{
|
||||
::operator delete(ptr);
|
||||
}
|
||||
|
||||
_LIBCXXABI_WEAK
|
||||
_LIBCPP_WEAK
|
||||
void
|
||||
operator delete[] (void* ptr, const std::nothrow_t&) noexcept
|
||||
{
|
||||
::operator delete[](ptr);
|
||||
}
|
||||
|
||||
_LIBCXXABI_WEAK
|
||||
_LIBCPP_WEAK
|
||||
void
|
||||
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)
|
||||
|
||||
_LIBCXXABI_WEAK
|
||||
_LIBCPP_WEAK
|
||||
void *
|
||||
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)
|
||||
nh();
|
||||
else {
|
||||
#ifndef _LIBCXXABI_NO_EXCEPTIONS
|
||||
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
|
||||
throw std::bad_alloc();
|
||||
#else
|
||||
break;
|
||||
|
|
@ -165,87 +175,87 @@ operator new(std::size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC
|
|||
return p;
|
||||
}
|
||||
|
||||
_LIBCXXABI_WEAK
|
||||
_LIBCPP_WEAK
|
||||
void*
|
||||
operator new(size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept
|
||||
{
|
||||
void* p = nullptr;
|
||||
#ifndef _LIBCXXABI_NO_EXCEPTIONS
|
||||
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
|
||||
try
|
||||
{
|
||||
#endif // _LIBCXXABI_NO_EXCEPTIONS
|
||||
#endif // _LIBCPP_HAS_NO_EXCEPTIONS
|
||||
p = ::operator new(size, alignment);
|
||||
#ifndef _LIBCXXABI_NO_EXCEPTIONS
|
||||
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
}
|
||||
#endif // _LIBCXXABI_NO_EXCEPTIONS
|
||||
#endif // _LIBCPP_HAS_NO_EXCEPTIONS
|
||||
return p;
|
||||
}
|
||||
|
||||
_LIBCXXABI_WEAK
|
||||
_LIBCPP_WEAK
|
||||
void*
|
||||
operator new[](size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC
|
||||
{
|
||||
return ::operator new(size, alignment);
|
||||
}
|
||||
|
||||
_LIBCXXABI_WEAK
|
||||
_LIBCPP_WEAK
|
||||
void*
|
||||
operator new[](size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept
|
||||
{
|
||||
void* p = nullptr;
|
||||
#ifndef _LIBCXXABI_NO_EXCEPTIONS
|
||||
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
|
||||
try
|
||||
{
|
||||
#endif // _LIBCXXABI_NO_EXCEPTIONS
|
||||
#endif // _LIBCPP_HAS_NO_EXCEPTIONS
|
||||
p = ::operator new[](size, alignment);
|
||||
#ifndef _LIBCXXABI_NO_EXCEPTIONS
|
||||
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
}
|
||||
#endif // _LIBCXXABI_NO_EXCEPTIONS
|
||||
#endif // _LIBCPP_HAS_NO_EXCEPTIONS
|
||||
return p;
|
||||
}
|
||||
|
||||
_LIBCXXABI_WEAK
|
||||
_LIBCPP_WEAK
|
||||
void
|
||||
operator delete(void* ptr, std::align_val_t) noexcept
|
||||
{
|
||||
std::__libcpp_aligned_free(ptr);
|
||||
}
|
||||
|
||||
_LIBCXXABI_WEAK
|
||||
_LIBCPP_WEAK
|
||||
void
|
||||
operator delete(void* ptr, std::align_val_t alignment, const std::nothrow_t&) noexcept
|
||||
{
|
||||
::operator delete(ptr, alignment);
|
||||
}
|
||||
|
||||
_LIBCXXABI_WEAK
|
||||
_LIBCPP_WEAK
|
||||
void
|
||||
operator delete(void* ptr, size_t, std::align_val_t alignment) noexcept
|
||||
{
|
||||
::operator delete(ptr, alignment);
|
||||
}
|
||||
|
||||
_LIBCXXABI_WEAK
|
||||
_LIBCPP_WEAK
|
||||
void
|
||||
operator delete[] (void* ptr, std::align_val_t alignment) noexcept
|
||||
{
|
||||
::operator delete(ptr, alignment);
|
||||
}
|
||||
|
||||
_LIBCXXABI_WEAK
|
||||
_LIBCPP_WEAK
|
||||
void
|
||||
operator delete[] (void* ptr, std::align_val_t alignment, const std::nothrow_t&) noexcept
|
||||
{
|
||||
::operator delete[](ptr, alignment);
|
||||
}
|
||||
|
||||
_LIBCXXABI_WEAK
|
||||
_LIBCPP_WEAK
|
||||
void
|
||||
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
|
||||
// ------------------ END COPY ------------------
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue