Index: llvm/include/llvm/Demangle/Demangle.h =================================================================== --- llvm/include/llvm/Demangle/Demangle.h +++ llvm/include/llvm/Demangle/Demangle.h @@ -37,10 +37,6 @@ void (*Callback)(void *, const char *)); -enum MSDemangleFlags { MSDF_None = 0, MSDF_DumpBackrefs = 1 << 0 }; -char *microsoftDemangle(const char *mangled_name, char *buf, size_t *n, - int *status, MSDemangleFlags Flags = MSDF_None); - /// "Partial" demangler. This supports demangling a string into an AST /// (typically an intermediate stage in itaniumDemangle) and querying certain /// properties or partially printing the demangled name. Index: llvm/include/llvm/Support/MicrosoftDemangle.h =================================================================== --- /dev/null +++ llvm/include/llvm/Support/MicrosoftDemangle.h @@ -0,0 +1,28 @@ +//===--- Demangle.h ---------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_MICROSOFT_DEMANGLE_H +#define LLVM_SUPPORT_MICROSOFT_DEMANGLE_H + +#include "llvm/ADT/StringRef.h" + +#include +#include + +namespace llvm { + enum MSDemangleFlags { + MSDF_None = 0, + MSDF_DumpBackrefs = 1 << 0 + }; + + std::string microsoftDemangle(StringRef MangledName, int *status, MSDemangleFlags Flags = MSDF_None); + +} // namespace llvm + +#endif Index: llvm/lib/Demangle/CMakeLists.txt =================================================================== --- llvm/lib/Demangle/CMakeLists.txt +++ llvm/lib/Demangle/CMakeLists.txt @@ -1,6 +1,5 @@ add_llvm_library(LLVMDemangle ItaniumDemangle.cpp - MicrosoftDemangle.cpp ADDITIONAL_HEADER_DIRS "${LLVM_MAIN_INCLUDE_DIR}/llvm/Demangle" Index: llvm/lib/Support/CMakeLists.txt =================================================================== --- llvm/lib/Support/CMakeLists.txt +++ llvm/lib/Support/CMakeLists.txt @@ -95,6 +95,7 @@ MathExtras.cpp MemoryBuffer.cpp MD5.cpp + MicrosoftDemangle.cpp NativeFormatting.cpp Options.cpp Parallel.cpp Index: llvm/lib/Support/MicrosoftDemangle.cpp =================================================================== --- llvm/lib/Support/MicrosoftDemangle.cpp +++ llvm/lib/Support/MicrosoftDemangle.cpp @@ -14,106 +14,70 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Demangle/Demangle.h" +#include "llvm/Support/MicrosoftDemangle.h" -#include "llvm/Demangle/Compiler.h" -#include "llvm/Demangle/StringView.h" -#include "llvm/Demangle/Utility.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/StringSaver.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/Compiler.h" #include #include #include #include -// This memory allocator is extremely fast, but it doesn't call dtors -// for allocated objects. That means you can't use STL containers -// (such as std::vector) with this allocator. But it pays off -- -// the demangler is 3x faster with this allocator compared to one with -// STL containers. -namespace { - constexpr size_t AllocUnit = 4096; - -class ArenaAllocator { - struct AllocatorNode { - uint8_t *Buf = nullptr; - size_t Used = 0; - size_t Capacity = 0; - AllocatorNode *Next = nullptr; - }; +using namespace llvm; - void addNode(size_t Capacity) { - AllocatorNode *NewHead = new AllocatorNode; - NewHead->Buf = new uint8_t[Capacity]; - NewHead->Next = Head; - NewHead->Capacity = Capacity; - Head = NewHead; - NewHead->Used = 0; - } +template static T *allocate(BumpPtrAllocator &Allocator, Args &&... CtorArgs) { + void *V = Allocator.Allocate(sizeof(T), alignof(T)); + return new (V) T(std::forward(CtorArgs)...); +} -public: - ArenaAllocator() { addNode(AllocUnit); } - - ~ArenaAllocator() { - while (Head) { - assert(Head->Buf); - delete[] Head->Buf; - AllocatorNode *Next = Head->Next; - delete Head; - Head = Next; - } - } - char *allocUnalignedBuffer(size_t Length) { - uint8_t *Buf = Head->Buf + Head->Used; +static char pop(StringRef &S) { + char C = S.front(); + S = S.drop_front(); + return C; +} - Head->Used += Length; - if (Head->Used > Head->Capacity) { - // It's possible we need a buffer which is larger than our default unit - // size, so we need to be careful to add a node with capacity that is at - // least as large as what we need. - addNode(std::max(AllocUnit, Length)); - Head->Used = Length; - Buf = Head->Buf; - } +static bool startswithDigit(StringRef S) { + return !S.empty() && std::isdigit(S.front()); +} - return reinterpret_cast(Buf); +class peekable_raw_ostream : public raw_ostream { +public: + explicit peekable_raw_ostream(raw_ostream &OS) + : OS(OS) { + SetUnbuffered(); } + + bool empty() const { return !LastChar.hasValue(); } - template T *alloc(Args &&... ConstructorArgs) { - - size_t Size = sizeof(T); - assert(Head && Head->Buf); - - size_t P = (size_t)Head->Buf + Head->Used; - uintptr_t AlignedP = - (((size_t)P + alignof(T) - 1) & ~(size_t)(alignof(T) - 1)); - uint8_t *PP = (uint8_t *)AlignedP; - size_t Adjustment = AlignedP - P; + char peek() const { return *LastChar; } - Head->Used += Size + Adjustment; - if (Head->Used < Head->Capacity) - return new (PP) T(std::forward(ConstructorArgs)...); - - addNode(AllocUnit); - Head->Used = Size; - return new (Head->Buf) T(std::forward(ConstructorArgs)...); +private: + void write_impl(const char *Ptr, size_t N) override { + OS.write(Ptr, N); + OS.flush(); + if (N > 0) + LastChar = Ptr[N - 1]; } -private: - AllocatorNode *Head = nullptr; -}; -} // namespace + uint64_t current_pos() const override { return OS.tell(); } -static bool startsWithDigit(StringView S) { - return !S.empty() && std::isdigit(S.front()); -} + Optional LastChar; + raw_ostream &OS; +}; // Writes a space if the last token does not end with a punctuation. -static void outputSpaceIfNecessary(OutputStream &OS) { +static void outputSpaceIfNecessary(peekable_raw_ostream &OS) { if (OS.empty()) return; - char C = OS.back(); + char C = OS.peek(); if (isalnum(C) || C == '>') OS << " "; } @@ -248,7 +212,7 @@ Vcall, // ?_9 # vcall Typeof, // ?_A # typeof LocalStaticGuard, // ?_B # local static guard - StringLiteral, // ?_C # string literal + StringLiteralSymbol, // ?_C # string literal VbaseDtor, // ?_D # vbase destructor VecDelDtor, // ?_E # vector deleting destructor DefaultCtorClosure, // ?_F # default constructor closure @@ -290,8 +254,8 @@ // A map to translate from operator prefix to operator type. struct OperatorMapEntry { - StringView Prefix; - StringView Name; + StringRef Prefix; + StringRef Name; OperatorTy Operator; }; @@ -346,7 +310,7 @@ {"_9", "`vcall'", OperatorTy::Vcall}, {"_A", "`typeof'", OperatorTy::Typeof}, {"_B", "`local static guard'", OperatorTy::LocalStaticGuard}, - {"_C", "`string'", OperatorTy::StringLiteral}, + {"_C", "`string'", OperatorTy::StringLiteralSymbol}, {"_D", "`vbase dtor'", OperatorTy::VbaseDtor}, {"_E", "`vector deleting dtor'", OperatorTy::VecDelDtor}, {"_F", "`default ctor closure'", OperatorTy::DefaultCtorClosure}, @@ -469,26 +433,26 @@ struct Type { virtual ~Type() {} - virtual Type *clone(ArenaAllocator &Arena) const; + virtual Type *clone(BumpPtrAllocator &Arena) const; // Write the "first half" of a given type. This is a static functions to // give the code a chance to do processing that is common to a subset of // subclasses - static void outputPre(OutputStream &OS, Type &Ty); + static void outputPre(peekable_raw_ostream &OS, Type &Ty); // Write the "second half" of a given type. This is a static functions to // give the code a chance to do processing that is common to a subset of // subclasses - static void outputPost(OutputStream &OS, Type &Ty); + static void outputPost(peekable_raw_ostream &OS, Type &Ty); - virtual void outputPre(OutputStream &OS); - virtual void outputPost(OutputStream &OS); + virtual void outputPre(peekable_raw_ostream &OS); + virtual void outputPost(peekable_raw_ostream &OS); // Primitive type such as Int. PrimTy Prim = PrimTy::Unknown; Qualifiers Quals = Q_None; - StringView Custom; + StringRef Custom; StorageClass Storage = StorageClass::None; // storage class }; @@ -500,10 +464,10 @@ bool IsOperator = false; bool IsBackReference = false; - bool isStringLiteralOperatorInfo() const; + bool isStringLiteralSymbolOperatorInfo() const; // Name read from an MangledName string. - StringView Str; + StringRef Str; // Template parameters. Only valid if IsTemplateInstantiation is true. TemplateParams *TParams = nullptr; @@ -535,8 +499,8 @@ const Name *TableTarget = nullptr; }; -struct StringLiteral : public OperatorInfo { - StringLiteral() : OperatorInfo(OperatorTy::StringLiteral) {} +struct StringLiteralSymbol : public OperatorInfo { + StringLiteralSymbol() : OperatorInfo(OperatorTy::StringLiteralSymbol) {} PrimTy CharType; bool IsTruncated = false; @@ -567,9 +531,9 @@ }; struct PointerType : public Type { - Type *clone(ArenaAllocator &Arena) const override; - void outputPre(OutputStream &OS) override; - void outputPost(OutputStream &OS) override; + Type *clone(BumpPtrAllocator &Arena) const override; + void outputPre(peekable_raw_ostream &OS) override; + void outputPost(peekable_raw_ostream &OS) override; PointerAffinity Affinity; @@ -579,9 +543,9 @@ }; struct MemberPointerType : public Type { - Type *clone(ArenaAllocator &Arena) const override; - void outputPre(OutputStream &OS) override; - void outputPost(OutputStream &OS) override; + Type *clone(BumpPtrAllocator &Arena) const override; + void outputPre(peekable_raw_ostream &OS) override; + void outputPost(peekable_raw_ostream &OS) override; Name *MemberName = nullptr; @@ -598,9 +562,9 @@ int32_t VtordispOffset = 0; }; - Type *clone(ArenaAllocator &Arena) const override; - void outputPre(OutputStream &OS) override; - void outputPost(OutputStream &OS) override; + Type *clone(BumpPtrAllocator &Arena) const override; + void outputPre(peekable_raw_ostream &OS) override; + void outputPost(peekable_raw_ostream &OS) override; // True if this FunctionType instance is the Pointee of a PointerType or // MemberPointerType. @@ -621,8 +585,8 @@ }; struct UdtType : public Type { - Type *clone(ArenaAllocator &Arena) const override; - void outputPre(OutputStream &OS) override; + Type *clone(BumpPtrAllocator &Arena) const override; + void outputPre(peekable_raw_ostream &OS) override; Name *UdtName = nullptr; }; @@ -633,9 +597,9 @@ }; struct ArrayType : public Type { - Type *clone(ArenaAllocator &Arena) const override; - void outputPre(OutputStream &OS) override; - void outputPost(OutputStream &OS) override; + Type *clone(BumpPtrAllocator &Arena) const override; + void outputPre(peekable_raw_ostream &OS) override; + void outputPost(peekable_raw_ostream &OS) override; // Either NextDimension or ElementType will be valid. ArrayDimension *Dims = nullptr; @@ -645,8 +609,8 @@ } // namespace -static bool isMemberPointer(StringView MangledName) { - switch (MangledName.popFront()) { +static bool isMemberPointer(StringRef MangledName) { + switch (MangledName.front()) { case '$': // This is probably an rvalue reference (e.g. $$Q), and you cannot have an // rvalue reference to a member. @@ -665,19 +629,20 @@ default: assert(false && "Ty is not a pointer type!"); } + MangledName = MangledName.drop_front(); // If it starts with a number, then 6 indicates a non-member function // pointer, and 8 indicates a member function pointer. - if (startsWithDigit(MangledName)) { + if (startswithDigit(MangledName)) { assert(MangledName[0] == '6' || MangledName[0] == '8'); return (MangledName[0] == '8'); } // Remove ext qualifiers since those can appear on either type and are // therefore not indicative. - MangledName.consumeFront('E'); // 64-bit - MangledName.consumeFront('I'); // restrict - MangledName.consumeFront('F'); // unaligned + MangledName.consume_front("E"); // 64-bit + MangledName.consume_front("I"); // restrict + MangledName.consume_front("F"); // unaligned assert(!MangledName.empty()); @@ -699,7 +664,7 @@ return false; } -static void outputCallingConvention(OutputStream &OS, CallingConv CC) { +static void outputCallingConvention(peekable_raw_ostream &OS, CallingConv CC) { outputSpaceIfNecessary(OS); switch (CC) { @@ -735,16 +700,16 @@ } } -static bool startsWithLocalScopePattern(StringView S) { - if (!S.consumeFront('?')) +static bool startswithLocalScopePattern(StringRef S) { + if (!S.consume_front("?")) return false; if (S.size() < 2) return false; size_t End = S.find('?'); - if (End == StringView::npos) + if (End == StringRef::npos) return false; - StringView Candidate = S.substr(0, End); + StringRef Candidate = S.substr(0, End); if (Candidate.empty()) return false; @@ -756,7 +721,7 @@ // If it's not 0-9, then it's an encoded number terminated with an @ if (Candidate.back() != '@') return false; - Candidate = Candidate.dropBack(); + Candidate = Candidate.drop_back(); // An encoded number starts with B-P and all subsequent digits are in A-P. // Note that the reason the first digit cannot be A is two fold. First, it @@ -766,18 +731,18 @@ // ambiguity is also why single digit encoded numbers use 0-9 rather than A-J. if (Candidate[0] < 'B' || Candidate[0] > 'P') return false; - Candidate = Candidate.dropFront(); + Candidate = Candidate.drop_front(); while (!Candidate.empty()) { if (Candidate[0] < 'A' || Candidate[0] > 'P') return false; - Candidate = Candidate.dropFront(); + Candidate = Candidate.drop_front(); } return true; } // Write a function or template parameter list. -static void outputParameterList(OutputStream &OS, +static void outputParameterList(peekable_raw_ostream &OS, const FunctionParams &Params) { if (!Params.Current) { OS << "void"; @@ -796,7 +761,7 @@ } } -static void outputStringLiteral(OutputStream &OS, const StringLiteral &Str) { +static void outputStringLiteralSymbol(peekable_raw_ostream &OS, const StringLiteralSymbol &Str) { switch (Str.CharType) { case PrimTy::Wchar: OS << "const wchar_t * {L\""; @@ -819,9 +784,9 @@ OS << "}"; } -static void outputName(OutputStream &OS, const Name *TheName, const Type *Ty); +static void outputName(peekable_raw_ostream &OS, const Name *TheName, const Type *Ty); -static void outputParameterList(OutputStream &OS, +static void outputParameterList(peekable_raw_ostream &OS, const TemplateParams &Params) { if (Params.IsEmptyParameterPack) { OS << "<>"; @@ -880,7 +845,7 @@ OS << ">"; } -static void outputQualifiers(OutputStream &OS, Qualifiers Q) { +static void outputQualifiers(peekable_raw_ostream &OS, Qualifiers Q) { if (Q & Q_Const) { outputSpaceIfNecessary(OS); OS << "const"; @@ -897,7 +862,7 @@ } } -static void outputNameComponent(OutputStream &OS, const Name &N) { +static void outputNameComponent(peekable_raw_ostream &OS, const Name &N) { OS << N.Str; if (N.IsTemplateInstantiation && N.TParams) @@ -914,7 +879,7 @@ return nullptr; } -static void outputName(OutputStream &OS, const Name *TheName, const Type *Ty) { +static void outputName(peekable_raw_ostream &OS, const Name *TheName, const Type *Ty) { if (!TheName) return; @@ -1036,7 +1001,7 @@ } } -static void outputSpecialOperator(OutputStream &OS, const Name *OuterName) { +static void outputSpecialOperator(peekable_raw_ostream &OS, const Name *OuterName) { assert(OuterName); // The last component should be an operator. const OperatorInfo *Operator = lastComponentAsOperator(OuterName); @@ -1044,9 +1009,9 @@ assert(Operator->IsOperator); const OperatorInfo &Oper = static_cast(*Operator); switch (Oper.Info->Operator) { - case OperatorTy::StringLiteral: { - const StringLiteral &SL = static_cast(Oper); - outputStringLiteral(OS, SL); + case OperatorTy::StringLiteralSymbol: { + const StringLiteralSymbol &SL = static_cast(Oper); + outputStringLiteralSymbol(OS, SL); break; } case OperatorTy::Vcall: { @@ -1073,19 +1038,19 @@ namespace { -bool Name::isStringLiteralOperatorInfo() const { +bool Name::isStringLiteralSymbolOperatorInfo() const { if (!IsOperator) return false; const OperatorInfo &O = static_cast(*this); - return O.Info->Operator == OperatorTy::StringLiteral; + return O.Info->Operator == OperatorTy::StringLiteralSymbol; } -Type *Type::clone(ArenaAllocator &Arena) const { - return Arena.alloc(*this); +Type *Type::clone(BumpPtrAllocator &Arena) const { + return allocate(Arena, *this); } // Write the "first half" of a given type. -void Type::outputPre(OutputStream &OS, Type &Ty) { +void Type::outputPre(peekable_raw_ostream &OS, Type &Ty) { // Function types require custom handling of const and static so we // handle them separately. All other types use the same decoration // for these modifiers, so handle them here in common code. @@ -1108,9 +1073,9 @@ } // Write the "second half" of a given type. -void Type::outputPost(OutputStream &OS, Type &Ty) { Ty.outputPost(OS); } +void Type::outputPost(peekable_raw_ostream &OS, Type &Ty) { Ty.outputPost(OS); } -void Type::outputPre(OutputStream &OS) { +void Type::outputPre(peekable_raw_ostream &OS) { switch (Prim) { case PrimTy::Void: OS << "void"; @@ -1182,13 +1147,13 @@ assert(false && "Invalid primitive type!"); } } -void Type::outputPost(OutputStream &OS) {} +void Type::outputPost(peekable_raw_ostream &OS) {} -Type *PointerType::clone(ArenaAllocator &Arena) const { - return Arena.alloc(*this); +Type *PointerType::clone(BumpPtrAllocator &Arena) const { + return allocate(Arena, *this); } -static void outputPointerIndicator(OutputStream &OS, PointerAffinity Affinity, +static void outputPointerIndicator(peekable_raw_ostream &OS, PointerAffinity Affinity, const Name *MemberName, const Type *Pointee) { // "[]" and "()" (for function parameters) take precedence over "*", @@ -1218,7 +1183,7 @@ OS << "&&"; } -void PointerType::outputPre(OutputStream &OS) { +void PointerType::outputPre(peekable_raw_ostream &OS) { Type::outputPre(OS, *Pointee); outputSpaceIfNecessary(OS); @@ -1233,18 +1198,18 @@ // OS << " __ptr64"; } -void PointerType::outputPost(OutputStream &OS) { +void PointerType::outputPost(peekable_raw_ostream &OS) { if (Pointee->Prim == PrimTy::Function || Pointee->Prim == PrimTy::Array) OS << ")"; Type::outputPost(OS, *Pointee); } -Type *MemberPointerType::clone(ArenaAllocator &Arena) const { - return Arena.alloc(*this); +Type *MemberPointerType::clone(BumpPtrAllocator &Arena) const { + return allocate(Arena, *this); } -void MemberPointerType::outputPre(OutputStream &OS) { +void MemberPointerType::outputPre(peekable_raw_ostream &OS) { Type::outputPre(OS, *Pointee); outputSpaceIfNecessary(OS); @@ -1256,18 +1221,18 @@ // OS << " __ptr64"; } -void MemberPointerType::outputPost(OutputStream &OS) { +void MemberPointerType::outputPost(peekable_raw_ostream &OS) { if (Pointee->Prim == PrimTy::Function || Pointee->Prim == PrimTy::Array) OS << ")"; Type::outputPost(OS, *Pointee); } -Type *FunctionType::clone(ArenaAllocator &Arena) const { - return Arena.alloc(*this); +Type *FunctionType::clone(BumpPtrAllocator &Arena) const { + return allocate(Arena, *this); } -void FunctionType::outputPre(OutputStream &OS) { +void FunctionType::outputPre(peekable_raw_ostream &OS) { if ((FunctionClass & StaticThisAdjust) || (FunctionClass & VirtualThisAdjust)) OS << "[thunk]: "; @@ -1293,7 +1258,7 @@ outputCallingConvention(OS, CallConvention); } -void FunctionType::outputPost(OutputStream &OS) { +void FunctionType::outputPost(peekable_raw_ostream &OS) { // extern "C" functions don't have a prototype. if (FunctionClass & NoPrototype) return; @@ -1333,11 +1298,11 @@ return; } -Type *UdtType::clone(ArenaAllocator &Arena) const { - return Arena.alloc(*this); +Type *UdtType::clone(BumpPtrAllocator &Arena) const { + return allocate(Arena, *this); } -void UdtType::outputPre(OutputStream &OS) { +void UdtType::outputPre(peekable_raw_ostream &OS) { switch (Prim) { case PrimTy::Class: OS << "class "; @@ -1358,15 +1323,15 @@ outputName(OS, UdtName, this); } -Type *ArrayType::clone(ArenaAllocator &Arena) const { - return Arena.alloc(*this); +Type *ArrayType::clone(BumpPtrAllocator &Arena) const { + return allocate(Arena, *this); } -void ArrayType::outputPre(OutputStream &OS) { +void ArrayType::outputPre(peekable_raw_ostream &OS) { Type::outputPre(OS, *ElementType); } -void ArrayType::outputPost(OutputStream &OS) { +void ArrayType::outputPost(peekable_raw_ostream &OS) { ArrayDimension *D = Dims; while (D) { OS << "["; @@ -1399,7 +1364,7 @@ // The first 10 BackReferences in a mangled name can be back-referenced by // special name @[0-9]. This is a storage for the first 10 BackReferences. - StringView Names[Max]; + StringRef Names[Max]; size_t NamesCount = 0; }; @@ -1408,15 +1373,16 @@ // It also has a set of functions to cnovert Type instances to strings. class Demangler { public: - Demangler() = default; + Demangler() : Saver(Arena) {} + virtual ~Demangler() = default; // You are supposed to call parse() first and then check if error is true. If // it is false, call output() to write the formatted name to the given stream. - Symbol *parse(StringView &MangledName); - Symbol *parseOperator(StringView &MangledName); + Symbol *parse(StringRef &MangledName); + Symbol *parseOperator(StringRef &MangledName); - void output(const Symbol *S, OutputStream &OS); + void output(const Symbol *S, peekable_raw_ostream &OS); // True if an error occurred. bool Error = false; @@ -1425,71 +1391,73 @@ private: std::pair - demangleSymbolCategoryAndType(StringView &MangledName); + demangleSymbolCategoryAndType(StringRef &MangledName); - Type *demangleVariableEncoding(StringView &MangledName, StorageClass SC); - Type *demangleFunctionEncoding(StringView &MangledName); - uint64_t demangleThunkThisAdjust(StringView &MangledName); + Type *demangleVariableEncoding(StringRef &MangledName, StorageClass SC); + Type *demangleFunctionEncoding(StringRef &MangledName); + uint64_t demangleThunkThisAdjust(StringRef &MangledName); - Qualifiers demanglePointerExtQualifiers(StringView &MangledName); + Qualifiers demanglePointerExtQualifiers(StringRef &MangledName); // Parser functions. This is a recursive-descent parser. - Type *demangleType(StringView &MangledName, QualifierMangleMode QMM); - Type *demangleBasicType(StringView &MangledName); - UdtType *demangleClassType(StringView &MangledName); - PointerType *demanglePointerType(StringView &MangledName); - MemberPointerType *demangleMemberPointerType(StringView &MangledName); - FunctionType *demangleFunctionType(StringView &MangledName, bool HasThisQuals, + Type *demangleType(StringRef &MangledName, QualifierMangleMode QMM); + Type *demangleBasicType(StringRef &MangledName); + UdtType *demangleClassType(StringRef &MangledName); + PointerType *demanglePointerType(StringRef &MangledName); + MemberPointerType *demangleMemberPointerType(StringRef &MangledName); + FunctionType *demangleFunctionType(StringRef &MangledName, bool HasThisQuals, bool IsFunctionPointer); - ArrayType *demangleArrayType(StringView &MangledName); + ArrayType *demangleArrayType(StringRef &MangledName); - TemplateParams *demangleTemplateParameterList(StringView &MangledName); - FunctionParams demangleFunctionParameterList(StringView &MangledName); + TemplateParams *demangleTemplateParameterList(StringRef &MangledName); + FunctionParams demangleFunctionParameterList(StringRef &MangledName); - std::pair demangleNumber(StringView &MangledName); - uint64_t demangleUnsigned(StringView &MangledName); - int64_t demangleSigned(StringView &MangledName); + std::pair demangleNumber(StringRef &MangledName); + uint64_t demangleUnsigned(StringRef &MangledName); + int64_t demangleSigned(StringRef &MangledName); - void memorizeString(StringView s); + void memorizeString(StringRef s); /// Allocate a copy of \p Borrowed into memory that we own. - StringView copyString(StringView Borrowed); + StringRef copyString(StringRef Borrowed); - Name *demangleFullyQualifiedTypeName(StringView &MangledName); - Name *demangleFullyQualifiedSymbolName(StringView &MangledName); + Name *demangleFullyQualifiedTypeName(StringRef &MangledName); + Name *demangleFullyQualifiedSymbolName(StringRef &MangledName); - Name *demangleUnqualifiedTypeName(StringView &MangledName, bool Memorize); - Name *demangleUnqualifiedSymbolName(StringView &MangledName, + Name *demangleUnqualifiedTypeName(StringRef &MangledName, bool Memorize); + Name *demangleUnqualifiedSymbolName(StringRef &MangledName, NameBackrefBehavior NBB); - Name *demangleNameScopeChain(StringView &MangledName, Name *UnqualifiedName); - Name *demangleNameScopePiece(StringView &MangledName); + Name *demangleNameScopeChain(StringRef &MangledName, Name *UnqualifiedName); + Name *demangleNameScopePiece(StringRef &MangledName); - Name *demangleBackRefName(StringView &MangledName); - Name *demangleTemplateInstantiationName(StringView &MangledName, + Name *demangleBackRefName(StringRef &MangledName); + Name *demangleTemplateInstantiationName(StringRef &MangledName, NameBackrefBehavior NBB); - std::pair demangleOperatorName(StringView &MangledName, + std::pair demangleOperatorName(StringRef &MangledName, bool FullyQualified); - Name *demangleSimpleName(StringView &MangledName, bool Memorize); - Name *demangleAnonymousNamespaceName(StringView &MangledName); - Name *demangleLocallyScopedNamePiece(StringView &MangledName); - StringLiteral *demangleStringLiteral(StringView &MangledName); + Name *demangleSimpleName(StringRef &MangledName, bool Memorize); + Name *demangleAnonymousNamespaceName(StringRef &MangledName); + Name *demangleLocallyScopedNamePiece(StringRef &MangledName); + StringLiteralSymbol *demangleStringLiteralSymbol(StringRef &MangledName); - StringView demangleSimpleString(StringView &MangledName, bool Memorize); + StringRef demangleSimpleString(StringRef &MangledName, bool Memorize); - FuncClass demangleFunctionClass(StringView &MangledName); - CallingConv demangleCallingConvention(StringView &MangledName); - StorageClass demangleVariableStorageClass(StringView &MangledName); - ReferenceKind demangleReferenceKind(StringView &MangledName); - void demangleThrowSpecification(StringView &MangledName); - wchar_t demangleWcharLiteral(StringView &MangledName); - uint8_t demangleCharLiteral(StringView &MangledName); + FuncClass demangleFunctionClass(StringRef &MangledName); + CallingConv demangleCallingConvention(StringRef &MangledName); + StorageClass demangleVariableStorageClass(StringRef &MangledName); + ReferenceKind demangleReferenceKind(StringRef &MangledName); + void demangleThrowSpecification(StringRef &MangledName); + wchar_t demangleWcharLiteral(StringRef &MangledName); + uint8_t demangleCharLiteral(StringRef &MangledName); - std::pair demangleQualifiers(StringView &MangledName); + std::pair demangleQualifiers(StringRef &MangledName); // Memory allocator. - ArenaAllocator Arena; + BumpPtrAllocator Arena; + + StringSaver Saver; // A single type uses one global back-ref table for all function params. // This means back-refs can even go "into" other types. Examples: @@ -1508,21 +1476,18 @@ }; } // namespace -StringView Demangler::copyString(StringView Borrowed) { - char *Stable = Arena.allocUnalignedBuffer(Borrowed.size() + 1); - std::strcpy(Stable, Borrowed.begin()); - - return {Stable, Borrowed.size()}; +StringRef Demangler::copyString(StringRef Borrowed) { + return Saver.save(Borrowed); } -Symbol *Demangler::parseOperator(StringView &MangledName) { - Symbol *S = Arena.alloc(); +Symbol *Demangler::parseOperator(StringRef &MangledName) { + Symbol *S = allocate(Arena); bool IsMember = false; OperatorTy OTy; std::tie(OTy, S->SymbolName) = demangleOperatorName(MangledName, true); switch (OTy) { - case OperatorTy::StringLiteral: + case OperatorTy::StringLiteralSymbol: S->Category = SymbolCategory::SpecialOperator; break; case OperatorTy::Vcall: @@ -1536,12 +1501,12 @@ case OperatorTy::RttiCompleteObjLocator: // Foo@@6B@ case OperatorTy::Vbtable: // Foo@@7B@ S->Category = SymbolCategory::UnnamedVariable; - switch (MangledName.popFront()) { + switch (pop(MangledName)) { case '6': case '7': { std::tie(S->SymbolQuals, IsMember) = demangleQualifiers(MangledName); - if (!MangledName.consumeFront('@')) { - IndirectTable *Table = Arena.alloc(OTy); + if (!MangledName.consume_front("@")) { + IndirectTable *Table = allocate(Arena, OTy); Table->TableTarget = demangleFullyQualifiedTypeName(MangledName); Table->TableLocation = S->SymbolName; S->SymbolName = Table; @@ -1558,7 +1523,7 @@ S->SymbolType = demangleType(MangledName, QualifierMangleMode::Result); if (Error) break; - if (!MangledName.consumeFront("@8")) + if (!MangledName.consume_front("@8")) Error = true; if (!MangledName.empty()) Error = true; @@ -1574,7 +1539,7 @@ } std::pair -Demangler::demangleSymbolCategoryAndType(StringView &MangledName) { +Demangler::demangleSymbolCategoryAndType(StringRef &MangledName) { // Read a variable. switch (MangledName.front()) { case '0': @@ -1587,7 +1552,7 @@ demangleVariableEncoding(MangledName, demangleVariableStorageClass(MangledName))); case '8': - MangledName.consumeFront('8'); + MangledName.consume_front("8"); return std::pair(SymbolCategory::UnnamedVariable, nullptr); } @@ -1596,27 +1561,27 @@ } // Parser entry point. -Symbol *Demangler::parse(StringView &MangledName) { +Symbol *Demangler::parse(StringRef &MangledName) { // We can't demangle MD5 names, just output them as-is. // Also, MSVC-style mangled symbols must start with '?'. - if (MangledName.startsWith("??@") || !MangledName.startsWith('?')) { - Symbol *S = Arena.alloc(); + if (MangledName.startswith("??@") || !MangledName.startswith("?")) { + Symbol *S = allocate(Arena); S->Category = SymbolCategory::Unknown; - S->SymbolName = Arena.alloc(); + S->SymbolName = allocate(Arena); S->SymbolName->Str = MangledName; S->SymbolType = nullptr; - MangledName = StringView(); + MangledName = StringRef(); return S; } - MangledName.consumeFront('?'); + MangledName.consume_front("?"); // ?$ is a template instantiation, but all other names that start with ? are // operators / special names. - if (MangledName.startsWith('?') && !MangledName.startsWith("?$")) + if (MangledName.startswith("?") && !MangledName.startswith("?$")) return parseOperator(MangledName); - Symbol *S = Arena.alloc(); + Symbol *S = allocate(Arena); // What follows is a main symbol name. This may include namespaces or class // back references. S->SymbolName = demangleFullyQualifiedSymbolName(MangledName); @@ -1639,7 +1604,7 @@ // ::= 3 # global // ::= 4 # static local -Type *Demangler::demangleVariableEncoding(StringView &MangledName, +Type *Demangler::demangleVariableEncoding(StringRef &MangledName, StorageClass SC) { Type *Ty = demangleType(MangledName, QualifierMangleMode::Drop); @@ -1689,12 +1654,12 @@ // ::= + @ # when Numbrer == 0 or >= 10 // // ::= [A-P] # A = 0, B = 1, ... -std::pair Demangler::demangleNumber(StringView &MangledName) { - bool IsNegative = MangledName.consumeFront('?'); +std::pair Demangler::demangleNumber(StringRef &MangledName) { + bool IsNegative = MangledName.consume_front("?"); - if (startsWithDigit(MangledName)) { + if (startswithDigit(MangledName)) { uint64_t Ret = MangledName[0] - '0' + 1; - MangledName = MangledName.dropFront(1); + MangledName = MangledName.drop_front(1); return {Ret, IsNegative}; } @@ -1702,7 +1667,7 @@ for (size_t i = 0; i < MangledName.size(); ++i) { char C = MangledName[i]; if (C == '@') { - MangledName = MangledName.dropFront(i + 1); + MangledName = MangledName.drop_front(i + 1); return {Ret, IsNegative}; } if ('A' <= C && C <= 'P') { @@ -1716,7 +1681,7 @@ return {0ULL, false}; } -uint64_t Demangler::demangleUnsigned(StringView &MangledName) { +uint64_t Demangler::demangleUnsigned(StringRef &MangledName) { bool IsNegative = false; uint64_t Number = 0; std::tie(Number, IsNegative) = demangleNumber(MangledName); @@ -1725,7 +1690,7 @@ return Number; } -int64_t Demangler::demangleSigned(StringView &MangledName) { +int64_t Demangler::demangleSigned(StringRef &MangledName) { bool IsNegative = false; uint64_t Number = 0; std::tie(Number, IsNegative) = demangleNumber(MangledName); @@ -1737,7 +1702,7 @@ // First 10 strings can be referenced by special BackReferences ?0, ?1, ..., ?9. // Memorize it. -void Demangler::memorizeString(StringView S) { +void Demangler::memorizeString(StringRef S) { if (Backrefs.NamesCount >= BackrefContext::Max) return; for (size_t i = 0; i < Backrefs.NamesCount; ++i) @@ -1746,8 +1711,8 @@ Backrefs.Names[Backrefs.NamesCount++] = S; } -Name *Demangler::demangleBackRefName(StringView &MangledName) { - assert(startsWithDigit(MangledName)); +Name *Demangler::demangleBackRefName(StringRef &MangledName) { + assert(startswithDigit(MangledName)); size_t I = MangledName[0] - '0'; if (I >= Backrefs.NamesCount) { @@ -1755,16 +1720,16 @@ return nullptr; } - MangledName = MangledName.dropFront(); - Name *Node = Arena.alloc(); + MangledName = MangledName.drop_front(); + Name *Node = allocate(Arena); Node->Str = Backrefs.Names[I]; return Node; } -Name *Demangler::demangleTemplateInstantiationName(StringView &MangledName, +Name *Demangler::demangleTemplateInstantiationName(StringRef &MangledName, NameBackrefBehavior NBB) { - assert(MangledName.startsWith("?$")); - MangledName.consumeFront("?$"); + assert(MangledName.startswith("?$")); + MangledName.consume_front("?$"); BackrefContext OuterContext; std::swap(OuterContext, Backrefs); @@ -1780,29 +1745,28 @@ Node->IsTemplateInstantiation = true; if (NBB & NBB_Template) { + SmallString<128> Buffer; + raw_svector_ostream RawOS(Buffer); + peekable_raw_ostream OS(RawOS); // Render this class template name into a string buffer so that we can // memorize it for the purpose of back-referencing. - OutputStream OS = OutputStream::create(nullptr, nullptr, 1024); outputName(OS, Node, nullptr); - OS << '\0'; - char *Name = OS.getBuffer(); - StringView Owned = copyString(Name); + StringRef Owned = copyString(Buffer); memorizeString(Owned); - std::free(Name); } return Node; } std::pair -Demangler::demangleOperatorName(StringView &MangledName, bool FullyQualified) { - assert(MangledName.startsWith('?')); - MangledName.consumeFront('?'); +Demangler::demangleOperatorName(StringRef &MangledName, bool FullyQualified) { + assert(MangledName.startswith("?")); + MangledName.consume_front("?"); const OperatorMapEntry *Entry = nullptr; for (const auto &MapEntry : OperatorMap) { - if (!MangledName.consumeFront(MapEntry.Prefix)) + if (!MangledName.consume_front(MapEntry.Prefix)) continue; Entry = &MapEntry; break; @@ -1818,23 +1782,23 @@ case OperatorTy::LocalVftable: // Foo@@6B@ case OperatorTy::RttiCompleteObjLocator: // Foo@@6B@ case OperatorTy::Vbtable: { // Foo@@7B@ - N = Arena.alloc(*Entry); + N = allocate(Arena, *Entry); if (FullyQualified) N = demangleNameScopeChain(MangledName, N); break; } - case OperatorTy::StringLiteral: - N = demangleStringLiteral(MangledName); + case OperatorTy::StringLiteralSymbol: + N = demangleStringLiteralSymbol(MangledName); break; case OperatorTy::LiteralOperator: - N = Arena.alloc(*Entry); + N = allocate(Arena, *Entry); N->Str = demangleSimpleString(MangledName, false); - if (!MangledName.consumeFront('@')) + if (!MangledName.consume_front("@")) Error = true; break; case OperatorTy::RttiBaseClassDescriptor: { - RttiBaseClassDescriptor *Temp = Arena.alloc(); + RttiBaseClassDescriptor *Temp = allocate(Arena); Temp->NVOffset = demangleUnsigned(MangledName); Temp->VBPtrOffset = demangleSigned(MangledName); Temp->VBTableOffset = demangleUnsigned(MangledName); @@ -1843,28 +1807,28 @@ break; } case OperatorTy::Vcall: { - VirtualMemberPtrThunk *Temp = Arena.alloc(); + VirtualMemberPtrThunk *Temp = allocate(Arena); N = demangleNameScopeChain(MangledName, Temp); if (Error) break; - if (!MangledName.consumeFront("$B")) + if (!MangledName.consume_front("$B")) Error = true; Temp->OffsetInVTable = demangleUnsigned(MangledName); - if (!MangledName.consumeFront('A')) + if (!MangledName.consume_front("A")) Error = true; Temp->CC = demangleCallingConvention(MangledName); break; } case OperatorTy::RttiTypeDescriptor: // This one is just followed by a type, not a name scope. - N = Arena.alloc(*Entry); + N = allocate(Arena, *Entry); break; case OperatorTy::LocalStaticGuard: { - LocalStaticGuardVariable *Temp = Arena.alloc(); + LocalStaticGuardVariable *Temp = allocate(Arena); N = (FullyQualified) ? demangleNameScopeChain(MangledName, Temp) : Temp; - if (MangledName.consumeFront("4IA")) + if (MangledName.consume_front("4IA")) Temp->IsVisible = false; - else if (MangledName.consumeFront("5")) + else if (MangledName.consume_front("5")) Temp->IsVisible = true; else Error = true; @@ -1873,7 +1837,7 @@ break; } default: - N = Arena.alloc(*Entry); + N = allocate(Arena, *Entry); N = (FullyQualified) ? demangleNameScopeChain(MangledName, N) : N; break; } @@ -1883,12 +1847,12 @@ return std::make_pair(Entry->Operator, N); } -Name *Demangler::demangleSimpleName(StringView &MangledName, bool Memorize) { - StringView S = demangleSimpleString(MangledName, Memorize); +Name *Demangler::demangleSimpleName(StringRef &MangledName, bool Memorize) { + StringRef S = demangleSimpleString(MangledName, Memorize); if (Error) return nullptr; - Name *Node = Arena.alloc(); + Name *Node = allocate(Arena); Node->Str = S; return Node; } @@ -1900,32 +1864,32 @@ return (C <= 'J') ? (C - 'A') : (10 + C - 'K'); } -uint8_t Demangler::demangleCharLiteral(StringView &MangledName) { - if (!MangledName.startsWith('?')) - return MangledName.popFront(); +uint8_t Demangler::demangleCharLiteral(StringRef &MangledName) { + if (!MangledName.startswith("?")) + return pop(MangledName); - MangledName = MangledName.dropFront(); + MangledName = MangledName.drop_front(); if (MangledName.empty()) goto CharLiteralError; - if (MangledName.consumeFront('$')) { + if (MangledName.consume_front("$")) { // Two hex digits if (MangledName.size() < 2) goto CharLiteralError; - StringView Nibbles = MangledName.substr(0, 2); + StringRef Nibbles = MangledName.substr(0, 2); if (!isRebasedHexDigit(Nibbles[0]) || !isRebasedHexDigit(Nibbles[1])) goto CharLiteralError; // Don't append the null terminator. uint8_t C1 = rebasedHexDigitToNumber(Nibbles[0]); uint8_t C2 = rebasedHexDigitToNumber(Nibbles[1]); - MangledName = MangledName.dropFront(2); + MangledName = MangledName.drop_front(2); return (C1 << 4) | C2; } - if (startsWithDigit(MangledName)) { + if (startswithDigit(MangledName)) { const char *Lookup = ",/\\:. \n\t'-"; char C = Lookup[MangledName[0] - '0']; - MangledName = MangledName.dropFront(); + MangledName = MangledName.drop_front(); return C; } @@ -1935,7 +1899,7 @@ '\xEF', '\xF0', '\xF1', '\xF2', '\xF3', '\xF4', '\xF5', '\xF6', '\xF7', '\xF8', '\xF9', '\xFA'}; char C = Lookup[MangledName[0] - 'a']; - MangledName = MangledName.dropFront(); + MangledName = MangledName.drop_front(); return C; } @@ -1945,7 +1909,7 @@ '\xCF', '\xD0', '\xD1', '\xD2', '\xD3', '\xD4', '\xD5', '\xD6', '\xD7', '\xD8', '\xD9', '\xDA'}; char C = Lookup[MangledName[0] - 'A']; - MangledName = MangledName.dropFront(); + MangledName = MangledName.drop_front(); return C; } @@ -1954,7 +1918,7 @@ return '\0'; } -wchar_t Demangler::demangleWcharLiteral(StringView &MangledName) { +wchar_t Demangler::demangleWcharLiteral(StringRef &MangledName) { uint8_t C1, C2; C1 = demangleCharLiteral(MangledName); @@ -1976,7 +1940,7 @@ *Buffer = (Digit < 10) ? ('0' + Digit) : ('A' + Digit - 10); } -static void outputHex(OutputStream &OS, unsigned C) { +static void outputHex(peekable_raw_ostream &OS, unsigned C) { if (C == 0) { OS << "\\x00"; return; @@ -2001,10 +1965,10 @@ TempBuffer[Pos--] = '\\'; assert(Pos >= 0); } - OS << StringView(&TempBuffer[Pos + 1]); + OS << StringRef(&TempBuffer[Pos + 1]); } -static void outputEscapedChar(OutputStream &OS, unsigned C) { +static void outputEscapedChar(peekable_raw_ostream &OS, unsigned C) { switch (C) { case '\'': // single quote OS << "\\\'"; @@ -2116,63 +2080,63 @@ return Result; } -StringLiteral *Demangler::demangleStringLiteral(StringView &MangledName) { +StringLiteralSymbol *Demangler::demangleStringLiteralSymbol(StringRef &MangledName) { // This function uses goto, so declare all variables up front. - OutputStream OS; - StringView CRC; + SmallString<64> Buffer; + raw_svector_ostream RawOS(Buffer); + peekable_raw_ostream OS(RawOS); + StringRef CRC; uint64_t StringByteSize; bool IsWcharT = false; bool IsNegative = false; size_t CrcEndPos = 0; - char *ResultBuffer = nullptr; - StringLiteral *Result = Arena.alloc(); + StringLiteralSymbol *Result = allocate(Arena); // Prefix indicating the beginning of a string literal - if (!MangledName.consumeFront("@_")) - goto StringLiteralError; + if (!MangledName.consume_front("@_")) + goto StringLiteralSymbolError; if (MangledName.empty()) - goto StringLiteralError; + goto StringLiteralSymbolError; // Char Type (regular or wchar_t) - switch (MangledName.popFront()) { + switch (pop(MangledName)) { case '1': IsWcharT = true; LLVM_FALLTHROUGH; case '0': break; default: - goto StringLiteralError; + goto StringLiteralSymbolError; } // Encoded Length std::tie(StringByteSize, IsNegative) = demangleNumber(MangledName); if (Error || IsNegative) - goto StringLiteralError; + goto StringLiteralSymbolError; // CRC 32 (always 8 characters plus a terminator) CrcEndPos = MangledName.find('@'); - if (CrcEndPos == StringView::npos) - goto StringLiteralError; + if (CrcEndPos == StringRef::npos) + goto StringLiteralSymbolError; CRC = MangledName.substr(0, CrcEndPos); - MangledName = MangledName.dropFront(CrcEndPos + 1); + MangledName = MangledName.drop_front(CrcEndPos + 1); if (MangledName.empty()) - goto StringLiteralError; + goto StringLiteralSymbolError; - OS = OutputStream::create(nullptr, nullptr, 1024); if (IsWcharT) { Result->CharType = PrimTy::Wchar; if (StringByteSize > 64) Result->IsTruncated = true; - while (!MangledName.consumeFront('@')) { + while (!MangledName.consume_front("@")) { assert(StringByteSize >= 2); wchar_t W = demangleWcharLiteral(MangledName); if (StringByteSize != 2 || Result->IsTruncated) outputEscapedChar(OS, W); StringByteSize -= 2; if (Error) - goto StringLiteralError; + goto StringLiteralSymbolError; } } else { if (StringByteSize > 32) @@ -2182,7 +2146,7 @@ uint8_t StringBytes[MaxStringByteLength]; unsigned BytesDecoded = 0; - while (!MangledName.consumeFront('@')) { + while (!MangledName.consume_front("@")) { assert(StringByteSize >= 1); StringBytes[BytesDecoded++] = demangleCharLiteral(MangledName); } @@ -2212,25 +2176,22 @@ } } - OS << '\0'; - ResultBuffer = OS.getBuffer(); - Result->Str = copyString(ResultBuffer); - std::free(ResultBuffer); + Result->Str = copyString(Buffer); return Result; -StringLiteralError: +StringLiteralSymbolError: Error = true; return nullptr; } -StringView Demangler::demangleSimpleString(StringView &MangledName, +StringRef Demangler::demangleSimpleString(StringRef &MangledName, bool Memorize) { - StringView S; + StringRef S; for (size_t i = 0; i < MangledName.size(); ++i) { if (MangledName[i] != '@') continue; S = MangledName.substr(0, i); - MangledName = MangledName.dropFront(i + 1); + MangledName = MangledName.drop_front(i + 1); if (Memorize) memorizeString(S); @@ -2241,33 +2202,33 @@ return {}; } -Name *Demangler::demangleAnonymousNamespaceName(StringView &MangledName) { - assert(MangledName.startsWith("?A")); - MangledName.consumeFront("?A"); +Name *Demangler::demangleAnonymousNamespaceName(StringRef &MangledName) { + assert(MangledName.startswith("?A")); + MangledName.consume_front("?A"); - Name *Node = Arena.alloc(); + Name *Node = allocate(Arena); Node->Str = "`anonymous namespace'"; size_t EndPos = MangledName.find('@'); - if (EndPos == StringView::npos) { + if (EndPos == StringRef::npos) { Error = true; return nullptr; } - StringView NamespaceKey = MangledName.substr(0, EndPos); + StringRef NamespaceKey = MangledName.substr(0, EndPos); memorizeString(NamespaceKey); MangledName = MangledName.substr(EndPos + 1); return Node; } -Name *Demangler::demangleLocallyScopedNamePiece(StringView &MangledName) { - assert(startsWithLocalScopePattern(MangledName)); +Name *Demangler::demangleLocallyScopedNamePiece(StringRef &MangledName) { + assert(startswithLocalScopePattern(MangledName)); - Name *Node = Arena.alloc(); - MangledName.consumeFront('?'); + Name *Node = allocate(Arena); + MangledName.consume_front("?"); auto Number = demangleNumber(MangledName); assert(!Number.second); // One ? to terminate the number - MangledName.consumeFront('?'); + MangledName.consume_front("?"); assert(!Error); Symbol *Scope = parse(MangledName); @@ -2275,20 +2236,19 @@ return nullptr; // Render the parent symbol's name into a buffer. - OutputStream OS = OutputStream::create(nullptr, nullptr, 1024); + SmallString<128> Buffer; + raw_svector_ostream RawOS(Buffer); + peekable_raw_ostream OS(RawOS); OS << '`'; output(Scope, OS); OS << '\''; OS << "::`" << Number.first << "'"; - OS << '\0'; - char *Result = OS.getBuffer(); - Node->Str = copyString(Result); - std::free(Result); + Node->Str = copyString(Buffer); return Node; } // Parses a type name in the form of A@B@C@@ which represents C::B::A. -Name *Demangler::demangleFullyQualifiedTypeName(StringView &MangledName) { +Name *Demangler::demangleFullyQualifiedTypeName(StringRef &MangledName) { Name *TypeName = demangleUnqualifiedTypeName(MangledName, true); if (Error) return nullptr; @@ -2304,7 +2264,7 @@ // Parses a symbol name in the form of A@B@C@@ which represents C::B::A. // Symbol names have slightly different rules regarding what can appear // so we separate out the implementations for flexibility. -Name *Demangler::demangleFullyQualifiedSymbolName(StringView &MangledName) { +Name *Demangler::demangleFullyQualifiedSymbolName(StringRef &MangledName) { // This is the final component of a symbol name (i.e. the leftmost component // of a mangled name. Since the only possible template instantiation that // can appear in this context is a function template, and since those are @@ -2321,53 +2281,53 @@ return QualName; } -Name *Demangler::demangleUnqualifiedTypeName(StringView &MangledName, +Name *Demangler::demangleUnqualifiedTypeName(StringRef &MangledName, bool Memorize) { // An inner-most name can be a back-reference, because a fully-qualified name // (e.g. Scope + Inner) can contain other fully qualified names inside of // them (for example template parameters), and these nested parameters can // refer to previously mangled types. - if (startsWithDigit(MangledName)) + if (startswithDigit(MangledName)) return demangleBackRefName(MangledName); - if (MangledName.startsWith("?$")) + if (MangledName.startswith("?$")) return demangleTemplateInstantiationName(MangledName, NBB_Template); return demangleSimpleName(MangledName, Memorize); } -Name *Demangler::demangleUnqualifiedSymbolName(StringView &MangledName, +Name *Demangler::demangleUnqualifiedSymbolName(StringRef &MangledName, NameBackrefBehavior NBB) { - if (startsWithDigit(MangledName)) + if (startswithDigit(MangledName)) return demangleBackRefName(MangledName); - if (MangledName.startsWith("?$")) + if (MangledName.startswith("?$")) return demangleTemplateInstantiationName(MangledName, NBB); - if (MangledName.startsWith('?')) + if (MangledName.startswith("?")) return demangleOperatorName(MangledName, false).second; return demangleSimpleName(MangledName, (NBB & NBB_Simple) != 0); } -Name *Demangler::demangleNameScopePiece(StringView &MangledName) { - if (startsWithDigit(MangledName)) +Name *Demangler::demangleNameScopePiece(StringRef &MangledName) { + if (startswithDigit(MangledName)) return demangleBackRefName(MangledName); - if (MangledName.startsWith("?$")) + if (MangledName.startswith("?$")) return demangleTemplateInstantiationName(MangledName, NBB_Template); - if (MangledName.startsWith("?A")) + if (MangledName.startswith("?A")) return demangleAnonymousNamespaceName(MangledName); - if (startsWithLocalScopePattern(MangledName)) + if (startswithLocalScopePattern(MangledName)) return demangleLocallyScopedNamePiece(MangledName); return demangleSimpleName(MangledName, true); } -Name *Demangler::demangleNameScopeChain(StringView &MangledName, +Name *Demangler::demangleNameScopeChain(StringRef &MangledName, Name *UnqualifiedName) { Name *Head = UnqualifiedName; - while (!MangledName.consumeFront("@")) { + while (!MangledName.consume_front("@")) { if (MangledName.empty()) { Error = true; return nullptr; @@ -2384,11 +2344,8 @@ return Head; } -FuncClass Demangler::demangleFunctionClass(StringView &MangledName) { - SwapAndRestore RestoreOnError(MangledName, MangledName); - RestoreOnError.shouldRestore(false); - - switch (MangledName.popFront()) { +FuncClass Demangler::demangleFunctionClass(StringRef &MangledName) { + switch (pop(MangledName)) { case '9': return FuncClass(ExternC | NoPrototype); case 'A': @@ -2441,10 +2398,10 @@ return FuncClass(Global | Far); case '$': { FuncClass VFlag = VirtualThisAdjust; - if (MangledName.consumeFront('R')) + if (MangledName.consume_front("R")) VFlag = FuncClass(VFlag | VirtualThisAdjustEx); - switch (MangledName.popFront()) { + switch (pop(MangledName)) { case '0': return FuncClass(Private | Virtual | VFlag); case '1': @@ -2462,12 +2419,11 @@ } Error = true; - RestoreOnError.shouldRestore(true); return Public; } -CallingConv Demangler::demangleCallingConvention(StringView &MangledName) { - switch (MangledName.popFront()) { +CallingConv Demangler::demangleCallingConvention(StringRef &MangledName) { + switch (pop(MangledName)) { case 'A': case 'B': return CallingConv::Cdecl; @@ -2496,10 +2452,10 @@ return CallingConv::None; } -StorageClass Demangler::demangleVariableStorageClass(StringView &MangledName) { +StorageClass Demangler::demangleVariableStorageClass(StringRef &MangledName) { assert(std::isdigit(MangledName.front())); - switch (MangledName.popFront()) { + switch (pop(MangledName)) { case '0': return StorageClass::PrivateStatic; case '1': @@ -2516,9 +2472,9 @@ } std::pair -Demangler::demangleQualifiers(StringView &MangledName) { +Demangler::demangleQualifiers(StringRef &MangledName) { - switch (MangledName.popFront()) { + switch (pop(MangledName)) { // Member qualifiers case 'Q': return std::make_pair(Q_None, true); @@ -2542,7 +2498,7 @@ return std::make_pair(Q_None, false); } -static bool isTagType(StringView S) { +static bool isTagType(StringRef S) { switch (S.front()) { case 'T': // union case 'U': // struct @@ -2553,8 +2509,8 @@ return false; } -static bool isPointerType(StringView S) { - if (S.startsWith("$$Q")) // foo && +static bool isPointerType(StringRef S) { + if (S.startswith("$$Q")) // foo && return true; switch (S.front()) { @@ -2568,22 +2524,22 @@ return false; } -static bool isArrayType(StringView S) { return S[0] == 'Y'; } +static bool isArrayType(StringRef S) { return S[0] == 'Y'; } -static bool isFunctionType(StringView S) { - return S.startsWith("$$A8@@") || S.startsWith("$$A6"); +static bool isFunctionType(StringRef S) { + return S.startswith("$$A8@@") || S.startswith("$$A6"); } // ::= // ::= # pointers, references -Type *Demangler::demangleType(StringView &MangledName, +Type *Demangler::demangleType(StringRef &MangledName, QualifierMangleMode QMM) { Qualifiers Quals = Q_None; bool IsMember = false; if (QMM == QualifierMangleMode::Mangle) { std::tie(Quals, IsMember) = demangleQualifiers(MangledName); } else if (QMM == QualifierMangleMode::Result) { - if (MangledName.consumeFront('?')) + if (MangledName.consume_front("?")) std::tie(Quals, IsMember) = demangleQualifiers(MangledName); } @@ -2598,11 +2554,11 @@ } else if (isArrayType(MangledName)) Ty = demangleArrayType(MangledName); else if (isFunctionType(MangledName)) { - if (MangledName.consumeFront("$$A8@@")) + if (MangledName.consume_front("$$A8@@")) Ty = demangleFunctionType(MangledName, true, false); else { - assert(MangledName.startsWith("$$A6")); - MangledName.consumeFront("$$A6"); + assert(MangledName.startswith("$$A6")); + MangledName.consume_front("$$A6"); Ty = demangleFunctionType(MangledName, false, false); } } else { @@ -2616,25 +2572,25 @@ return Ty; } -ReferenceKind Demangler::demangleReferenceKind(StringView &MangledName) { - if (MangledName.consumeFront('G')) +ReferenceKind Demangler::demangleReferenceKind(StringRef &MangledName) { + if (MangledName.consume_front("G")) return ReferenceKind::LValueRef; - else if (MangledName.consumeFront('H')) + else if (MangledName.consume_front("H")) return ReferenceKind::RValueRef; return ReferenceKind::None; } -void Demangler::demangleThrowSpecification(StringView &MangledName) { - if (MangledName.consumeFront('Z')) +void Demangler::demangleThrowSpecification(StringRef &MangledName) { + if (MangledName.consume_front("Z")) return; Error = true; } -FunctionType *Demangler::demangleFunctionType(StringView &MangledName, +FunctionType *Demangler::demangleFunctionType(StringRef &MangledName, bool HasThisQuals, bool IsFunctionPointer) { - FunctionType *FTy = Arena.alloc(); + FunctionType *FTy = allocate(Arena); FTy->Prim = PrimTy::Function; FTy->IsFunctionPointer = IsFunctionPointer; @@ -2649,7 +2605,7 @@ // ::= // ::= @ # structors (they have no declared return type) - bool IsStructor = MangledName.consumeFront('@'); + bool IsStructor = MangledName.consume_front("@"); if (!IsStructor) FTy->ReturnType = demangleType(MangledName, QualifierMangleMode::Result); @@ -2660,9 +2616,9 @@ return FTy; } -Type *Demangler::demangleFunctionEncoding(StringView &MangledName) { +Type *Demangler::demangleFunctionEncoding(StringRef &MangledName) { FuncClass ExtraFlags = FuncClass::None; - if (MangledName.consumeFront("$$J0")) + if (MangledName.consume_front("$$J0")) ExtraFlags = FuncClass::ExternC; FuncClass FC = demangleFunctionClass(MangledName); @@ -2670,10 +2626,10 @@ FunctionType::ThisAdjustor *Adjustor = nullptr; if (FC & FuncClass::StaticThisAdjust) { - Adjustor = Arena.alloc(); + Adjustor = allocate(Arena); Adjustor->StaticOffset = demangleSigned(MangledName); } else if (FC & FuncClass::VirtualThisAdjust) { - Adjustor = Arena.alloc(); + Adjustor = allocate(Arena); if (FC & FuncClass::VirtualThisAdjustEx) { Adjustor->VBPtrOffset = demangleSigned(MangledName); Adjustor->VBOffsetOffset = demangleSigned(MangledName); @@ -2687,7 +2643,7 @@ // This is an extern "C" function whose full signature hasn't been mangled. // This happens when we need to mangle a local symbol inside of an extern // "C" function. - FTy = Arena.alloc(); + FTy = allocate(Arena); } else { bool HasThisQuals = !(FC & (Global | Static)); FTy = demangleFunctionType(MangledName, HasThisQuals, false); @@ -2699,24 +2655,24 @@ } // Reads a primitive type. -Type *Demangler::demangleBasicType(StringView &MangledName) { - Type *Ty = Arena.alloc(); +Type *Demangler::demangleBasicType(StringRef &MangledName) { + Type *Ty = allocate(Arena); - if (MangledName.consumeFront("$$T")) { + if (MangledName.consume_front("$$T")) { Ty->Prim = PrimTy::Nullptr; return Ty; } - if (MangledName.consumeFront("?")) { + if (MangledName.consume_front("?")) { Ty->Prim = PrimTy::Custom; Ty->Custom = demangleSimpleString(MangledName, false); - if (!MangledName.consumeFront('@')) { + if (!MangledName.consume_front("@")) { Error = true; return nullptr; } return Ty; } - switch (MangledName.popFront()) { + switch (pop(MangledName)) { case 'X': Ty->Prim = PrimTy::Void; break; @@ -2761,7 +2717,7 @@ Error = true; return nullptr; } - switch (MangledName.popFront()) { + switch (pop(MangledName)) { case 'N': Ty->Prim = PrimTy::Bool; break; @@ -2793,10 +2749,10 @@ return Ty; } -UdtType *Demangler::demangleClassType(StringView &MangledName) { - UdtType *UTy = Arena.alloc(); +UdtType *Demangler::demangleClassType(StringRef &MangledName) { + UdtType *UTy = allocate(Arena); - switch (MangledName.popFront()) { + switch (pop(MangledName)) { case 'T': UTy->Prim = PrimTy::Union; break; @@ -2807,7 +2763,7 @@ UTy->Prim = PrimTy::Class; break; case 'W': - if (MangledName.popFront() != '4') { + if (pop(MangledName) != '4') { Error = true; return nullptr; } @@ -2822,11 +2778,11 @@ } static std::pair -demanglePointerCVQualifiers(StringView &MangledName) { - if (MangledName.consumeFront("$$Q")) +demanglePointerCVQualifiers(StringRef &MangledName) { + if (MangledName.consume_front("$$Q")) return std::make_pair(Q_None, PointerAffinity::RValueReference); - switch (MangledName.popFront()) { + switch (pop(MangledName)) { case 'A': return std::make_pair(Q_None, PointerAffinity::Reference); case 'P': @@ -2846,14 +2802,14 @@ // ::= E? // # the E is required for 64-bit non-static pointers -PointerType *Demangler::demanglePointerType(StringView &MangledName) { - PointerType *Pointer = Arena.alloc(); +PointerType *Demangler::demanglePointerType(StringRef &MangledName) { + PointerType *Pointer = allocate(Arena); std::tie(Pointer->Quals, Pointer->Affinity) = demanglePointerCVQualifiers(MangledName); Pointer->Prim = PrimTy::Ptr; - if (MangledName.consumeFront("6")) { + if (MangledName.consume_front("6")) { Pointer->Pointee = demangleFunctionType(MangledName, false, true); return Pointer; } @@ -2866,8 +2822,8 @@ } MemberPointerType * -Demangler::demangleMemberPointerType(StringView &MangledName) { - MemberPointerType *Pointer = Arena.alloc(); +Demangler::demangleMemberPointerType(StringRef &MangledName) { + MemberPointerType *Pointer = allocate(Arena); Pointer->Prim = PrimTy::MemberPtr; PointerAffinity Affinity; @@ -2877,7 +2833,7 @@ Qualifiers ExtQuals = demanglePointerExtQualifiers(MangledName); Pointer->Quals = Qualifiers(Pointer->Quals | ExtQuals); - if (MangledName.consumeFront("8")) { + if (MangledName.consume_front("8")) { Pointer->MemberName = demangleFullyQualifiedSymbolName(MangledName); Pointer->Pointee = demangleFunctionType(MangledName, true, true); } else { @@ -2894,21 +2850,21 @@ return Pointer; } -Qualifiers Demangler::demanglePointerExtQualifiers(StringView &MangledName) { +Qualifiers Demangler::demanglePointerExtQualifiers(StringRef &MangledName) { Qualifiers Quals = Q_None; - if (MangledName.consumeFront('E')) + if (MangledName.consume_front("E")) Quals = Qualifiers(Quals | Q_Pointer64); - if (MangledName.consumeFront('I')) + if (MangledName.consume_front("I")) Quals = Qualifiers(Quals | Q_Restrict); - if (MangledName.consumeFront('F')) + if (MangledName.consume_front("F")) Quals = Qualifiers(Quals | Q_Unaligned); return Quals; } -ArrayType *Demangler::demangleArrayType(StringView &MangledName) { +ArrayType *Demangler::demangleArrayType(StringRef &MangledName) { assert(MangledName.front() == 'Y'); - MangledName.popFront(); + pop(MangledName); uint64_t Rank = 0; bool IsNegative = false; @@ -2918,9 +2874,9 @@ return nullptr; } - ArrayType *ATy = Arena.alloc(); + ArrayType *ATy = allocate(Arena); ATy->Prim = PrimTy::Array; - ATy->Dims = Arena.alloc(); + ATy->Dims = allocate(Arena); ArrayDimension *Dim = ATy->Dims; for (uint64_t I = 0; I < Rank; ++I) { std::tie(Dim->Dim, IsNegative) = demangleNumber(MangledName); @@ -2929,12 +2885,12 @@ return nullptr; } if (I + 1 < Rank) { - Dim->Next = Arena.alloc(); + Dim->Next = allocate(Arena); Dim = Dim->Next; } } - if (MangledName.consumeFront("$$C")) { + if (MangledName.consume_front("$$C")) { bool IsMember = false; std::tie(ATy->Quals, IsMember) = demangleQualifiers(MangledName); if (IsMember) { @@ -2949,25 +2905,25 @@ // Reads a function or a template parameters. FunctionParams -Demangler::demangleFunctionParameterList(StringView &MangledName) { +Demangler::demangleFunctionParameterList(StringRef &MangledName) { // Empty parameter list. - if (MangledName.consumeFront('X')) + if (MangledName.consume_front("X")) return {}; FunctionParams *Head; FunctionParams **Current = &Head; - while (!Error && !MangledName.startsWith('@') && - !MangledName.startsWith('Z')) { + while (!Error && !MangledName.startswith("@") && + !MangledName.startswith("Z")) { - if (startsWithDigit(MangledName)) { + if (startswithDigit(MangledName)) { size_t N = MangledName[0] - '0'; if (N >= Backrefs.FunctionParamCount) { Error = true; return {}; } - MangledName = MangledName.dropFront(); + MangledName = MangledName.drop_front(); - *Current = Arena.alloc(); + *Current = allocate(Arena); (*Current)->Current = Backrefs.FunctionParams[N]->clone(Arena); Current = &(*Current)->Next; continue; @@ -2975,7 +2931,7 @@ size_t OldSize = MangledName.size(); - *Current = Arena.alloc(); + *Current = allocate(Arena); (*Current)->Current = demangleType(MangledName, QualifierMangleMode::Drop); size_t CharsConsumed = OldSize - MangledName.size(); @@ -2996,10 +2952,10 @@ // A non-empty parameter list is terminated by either 'Z' (variadic) parameter // list or '@' (non variadic). Careful not to consume "@Z", as in that case // the following Z could be a throw specifier. - if (MangledName.consumeFront('@')) + if (MangledName.consume_front("@")) return *Head; - if (MangledName.consumeFront('Z')) { + if (MangledName.consume_front("Z")) { Head->IsVariadic = true; return *Head; } @@ -3009,40 +2965,40 @@ } TemplateParams * -Demangler::demangleTemplateParameterList(StringView &MangledName) { +Demangler::demangleTemplateParameterList(StringRef &MangledName) { TemplateParams *Head; TemplateParams **Current = &Head; - while (!Error && !MangledName.startsWith('@')) { + while (!Error && !MangledName.startswith("@")) { // Template parameter lists don't participate in back-referencing. - *Current = Arena.alloc(); + *Current = allocate(Arena); TemplateParams &TP = **Current; // Empty parameter pack. - if (MangledName.consumeFront("$S") || MangledName.consumeFront("$$V") || - MangledName.consumeFront("$$$V")) { + if (MangledName.consume_front("$S") || MangledName.consume_front("$$V") || + MangledName.consume_front("$$$V")) { TP.IsEmptyParameterPack = true; - } else if (MangledName.consumeFront("$$Y")) { + } else if (MangledName.consume_front("$$Y")) { // Template alias TP.IsTemplateTemplate = true; TP.IsAliasTemplate = true; TP.ParamName = demangleFullyQualifiedTypeName(MangledName); - } else if (MangledName.consumeFront("$$B")) { + } else if (MangledName.consume_front("$$B")) { // Array TP.ParamType = demangleType(MangledName, QualifierMangleMode::Drop); - } else if (MangledName.consumeFront("$$C")) { + } else if (MangledName.consume_front("$$C")) { // Type has qualifiers. TP.ParamType = demangleType(MangledName, QualifierMangleMode::Mangle); - } else if (MangledName.startsWith("$1") || MangledName.startsWith("$H") || - MangledName.startsWith("$I") || MangledName.startsWith("$J")) { - MangledName = MangledName.dropFront(); + } else if (MangledName.startswith("$1") || MangledName.startswith("$H") || + MangledName.startswith("$I") || MangledName.startswith("$J")) { + MangledName = MangledName.drop_front(); // 1 - single inheritance // H - multiple inheritance // I - virtual inheritance // J - unspecified inheritance - char InheritanceSpecifier = MangledName.popFront(); + char InheritanceSpecifier = pop(MangledName); // Pointer to member - Symbol *S = MangledName.startsWith('?') ? parse(MangledName) : nullptr; + Symbol *S = MangledName.startswith("?") ? parse(MangledName) : nullptr; switch (InheritanceSpecifier) { case 'J': TP.ThunkOffsets[TP.ThunkOffsetCount++] = demangleSigned(MangledName); @@ -3065,17 +3021,17 @@ TP.ParamType = S->SymbolType; } else TP.NullptrLiteral = true; - } else if (MangledName.startsWith("$E?")) { - MangledName.consumeFront("$E"); + } else if (MangledName.startswith("$E?")) { + MangledName.consume_front("$E"); // Reference to symbol Symbol *S = parse(MangledName); TP.ParamName = S->SymbolName; TP.ParamType = S->SymbolType; TP.ReferenceToSymbol = true; - } else if (MangledName.startsWith("$F") || MangledName.startsWith("$G")) { + } else if (MangledName.startswith("$F") || MangledName.startswith("$G")) { // Data member pointer. - MangledName = MangledName.dropFront(); - char InheritanceSpecifier = MangledName.popFront(); + MangledName = MangledName.drop_front(); + char InheritanceSpecifier = pop(MangledName); switch (InheritanceSpecifier) { case 'G': @@ -3093,7 +3049,7 @@ } TP.DataMemberPointer = true; - } else if (MangledName.consumeFront("$0")) { + } else if (MangledName.consume_front("$0")) { // Integral non-type template parameter bool IsNegative = false; uint64_t Value = 0; @@ -3116,13 +3072,13 @@ // Template parameter lists cannot be variadic, so it can only be terminated // by @. - if (MangledName.consumeFront('@')) + if (MangledName.consume_front("@")) return Head; Error = true; return nullptr; } -void Demangler::output(const Symbol *S, OutputStream &OS) { +void Demangler::output(const Symbol *S, peekable_raw_ostream &OS) { if (S->Category == SymbolCategory::Unknown) { outputName(OS, S->SymbolName, S->SymbolType); return; @@ -3165,18 +3121,16 @@ (int)Backrefs.FunctionParamCount); // Create an output stream so we can render each type. - OutputStream OS = OutputStream::create(nullptr, 0, 1024); + SmallString<64> Buffer; for (size_t I = 0; I < Backrefs.FunctionParamCount; ++I) { - OS.setCurrentPosition(0); + raw_svector_ostream RawOS(Buffer); + peekable_raw_ostream OS(RawOS); Type *T = Backrefs.FunctionParams[I]; Type::outputPre(OS, *T); Type::outputPost(OS, *T); - - std::printf(" [%d] - %.*s\n", (int)I, (int)OS.getCurrentPosition(), - OS.getBuffer()); + llvm::outs() << " [" << I << "] - " << Buffer << "\n"; } - std::free(OS.getBuffer()); if (Backrefs.FunctionParamCount > 0) std::printf("\n"); @@ -3189,23 +3143,24 @@ std::printf("\n"); } -char *llvm::microsoftDemangle(const char *MangledName, char *Buf, size_t *N, +std::string llvm::microsoftDemangle(StringRef MangledName, int *Status, MSDemangleFlags Flags) { Demangler D; - StringView Name{MangledName}; - Symbol *S = D.parse(Name); + Symbol *S = D.parse(MangledName); if (Flags & MSDF_DumpBackrefs) D.dumpBackReferences(); - OutputStream OS = OutputStream::create(Buf, N, 1024); + std::string Buffer; + raw_string_ostream RawOS(Buffer); + peekable_raw_ostream OS(RawOS); if (D.Error) { OS << MangledName; - *Status = llvm::demangle_invalid_mangled_name; + *Status = -1; } else { D.output(S, OS); - *Status = llvm::demangle_success; + *Status = 0; } + OS.flush(); - OS << '\0'; - return OS.getBuffer(); + return Buffer; } Index: llvm/tools/llvm-undname/llvm-undname.cpp =================================================================== --- llvm/tools/llvm-undname/llvm-undname.cpp +++ llvm/tools/llvm-undname/llvm-undname.cpp @@ -1,5 +1,4 @@ -//===-- llvm-undname.cpp - Microsoft ABI name undecorator -//------------------===// +//===-- llvm-undname.cpp - Microsoft ABI name undecorator -----------------===// // // The LLVM Compiler Infrastructure // @@ -14,9 +13,9 @@ //===----------------------------------------------------------------------===// #include "llvm/ADT/StringRef.h" -#include "llvm/Demangle/Demangle.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/InitLLVM.h" +#include "llvm/Support/MicrosoftDemangle.h" #include "llvm/Support/Process.h" #include "llvm/Support/raw_ostream.h" #include @@ -38,15 +37,13 @@ if (DumpBackReferences) Flags = MSDemangleFlags(Flags | MSDF_DumpBackrefs); - char *ResultBuf = - microsoftDemangle(S.c_str(), nullptr, nullptr, &Status, Flags); - if (Status == llvm::demangle_success) { - outs() << ResultBuf << "\n"; + std::string Result = microsoftDemangle(S, &Status, Flags); + if (Status == 0) { + outs() << Result << "\n"; outs().flush(); } else { errs() << "Error: Invalid mangled name\n"; } - std::free(ResultBuf); } int main(int argc, char **argv) {