mirror of https://git.suyu.dev/suyu/suyu
demangle: Update to llvm/llvm-project@ecbc812e0c
This commit is contained in:
parent
c1e57ad358
commit
1ab3bd5a5e
|
@ -20,9 +20,7 @@
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <numeric>
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
using namespace llvm::itanium_demangle;
|
using namespace llvm::itanium_demangle;
|
||||||
|
@ -81,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.data());
|
||||||
}
|
}
|
||||||
void print(const Node *N) {
|
void print(const Node *N) {
|
||||||
if (N)
|
if (N)
|
||||||
|
@ -90,14 +88,6 @@ struct DumpVisitor {
|
||||||
else
|
else
|
||||||
printStr("<null>");
|
printStr("<null>");
|
||||||
}
|
}
|
||||||
void print(NodeOrString NS) {
|
|
||||||
if (NS.isNode())
|
|
||||||
print(NS.asNode());
|
|
||||||
else if (NS.isString())
|
|
||||||
print(NS.asString());
|
|
||||||
else
|
|
||||||
printStr("NodeOrString()");
|
|
||||||
}
|
|
||||||
void print(NodeArray A) {
|
void print(NodeArray A) {
|
||||||
++Depth;
|
++Depth;
|
||||||
printStr("{");
|
printStr("{");
|
||||||
|
@ -116,13 +106,11 @@ struct DumpVisitor {
|
||||||
// Overload used when T is exactly 'bool', not merely convertible to 'bool'.
|
// Overload used when T is exactly 'bool', not merely convertible to 'bool'.
|
||||||
void print(bool B) { printStr(B ? "true" : "false"); }
|
void print(bool B) { printStr(B ? "true" : "false"); }
|
||||||
|
|
||||||
template <class T>
|
template <class T> std::enable_if_t<std::is_unsigned<T>::value> print(T N) {
|
||||||
typename std::enable_if<std::is_unsigned<T>::value>::type print(T N) {
|
|
||||||
fprintf(stderr, "%llu", (unsigned long long)N);
|
fprintf(stderr, "%llu", (unsigned long long)N);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T> std::enable_if_t<std::is_signed<T>::value> print(T N) {
|
||||||
typename std::enable_if<std::is_signed<T>::value>::type print(T N) {
|
|
||||||
fprintf(stderr, "%lld", (long long)N);
|
fprintf(stderr, "%lld", (long long)N);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -185,6 +173,50 @@ struct DumpVisitor {
|
||||||
return printStr("TemplateParamKind::Template");
|
return printStr("TemplateParamKind::Template");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
void print(Node::Prec P) {
|
||||||
|
switch (P) {
|
||||||
|
case Node::Prec::Primary:
|
||||||
|
return printStr("Node::Prec::Primary");
|
||||||
|
case Node::Prec::Postfix:
|
||||||
|
return printStr("Node::Prec::Postfix");
|
||||||
|
case Node::Prec::Unary:
|
||||||
|
return printStr("Node::Prec::Unary");
|
||||||
|
case Node::Prec::Cast:
|
||||||
|
return printStr("Node::Prec::Cast");
|
||||||
|
case Node::Prec::PtrMem:
|
||||||
|
return printStr("Node::Prec::PtrMem");
|
||||||
|
case Node::Prec::Multiplicative:
|
||||||
|
return printStr("Node::Prec::Multiplicative");
|
||||||
|
case Node::Prec::Additive:
|
||||||
|
return printStr("Node::Prec::Additive");
|
||||||
|
case Node::Prec::Shift:
|
||||||
|
return printStr("Node::Prec::Shift");
|
||||||
|
case Node::Prec::Spaceship:
|
||||||
|
return printStr("Node::Prec::Spaceship");
|
||||||
|
case Node::Prec::Relational:
|
||||||
|
return printStr("Node::Prec::Relational");
|
||||||
|
case Node::Prec::Equality:
|
||||||
|
return printStr("Node::Prec::Equality");
|
||||||
|
case Node::Prec::And:
|
||||||
|
return printStr("Node::Prec::And");
|
||||||
|
case Node::Prec::Xor:
|
||||||
|
return printStr("Node::Prec::Xor");
|
||||||
|
case Node::Prec::Ior:
|
||||||
|
return printStr("Node::Prec::Ior");
|
||||||
|
case Node::Prec::AndIf:
|
||||||
|
return printStr("Node::Prec::AndIf");
|
||||||
|
case Node::Prec::OrIf:
|
||||||
|
return printStr("Node::Prec::OrIf");
|
||||||
|
case Node::Prec::Conditional:
|
||||||
|
return printStr("Node::Prec::Conditional");
|
||||||
|
case Node::Prec::Assign:
|
||||||
|
return printStr("Node::Prec::Assign");
|
||||||
|
case Node::Prec::Comma:
|
||||||
|
return printStr("Node::Prec::Comma");
|
||||||
|
case Node::Prec::Default:
|
||||||
|
return printStr("Node::Prec::Default");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void newLine() {
|
void newLine() {
|
||||||
printStr("\n");
|
printStr("\n");
|
||||||
|
@ -334,36 +366,21 @@ public:
|
||||||
|
|
||||||
using Demangler = itanium_demangle::ManglingParser<DefaultAllocator>;
|
using Demangler = itanium_demangle::ManglingParser<DefaultAllocator>;
|
||||||
|
|
||||||
char *llvm::itaniumDemangle(const char *MangledName, char *Buf,
|
char *llvm::itaniumDemangle(std::string_view MangledName) {
|
||||||
size_t *N, int *Status) {
|
if (MangledName.empty())
|
||||||
if (MangledName == nullptr || (Buf != nullptr && N == nullptr)) {
|
|
||||||
if (Status)
|
|
||||||
*Status = demangle_invalid_args;
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
|
||||||
|
|
||||||
int InternalStatus = demangle_success;
|
|
||||||
Demangler Parser(MangledName, MangledName + std::strlen(MangledName));
|
|
||||||
OutputStream S;
|
|
||||||
|
|
||||||
|
Demangler Parser(MangledName.data(),
|
||||||
|
MangledName.data() + MangledName.length());
|
||||||
Node *AST = Parser.parse();
|
Node *AST = Parser.parse();
|
||||||
|
if (!AST)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
if (AST == nullptr)
|
OutputBuffer OB;
|
||||||
InternalStatus = demangle_invalid_mangled_name;
|
|
||||||
else if (!initializeOutputStream(Buf, N, S, 1024))
|
|
||||||
InternalStatus = demangle_memory_alloc_failure;
|
|
||||||
else {
|
|
||||||
assert(Parser.ForwardTemplateRefs.empty());
|
assert(Parser.ForwardTemplateRefs.empty());
|
||||||
AST->print(S);
|
AST->print(OB);
|
||||||
S += '\0';
|
OB += '\0';
|
||||||
if (N != nullptr)
|
return OB.getBuffer();
|
||||||
*N = S.getCurrentPosition();
|
|
||||||
Buf = S.getBuffer();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Status)
|
|
||||||
*Status = InternalStatus;
|
|
||||||
return InternalStatus == demangle_success ? Buf : nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ItaniumPartialDemangler::ItaniumPartialDemangler()
|
ItaniumPartialDemangler::ItaniumPartialDemangler()
|
||||||
|
@ -396,14 +413,12 @@ bool ItaniumPartialDemangler::partialDemangle(const char *MangledName) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *printNode(const Node *RootNode, char *Buf, size_t *N) {
|
static char *printNode(const Node *RootNode, char *Buf, size_t *N) {
|
||||||
OutputStream S;
|
OutputBuffer OB(Buf, N);
|
||||||
if (!initializeOutputStream(Buf, N, S, 128))
|
RootNode->print(OB);
|
||||||
return nullptr;
|
OB += '\0';
|
||||||
RootNode->print(S);
|
|
||||||
S += '\0';
|
|
||||||
if (N != nullptr)
|
if (N != nullptr)
|
||||||
*N = S.getCurrentPosition();
|
*N = OB.getCurrentPosition();
|
||||||
return S.getBuffer();
|
return OB.getBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
char *ItaniumPartialDemangler::getFunctionBaseName(char *Buf, size_t *N) const {
|
char *ItaniumPartialDemangler::getFunctionBaseName(char *Buf, size_t *N) const {
|
||||||
|
@ -417,8 +432,8 @@ char *ItaniumPartialDemangler::getFunctionBaseName(char *Buf, size_t *N) const {
|
||||||
case Node::KAbiTagAttr:
|
case Node::KAbiTagAttr:
|
||||||
Name = static_cast<const AbiTagAttr *>(Name)->Base;
|
Name = static_cast<const AbiTagAttr *>(Name)->Base;
|
||||||
continue;
|
continue;
|
||||||
case Node::KStdQualifiedName:
|
case Node::KModuleEntity:
|
||||||
Name = static_cast<const StdQualifiedName *>(Name)->Child;
|
Name = static_cast<const ModuleEntity *>(Name)->Name;
|
||||||
continue;
|
continue;
|
||||||
case Node::KNestedName:
|
case Node::KNestedName:
|
||||||
Name = static_cast<const NestedName *>(Name)->Name;
|
Name = static_cast<const NestedName *>(Name)->Name;
|
||||||
|
@ -441,9 +456,7 @@ char *ItaniumPartialDemangler::getFunctionDeclContextName(char *Buf,
|
||||||
return nullptr;
|
return nullptr;
|
||||||
const Node *Name = static_cast<const FunctionEncoding *>(RootNode)->getName();
|
const Node *Name = static_cast<const FunctionEncoding *>(RootNode)->getName();
|
||||||
|
|
||||||
OutputStream S;
|
OutputBuffer OB(Buf, N);
|
||||||
if (!initializeOutputStream(Buf, N, S, 128))
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
KeepGoingLocalFunction:
|
KeepGoingLocalFunction:
|
||||||
while (true) {
|
while (true) {
|
||||||
|
@ -458,27 +471,27 @@ char *ItaniumPartialDemangler::getFunctionDeclContextName(char *Buf,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Name->getKind() == Node::KModuleEntity)
|
||||||
|
Name = static_cast<const ModuleEntity *>(Name)->Name;
|
||||||
|
|
||||||
switch (Name->getKind()) {
|
switch (Name->getKind()) {
|
||||||
case Node::KStdQualifiedName:
|
|
||||||
S += "std";
|
|
||||||
break;
|
|
||||||
case Node::KNestedName:
|
case Node::KNestedName:
|
||||||
static_cast<const NestedName *>(Name)->Qual->print(S);
|
static_cast<const NestedName *>(Name)->Qual->print(OB);
|
||||||
break;
|
break;
|
||||||
case Node::KLocalName: {
|
case Node::KLocalName: {
|
||||||
auto *LN = static_cast<const LocalName *>(Name);
|
auto *LN = static_cast<const LocalName *>(Name);
|
||||||
LN->Encoding->print(S);
|
LN->Encoding->print(OB);
|
||||||
S += "::";
|
OB += "::";
|
||||||
Name = LN->Entity;
|
Name = LN->Entity;
|
||||||
goto KeepGoingLocalFunction;
|
goto KeepGoingLocalFunction;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
S += '\0';
|
OB += '\0';
|
||||||
if (N != nullptr)
|
if (N != nullptr)
|
||||||
*N = S.getCurrentPosition();
|
*N = OB.getCurrentPosition();
|
||||||
return S.getBuffer();
|
return OB.getBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
char *ItaniumPartialDemangler::getFunctionName(char *Buf, size_t *N) const {
|
char *ItaniumPartialDemangler::getFunctionName(char *Buf, size_t *N) const {
|
||||||
|
@ -494,17 +507,15 @@ char *ItaniumPartialDemangler::getFunctionParameters(char *Buf,
|
||||||
return nullptr;
|
return nullptr;
|
||||||
NodeArray Params = static_cast<FunctionEncoding *>(RootNode)->getParams();
|
NodeArray Params = static_cast<FunctionEncoding *>(RootNode)->getParams();
|
||||||
|
|
||||||
OutputStream S;
|
OutputBuffer OB(Buf, N);
|
||||||
if (!initializeOutputStream(Buf, N, S, 128))
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
S += '(';
|
OB += '(';
|
||||||
Params.printWithComma(S);
|
Params.printWithComma(OB);
|
||||||
S += ')';
|
OB += ')';
|
||||||
S += '\0';
|
OB += '\0';
|
||||||
if (N != nullptr)
|
if (N != nullptr)
|
||||||
*N = S.getCurrentPosition();
|
*N = OB.getCurrentPosition();
|
||||||
return S.getBuffer();
|
return OB.getBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
char *ItaniumPartialDemangler::getFunctionReturnType(
|
char *ItaniumPartialDemangler::getFunctionReturnType(
|
||||||
|
@ -512,18 +523,16 @@ char *ItaniumPartialDemangler::getFunctionReturnType(
|
||||||
if (!isFunction())
|
if (!isFunction())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
OutputStream S;
|
OutputBuffer OB(Buf, N);
|
||||||
if (!initializeOutputStream(Buf, N, S, 128))
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
if (const Node *Ret =
|
if (const Node *Ret =
|
||||||
static_cast<const FunctionEncoding *>(RootNode)->getReturnType())
|
static_cast<const FunctionEncoding *>(RootNode)->getReturnType())
|
||||||
Ret->print(S);
|
Ret->print(OB);
|
||||||
|
|
||||||
S += '\0';
|
OB += '\0';
|
||||||
if (N != nullptr)
|
if (N != nullptr)
|
||||||
*N = S.getCurrentPosition();
|
*N = OB.getCurrentPosition();
|
||||||
return S.getBuffer();
|
return OB.getBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
char *ItaniumPartialDemangler::finishDemangle(char *Buf, size_t *N) const {
|
char *ItaniumPartialDemangler::finishDemangle(char *Buf, size_t *N) const {
|
||||||
|
@ -563,8 +572,8 @@ bool ItaniumPartialDemangler::isCtorOrDtor() const {
|
||||||
case Node::KNestedName:
|
case Node::KNestedName:
|
||||||
N = static_cast<const NestedName *>(N)->Name;
|
N = static_cast<const NestedName *>(N)->Name;
|
||||||
break;
|
break;
|
||||||
case Node::KStdQualifiedName:
|
case Node::KModuleEntity:
|
||||||
N = static_cast<const StdQualifiedName *>(N)->Child;
|
N = static_cast<const ModuleEntity *>(N)->Name;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <string_view>
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
/// This is a llvm local version of __cxa_demangle. Other than the name and
|
/// This is a llvm local version of __cxa_demangle. Other than the name and
|
||||||
|
@ -29,9 +30,10 @@ enum : int {
|
||||||
demangle_success = 0,
|
demangle_success = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
char *itaniumDemangle(const char *mangled_name, char *buf, size_t *n,
|
/// Returns a non-NULL pointer to a NUL-terminated C style string
|
||||||
int *status);
|
/// that should be explicitly freed, if successful. Otherwise, may return
|
||||||
|
/// nullptr if mangled_name is not a valid mangling or is nullptr.
|
||||||
|
char *itaniumDemangle(std::string_view mangled_name);
|
||||||
|
|
||||||
enum MSDemangleFlags {
|
enum MSDemangleFlags {
|
||||||
MSDF_None = 0,
|
MSDF_None = 0,
|
||||||
|
@ -40,10 +42,34 @@ enum MSDemangleFlags {
|
||||||
MSDF_NoCallingConvention = 1 << 2,
|
MSDF_NoCallingConvention = 1 << 2,
|
||||||
MSDF_NoReturnType = 1 << 3,
|
MSDF_NoReturnType = 1 << 3,
|
||||||
MSDF_NoMemberType = 1 << 4,
|
MSDF_NoMemberType = 1 << 4,
|
||||||
|
MSDF_NoVariableType = 1 << 5,
|
||||||
};
|
};
|
||||||
char *microsoftDemangle(const char *mangled_name, char *buf, size_t *n,
|
|
||||||
|
/// Demangles the Microsoft symbol pointed at by mangled_name and returns it.
|
||||||
|
/// Returns a pointer to the start of a null-terminated demangled string on
|
||||||
|
/// success, or nullptr on error.
|
||||||
|
/// If n_read is non-null and demangling was successful, it receives how many
|
||||||
|
/// bytes of the input string were consumed.
|
||||||
|
/// status receives one of the demangle_ enum entries above if it's not nullptr.
|
||||||
|
/// Flags controls various details of the demangled representation.
|
||||||
|
char *microsoftDemangle(std::string_view mangled_name, size_t *n_read,
|
||||||
int *status, MSDemangleFlags Flags = MSDF_None);
|
int *status, MSDemangleFlags Flags = MSDF_None);
|
||||||
|
|
||||||
|
// Demangles a Rust v0 mangled symbol.
|
||||||
|
char *rustDemangle(std::string_view MangledName);
|
||||||
|
|
||||||
|
// Demangles a D mangled symbol.
|
||||||
|
char *dlangDemangle(std::string_view MangledName);
|
||||||
|
|
||||||
|
/// Attempt to demangle a string using different demangling schemes.
|
||||||
|
/// The function uses heuristics to determine which demangling scheme to use.
|
||||||
|
/// \param MangledName - reference to string to demangle.
|
||||||
|
/// \returns - the demangled string, or a copy of the input string if no
|
||||||
|
/// demangling occurred.
|
||||||
|
std::string demangle(std::string_view MangledName);
|
||||||
|
|
||||||
|
bool nonMicrosoftDemangle(std::string_view MangledName, std::string &Result);
|
||||||
|
|
||||||
/// "Partial" demangler. This supports demangling a string into an AST
|
/// "Partial" demangler. This supports demangling a string into an AST
|
||||||
/// (typically an intermediate stage in itaniumDemangle) and querying certain
|
/// (typically an intermediate stage in itaniumDemangle) and querying certain
|
||||||
/// properties or partially printing the demangled name.
|
/// properties or partially printing the demangled name.
|
||||||
|
@ -59,7 +85,7 @@ struct ItaniumPartialDemangler {
|
||||||
bool partialDemangle(const char *MangledName);
|
bool partialDemangle(const char *MangledName);
|
||||||
|
|
||||||
/// Just print the entire mangled name into Buf. Buf and N behave like the
|
/// Just print the entire mangled name into Buf. Buf and N behave like the
|
||||||
/// second and third parameters to itaniumDemangle.
|
/// second and third parameters to __cxa_demangle.
|
||||||
char *finishDemangle(char *Buf, size_t *N) const;
|
char *finishDemangle(char *Buf, size_t *N) const;
|
||||||
|
|
||||||
/// Get the base name of a function. This doesn't include trailing template
|
/// Get the base name of a function. This doesn't include trailing template
|
||||||
|
@ -95,6 +121,7 @@ struct ItaniumPartialDemangler {
|
||||||
bool isSpecialName() const;
|
bool isSpecialName() const;
|
||||||
|
|
||||||
~ItaniumPartialDemangler();
|
~ItaniumPartialDemangler();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void *RootNode;
|
void *RootNode;
|
||||||
void *Context;
|
void *Context;
|
||||||
|
|
|
@ -13,8 +13,8 @@
|
||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#ifndef LLVM_DEMANGLE_COMPILER_H
|
#ifndef LLVM_DEMANGLE_DEMANGLECONFIG_H
|
||||||
#define LLVM_DEMANGLE_COMPILER_H
|
#define LLVM_DEMANGLE_DEMANGLECONFIG_H
|
||||||
|
|
||||||
#ifndef __has_feature
|
#ifndef __has_feature
|
||||||
#define __has_feature(x) 0
|
#define __has_feature(x) 0
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,96 @@
|
||||||
|
//===--- ItaniumNodes.def ------------*- mode:c++;eval:(read-only-mode) -*-===//
|
||||||
|
// Do not edit! See README.txt.
|
||||||
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||||
|
// See https://llvm.org/LICENSE.txt for license information.
|
||||||
|
// SPDX-FileCopyrightText: Part of the LLVM Project
|
||||||
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// Define the demangler's node names
|
||||||
|
|
||||||
|
#ifndef NODE
|
||||||
|
#error Define NODE to handle nodes
|
||||||
|
#endif
|
||||||
|
|
||||||
|
NODE(NodeArrayNode)
|
||||||
|
NODE(DotSuffix)
|
||||||
|
NODE(VendorExtQualType)
|
||||||
|
NODE(QualType)
|
||||||
|
NODE(ConversionOperatorType)
|
||||||
|
NODE(PostfixQualifiedType)
|
||||||
|
NODE(ElaboratedTypeSpefType)
|
||||||
|
NODE(NameType)
|
||||||
|
NODE(AbiTagAttr)
|
||||||
|
NODE(EnableIfAttr)
|
||||||
|
NODE(ObjCProtoName)
|
||||||
|
NODE(PointerType)
|
||||||
|
NODE(ReferenceType)
|
||||||
|
NODE(PointerToMemberType)
|
||||||
|
NODE(ArrayType)
|
||||||
|
NODE(FunctionType)
|
||||||
|
NODE(NoexceptSpec)
|
||||||
|
NODE(DynamicExceptionSpec)
|
||||||
|
NODE(FunctionEncoding)
|
||||||
|
NODE(LiteralOperator)
|
||||||
|
NODE(SpecialName)
|
||||||
|
NODE(CtorVtableSpecialName)
|
||||||
|
NODE(QualifiedName)
|
||||||
|
NODE(NestedName)
|
||||||
|
NODE(LocalName)
|
||||||
|
NODE(ModuleName)
|
||||||
|
NODE(ModuleEntity)
|
||||||
|
NODE(VectorType)
|
||||||
|
NODE(PixelVectorType)
|
||||||
|
NODE(BinaryFPType)
|
||||||
|
NODE(BitIntType)
|
||||||
|
NODE(SyntheticTemplateParamName)
|
||||||
|
NODE(TypeTemplateParamDecl)
|
||||||
|
NODE(NonTypeTemplateParamDecl)
|
||||||
|
NODE(TemplateTemplateParamDecl)
|
||||||
|
NODE(TemplateParamPackDecl)
|
||||||
|
NODE(ParameterPack)
|
||||||
|
NODE(TemplateArgumentPack)
|
||||||
|
NODE(ParameterPackExpansion)
|
||||||
|
NODE(TemplateArgs)
|
||||||
|
NODE(ForwardTemplateReference)
|
||||||
|
NODE(NameWithTemplateArgs)
|
||||||
|
NODE(GlobalQualifiedName)
|
||||||
|
NODE(ExpandedSpecialSubstitution)
|
||||||
|
NODE(SpecialSubstitution)
|
||||||
|
NODE(CtorDtorName)
|
||||||
|
NODE(DtorName)
|
||||||
|
NODE(UnnamedTypeName)
|
||||||
|
NODE(ClosureTypeName)
|
||||||
|
NODE(StructuredBindingName)
|
||||||
|
NODE(BinaryExpr)
|
||||||
|
NODE(ArraySubscriptExpr)
|
||||||
|
NODE(PostfixExpr)
|
||||||
|
NODE(ConditionalExpr)
|
||||||
|
NODE(MemberExpr)
|
||||||
|
NODE(SubobjectExpr)
|
||||||
|
NODE(EnclosingExpr)
|
||||||
|
NODE(CastExpr)
|
||||||
|
NODE(SizeofParamPackExpr)
|
||||||
|
NODE(CallExpr)
|
||||||
|
NODE(NewExpr)
|
||||||
|
NODE(DeleteExpr)
|
||||||
|
NODE(PrefixExpr)
|
||||||
|
NODE(FunctionParam)
|
||||||
|
NODE(ConversionExpr)
|
||||||
|
NODE(PointerToMemberConversionExpr)
|
||||||
|
NODE(InitListExpr)
|
||||||
|
NODE(FoldExpr)
|
||||||
|
NODE(ThrowExpr)
|
||||||
|
NODE(BoolExpr)
|
||||||
|
NODE(StringLiteral)
|
||||||
|
NODE(LambdaExpr)
|
||||||
|
NODE(EnumLiteral)
|
||||||
|
NODE(IntegerLiteral)
|
||||||
|
NODE(FloatLiteral)
|
||||||
|
NODE(DoubleLiteral)
|
||||||
|
NODE(LongDoubleLiteral)
|
||||||
|
NODE(BracedExpr)
|
||||||
|
NODE(BracedRangeExpr)
|
||||||
|
|
||||||
|
#undef NODE
|
|
@ -1,5 +1,5 @@
|
||||||
//===--- StringView.h -------------------------------------------*- C++ -*-===//
|
//===--- StringView.h ----------------*- mode:c++;eval:(read-only-mode) -*-===//
|
||||||
//
|
// Do not edit! See README.txt.
|
||||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||||
// See https://llvm.org/LICENSE.txt for license information.
|
// See https://llvm.org/LICENSE.txt for license information.
|
||||||
// SPDX-FileCopyrightText: Part of the LLVM Project
|
// SPDX-FileCopyrightText: Part of the LLVM Project
|
||||||
|
@ -8,6 +8,9 @@
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
//
|
//
|
||||||
// FIXME: Use std::string_view instead when we support C++17.
|
// 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.
|
||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
@ -15,7 +18,6 @@
|
||||||
#define DEMANGLE_STRINGVIEW_H
|
#define DEMANGLE_STRINGVIEW_H
|
||||||
|
|
||||||
#include "DemangleConfig.h"
|
#include "DemangleConfig.h"
|
||||||
#include <algorithm>
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
|
@ -37,29 +39,23 @@ public:
|
||||||
StringView(const char *Str) : First(Str), Last(Str + std::strlen(Str)) {}
|
StringView(const char *Str) : First(Str), Last(Str + std::strlen(Str)) {}
|
||||||
StringView() : First(nullptr), Last(nullptr) {}
|
StringView() : First(nullptr), Last(nullptr) {}
|
||||||
|
|
||||||
StringView substr(size_t From) const {
|
StringView substr(size_t Pos, size_t Len = npos) const {
|
||||||
return StringView(begin() + From, size() - From);
|
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 {
|
size_t find(char C, size_t From = 0) const {
|
||||||
size_t FindBegin = std::min(From, size());
|
|
||||||
// Avoid calling memchr with nullptr.
|
// Avoid calling memchr with nullptr.
|
||||||
if (FindBegin < size()) {
|
if (From < size()) {
|
||||||
// Just forward to memchr, which is faster than a hand-rolled loop.
|
// Just forward to memchr, which is faster than a hand-rolled loop.
|
||||||
if (const void *P = ::memchr(First + FindBegin, C, size() - FindBegin))
|
if (const void *P = ::memchr(First + From, C, size() - From))
|
||||||
return size_t(static_cast<const char *>(P) - First);
|
return size_t(static_cast<const char *>(P) - First);
|
||||||
}
|
}
|
||||||
return npos;
|
return npos;
|
||||||
}
|
}
|
||||||
|
|
||||||
StringView substr(size_t From, size_t To) const {
|
|
||||||
if (To >= size())
|
|
||||||
To = size() - 1;
|
|
||||||
if (From >= size())
|
|
||||||
From = size() - 1;
|
|
||||||
return StringView(First + From, First + To);
|
|
||||||
}
|
|
||||||
|
|
||||||
StringView dropFront(size_t N = 1) const {
|
StringView dropFront(size_t N = 1) const {
|
||||||
if (N >= size())
|
if (N >= size())
|
||||||
N = size();
|
N = size();
|
||||||
|
@ -106,7 +102,7 @@ public:
|
||||||
bool startsWith(StringView Str) const {
|
bool startsWith(StringView Str) const {
|
||||||
if (Str.size() > size())
|
if (Str.size() > size())
|
||||||
return false;
|
return false;
|
||||||
return std::equal(Str.begin(), Str.end(), begin());
|
return std::strncmp(Str.begin(), begin(), Str.size()) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char &operator[](size_t Idx) const { return *(begin() + Idx); }
|
const char &operator[](size_t Idx) const { return *(begin() + Idx); }
|
||||||
|
@ -119,7 +115,7 @@ public:
|
||||||
|
|
||||||
inline bool operator==(const StringView &LHS, const StringView &RHS) {
|
inline bool operator==(const StringView &LHS, const StringView &RHS) {
|
||||||
return LHS.size() == RHS.size() &&
|
return LHS.size() == RHS.size() &&
|
||||||
std::equal(LHS.begin(), LHS.end(), RHS.begin());
|
std::strncmp(LHS.begin(), RHS.begin(), LHS.size()) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEMANGLE_NAMESPACE_END
|
DEMANGLE_NAMESPACE_END
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
//===--- StringViewExtras.h ----------*- mode:c++;eval:(read-only-mode) -*-===//
|
||||||
|
// Do not edit! See README.txt.
|
||||||
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||||
|
// See https://llvm.org/LICENSE.txt for license information.
|
||||||
|
// SPDX-FileCopyrightText: Part of the LLVM Project
|
||||||
|
// 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
|
|
@ -1,5 +1,5 @@
|
||||||
//===--- Utility.h ----------------------------------------------*- C++ -*-===//
|
//===--- Utility.h -------------------*- mode:c++;eval:(read-only-mode) -*-===//
|
||||||
//
|
// Do not edit! See README.txt.
|
||||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||||
// See https://llvm.org/LICENSE.txt for license information.
|
// See https://llvm.org/LICENSE.txt for license information.
|
||||||
// SPDX-FileCopyrightText: Part of the LLVM Project
|
// SPDX-FileCopyrightText: Part of the LLVM Project
|
||||||
|
@ -7,70 +7,83 @@
|
||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
//
|
//
|
||||||
// Provide some utility classes for use in the demangler(s).
|
// Provide some utility classes for use in the demangler.
|
||||||
|
// There are two copies of this file in the source tree. The one in libcxxabi
|
||||||
|
// is the original and the one in llvm is the copy. Use cp-to-llvm.sh to update
|
||||||
|
// the copy. See README.txt for more details.
|
||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#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 <cassert>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <iterator>
|
#include <exception>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
#include <string_view>
|
||||||
|
|
||||||
DEMANGLE_NAMESPACE_BEGIN
|
DEMANGLE_NAMESPACE_BEGIN
|
||||||
|
|
||||||
// Stream that AST nodes write their string representation into after the AST
|
// Stream that AST nodes write their string representation into after the AST
|
||||||
// has been parsed.
|
// has been parsed.
|
||||||
class OutputStream {
|
class OutputBuffer {
|
||||||
char *Buffer;
|
char *Buffer = nullptr;
|
||||||
size_t CurrentPosition;
|
size_t CurrentPosition = 0;
|
||||||
size_t BufferCapacity;
|
size_t BufferCapacity = 0;
|
||||||
|
|
||||||
// Ensure there is at least n more positions in buffer.
|
// Ensure there are at least N more positions in the buffer.
|
||||||
void grow(size_t N) {
|
void grow(size_t N) {
|
||||||
if (N + CurrentPosition >= BufferCapacity) {
|
size_t Need = N + CurrentPosition;
|
||||||
|
if (Need > BufferCapacity) {
|
||||||
|
// Reduce the number of reallocations, with a bit of hysteresis. The
|
||||||
|
// number here is chosen so the first allocation will more-than-likely not
|
||||||
|
// allocate more than 1K.
|
||||||
|
Need += 1024 - 32;
|
||||||
BufferCapacity *= 2;
|
BufferCapacity *= 2;
|
||||||
if (BufferCapacity < N + CurrentPosition)
|
if (BufferCapacity < Need)
|
||||||
BufferCapacity = N + CurrentPosition;
|
BufferCapacity = Need;
|
||||||
Buffer = static_cast<char *>(std::realloc(Buffer, BufferCapacity));
|
Buffer = static_cast<char *>(std::realloc(Buffer, BufferCapacity));
|
||||||
if (Buffer == nullptr)
|
if (Buffer == nullptr)
|
||||||
std::terminate();
|
std::terminate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void writeUnsigned(uint64_t N, bool isNeg = false) {
|
OutputBuffer &writeUnsigned(uint64_t N, bool isNeg = false) {
|
||||||
// Handle special case...
|
std::array<char, 21> Temp;
|
||||||
if (N == 0) {
|
char *TempPtr = Temp.data() + Temp.size();
|
||||||
*this << '0';
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
char Temp[21];
|
// Output at least one character.
|
||||||
char *TempPtr = std::end(Temp);
|
do {
|
||||||
|
*--TempPtr = char('0' + N % 10);
|
||||||
while (N) {
|
|
||||||
*--TempPtr = '0' + char(N % 10);
|
|
||||||
N /= 10;
|
N /= 10;
|
||||||
}
|
} while (N);
|
||||||
|
|
||||||
// Add negative sign...
|
// Add negative sign.
|
||||||
if (isNeg)
|
if (isNeg)
|
||||||
*--TempPtr = '-';
|
*--TempPtr = '-';
|
||||||
this->operator<<(StringView(TempPtr, std::end(Temp)));
|
|
||||||
|
return operator+=(
|
||||||
|
std::string_view(TempPtr, Temp.data() + Temp.size() - TempPtr));
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
OutputStream(char *StartBuf, size_t Size)
|
OutputBuffer(char *StartBuf, size_t Size)
|
||||||
: Buffer(StartBuf), CurrentPosition(0), BufferCapacity(Size) {}
|
: Buffer(StartBuf), BufferCapacity(Size) {}
|
||||||
OutputStream() = default;
|
OutputBuffer(char *StartBuf, size_t *SizePtr)
|
||||||
void reset(char *Buffer_, size_t BufferCapacity_) {
|
: OutputBuffer(StartBuf, StartBuf ? *SizePtr : 0) {}
|
||||||
CurrentPosition = 0;
|
OutputBuffer() = default;
|
||||||
Buffer = Buffer_;
|
// Non-copyable
|
||||||
BufferCapacity = BufferCapacity_;
|
OutputBuffer(const OutputBuffer &) = delete;
|
||||||
|
OutputBuffer &operator=(const OutputBuffer &) = delete;
|
||||||
|
|
||||||
|
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
|
||||||
|
@ -78,115 +91,116 @@ public:
|
||||||
unsigned CurrentPackIndex = std::numeric_limits<unsigned>::max();
|
unsigned CurrentPackIndex = std::numeric_limits<unsigned>::max();
|
||||||
unsigned CurrentPackMax = std::numeric_limits<unsigned>::max();
|
unsigned CurrentPackMax = std::numeric_limits<unsigned>::max();
|
||||||
|
|
||||||
OutputStream &operator+=(StringView R) {
|
/// When zero, we're printing template args and '>' needs to be parenthesized.
|
||||||
size_t Size = R.size();
|
/// Use a counter so we can simply increment inside parentheses.
|
||||||
if (Size == 0)
|
unsigned GtIsGt = 1;
|
||||||
return *this;
|
|
||||||
|
bool isGtInsideTemplateArgs() const { return GtIsGt == 0; }
|
||||||
|
|
||||||
|
void printOpen(char Open = '(') {
|
||||||
|
GtIsGt++;
|
||||||
|
*this += Open;
|
||||||
|
}
|
||||||
|
void printClose(char Close = ')') {
|
||||||
|
GtIsGt--;
|
||||||
|
*this += Close;
|
||||||
|
}
|
||||||
|
|
||||||
|
OutputBuffer &operator+=(std::string_view R) {
|
||||||
|
if (size_t Size = R.size()) {
|
||||||
grow(Size);
|
grow(Size);
|
||||||
std::memmove(Buffer + CurrentPosition, R.begin(), Size);
|
std::memcpy(Buffer + CurrentPosition, &*R.begin(), Size);
|
||||||
CurrentPosition += Size;
|
CurrentPosition += Size;
|
||||||
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
OutputStream &operator+=(char C) {
|
OutputBuffer &operator+=(char C) {
|
||||||
grow(1);
|
grow(1);
|
||||||
Buffer[CurrentPosition++] = C;
|
Buffer[CurrentPosition++] = C;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
OutputStream &operator<<(StringView R) { return (*this += R); }
|
OutputBuffer &prepend(std::string_view R) {
|
||||||
|
size_t Size = R.size();
|
||||||
|
|
||||||
OutputStream &operator<<(char C) { return (*this += C); }
|
grow(Size);
|
||||||
|
std::memmove(Buffer + Size, Buffer, CurrentPosition);
|
||||||
|
std::memcpy(Buffer, &*R.begin(), Size);
|
||||||
|
CurrentPosition += Size;
|
||||||
|
|
||||||
OutputStream &operator<<(long long N) {
|
|
||||||
if (N < 0)
|
|
||||||
writeUnsigned(static_cast<unsigned long long>(-N), true);
|
|
||||||
else
|
|
||||||
writeUnsigned(static_cast<unsigned long long>(N));
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
OutputStream &operator<<(unsigned long long N) {
|
OutputBuffer &operator<<(std::string_view R) { return (*this += R); }
|
||||||
writeUnsigned(N, false);
|
|
||||||
return *this;
|
OutputBuffer &operator<<(char C) { return (*this += C); }
|
||||||
|
|
||||||
|
OutputBuffer &operator<<(long long N) {
|
||||||
|
return writeUnsigned(static_cast<unsigned long long>(std::abs(N)), N < 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
OutputStream &operator<<(long N) {
|
OutputBuffer &operator<<(unsigned long long N) {
|
||||||
|
return writeUnsigned(N, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
OutputBuffer &operator<<(long N) {
|
||||||
return this->operator<<(static_cast<long long>(N));
|
return this->operator<<(static_cast<long long>(N));
|
||||||
}
|
}
|
||||||
|
|
||||||
OutputStream &operator<<(unsigned long N) {
|
OutputBuffer &operator<<(unsigned long N) {
|
||||||
return this->operator<<(static_cast<unsigned long long>(N));
|
return this->operator<<(static_cast<unsigned long long>(N));
|
||||||
}
|
}
|
||||||
|
|
||||||
OutputStream &operator<<(int N) {
|
OutputBuffer &operator<<(int N) {
|
||||||
return this->operator<<(static_cast<long long>(N));
|
return this->operator<<(static_cast<long long>(N));
|
||||||
}
|
}
|
||||||
|
|
||||||
OutputStream &operator<<(unsigned int N) {
|
OutputBuffer &operator<<(unsigned int N) {
|
||||||
return this->operator<<(static_cast<unsigned long long>(N));
|
return this->operator<<(static_cast<unsigned long long>(N));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void insert(size_t Pos, const char *S, size_t N) {
|
||||||
|
assert(Pos <= CurrentPosition);
|
||||||
|
if (N == 0)
|
||||||
|
return;
|
||||||
|
grow(N);
|
||||||
|
std::memmove(Buffer + Pos + N, Buffer + Pos, CurrentPosition - Pos);
|
||||||
|
std::memcpy(Buffer + Pos, S, N);
|
||||||
|
CurrentPosition += N;
|
||||||
|
}
|
||||||
|
|
||||||
size_t getCurrentPosition() const { return CurrentPosition; }
|
size_t getCurrentPosition() const { return CurrentPosition; }
|
||||||
void setCurrentPosition(size_t NewPos) { CurrentPosition = NewPos; }
|
void setCurrentPosition(size_t NewPos) { CurrentPosition = NewPos; }
|
||||||
|
|
||||||
char back() const {
|
char back() const {
|
||||||
return CurrentPosition ? Buffer[CurrentPosition - 1] : '\0';
|
assert(CurrentPosition);
|
||||||
|
return Buffer[CurrentPosition - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
bool empty() const { return CurrentPosition == 0; }
|
bool empty() const { return CurrentPosition == 0; }
|
||||||
|
|
||||||
char *getBuffer() { return Buffer; }
|
char *getBuffer() { return Buffer; }
|
||||||
char *getBufferEnd() { return Buffer + CurrentPosition - 1; }
|
char *getBufferEnd() { return Buffer + CurrentPosition - 1; }
|
||||||
size_t getBufferCapacity() { return BufferCapacity; }
|
size_t getBufferCapacity() const { return BufferCapacity; }
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class T> class SwapAndRestore {
|
template <class T> class ScopedOverride {
|
||||||
T &Restore;
|
T &Loc;
|
||||||
T OriginalValue;
|
T Original;
|
||||||
bool ShouldRestore = true;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SwapAndRestore(T &Restore_) : SwapAndRestore(Restore_, Restore_) {}
|
ScopedOverride(T &Loc_) : ScopedOverride(Loc_, Loc_) {}
|
||||||
|
|
||||||
SwapAndRestore(T &Restore_, T NewVal)
|
ScopedOverride(T &Loc_, T NewVal) : Loc(Loc_), Original(Loc_) {
|
||||||
: Restore(Restore_), OriginalValue(Restore) {
|
Loc_ = std::move(NewVal);
|
||||||
Restore = std::move(NewVal);
|
|
||||||
}
|
|
||||||
~SwapAndRestore() {
|
|
||||||
if (ShouldRestore)
|
|
||||||
Restore = std::move(OriginalValue);
|
|
||||||
}
|
}
|
||||||
|
~ScopedOverride() { Loc = std::move(Original); }
|
||||||
|
|
||||||
void shouldRestore(bool ShouldRestore_) { ShouldRestore = ShouldRestore_; }
|
ScopedOverride(const ScopedOverride &) = delete;
|
||||||
|
ScopedOverride &operator=(const ScopedOverride &) = delete;
|
||||||
void restoreNow(bool Force) {
|
|
||||||
if (!Force && !ShouldRestore)
|
|
||||||
return;
|
|
||||||
|
|
||||||
Restore = std::move(OriginalValue);
|
|
||||||
ShouldRestore = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
SwapAndRestore(const SwapAndRestore &) = delete;
|
|
||||||
SwapAndRestore &operator=(const SwapAndRestore &) = delete;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
inline bool initializeOutputStream(char *Buf, size_t *N, OutputStream &S,
|
|
||||||
size_t InitSize) {
|
|
||||||
size_t BufferSize;
|
|
||||||
if (Buf == nullptr) {
|
|
||||||
Buf = static_cast<char *>(std::malloc(InitSize));
|
|
||||||
if (Buf == nullptr)
|
|
||||||
return false;
|
|
||||||
BufferSize = InitSize;
|
|
||||||
} else
|
|
||||||
BufferSize = *N;
|
|
||||||
|
|
||||||
S.reset(Buf, BufferSize);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
DEMANGLE_NAMESPACE_END
|
DEMANGLE_NAMESPACE_END
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue