Index: libcxxabi/trunk/src/cxa_demangle.cpp =================================================================== --- libcxxabi/trunk/src/cxa_demangle.cpp +++ libcxxabi/trunk/src/cxa_demangle.cpp @@ -15,150 +15,27 @@ #include "__cxxabi_config.h" -#include -#include -#include +#include "demangle/Compiler.h" +#include "demangle/StringView.h" +#include "demangle/Utility.h" + #include +#include #include #include #include -#include +#include +#include -#ifdef _MSC_VER -// snprintf is implemented in VS 2015 -#if _MSC_VER < 1900 -#define snprintf _snprintf_s -#endif -#endif - -#ifndef NDEBUG -#if __has_attribute(noinline) && __has_attribute(used) -#define DUMP_METHOD __attribute__((noinline,used)) -#else -#define DUMP_METHOD -#endif -#endif namespace { -class StringView { - const char *First; - const char *Last; - -public: - template - StringView(const char (&Str)[N]) : First(Str), Last(Str + N - 1) {} - StringView(const char *First_, const char *Last_) : First(First_), Last(Last_) {} - StringView() : First(nullptr), Last(nullptr) {} - - StringView substr(size_t From, size_t To) { - if (To >= size()) - To = size() - 1; - if (From >= size()) - From = size() - 1; - return StringView(First + From, First + To); - } - - StringView dropFront(size_t N) const { - if (N >= size()) - N = size() - 1; - return StringView(First + N, Last); - } - - bool startsWith(StringView Str) const { - if (Str.size() > size()) - return false; - return std::equal(Str.begin(), Str.end(), begin()); - } - - const char &operator[](size_t Idx) const { return *(begin() + Idx); } - - const char *begin() const { return First; } - const char *end() const { return Last; } - size_t size() const { return static_cast(Last - First); } - bool empty() const { return First == Last; } -}; - -bool operator==(const StringView &LHS, const StringView &RHS) { - return LHS.size() == RHS.size() && - std::equal(LHS.begin(), LHS.end(), RHS.begin()); -} - -// Stream that AST nodes write their string representation into after the AST -// has been parsed. -class OutputStream { - char *Buffer; - size_t CurrentPosition; - size_t BufferCapacity; - - // Ensure there is at least n more positions in buffer. - void grow(size_t N) { - if (N + CurrentPosition >= BufferCapacity) { - BufferCapacity *= 2; - if (BufferCapacity < N + CurrentPosition) - BufferCapacity = N + CurrentPosition; - Buffer = static_cast(std::realloc(Buffer, BufferCapacity)); - } - } - -public: - OutputStream(char *StartBuf, size_t Size) - : Buffer(StartBuf), CurrentPosition(0), BufferCapacity(Size) {} - OutputStream() = default; - void reset(char *Buffer_, size_t BufferCapacity_) { - CurrentPosition = 0; - Buffer = Buffer_; - BufferCapacity = BufferCapacity_; - } - - /// If a ParameterPackExpansion (or similar type) is encountered, the offset - /// into the pack that we're currently printing. - unsigned CurrentPackIndex = std::numeric_limits::max(); - unsigned CurrentPackMax = std::numeric_limits::max(); - - OutputStream &operator+=(StringView R) { - size_t Size = R.size(); - if (Size == 0) - return *this; - grow(Size); - memmove(Buffer + CurrentPosition, R.begin(), Size); - CurrentPosition += Size; - return *this; - } - - OutputStream &operator+=(char C) { - grow(1); - Buffer[CurrentPosition++] = C; - return *this; - } - - size_t getCurrentPosition() const { return CurrentPosition; } - void setCurrentPosition(size_t NewPos) { CurrentPosition = NewPos; } - - char back() const { - return CurrentPosition ? Buffer[CurrentPosition - 1] : '\0'; - } - - bool empty() const { return CurrentPosition == 0; } - - char *getBuffer() { return Buffer; } - char *getBufferEnd() { return Buffer + CurrentPosition - 1; } - size_t getBufferCapacity() { return BufferCapacity; } -}; - -template -class SwapAndRestore { - T &Restore; - T OriginalValue; -public: - SwapAndRestore(T& Restore_, T NewVal) - : Restore(Restore_), OriginalValue(Restore) { - Restore = std::move(NewVal); - } - ~SwapAndRestore() { Restore = std::move(OriginalValue); } - - SwapAndRestore(const SwapAndRestore &) = delete; - SwapAndRestore &operator=(const SwapAndRestore &) = delete; +enum : int { + demangle_unknown_error = -4, + demangle_invalid_args = -3, + demangle_invalid_mangled_name = -2, + demangle_memory_alloc_failure = -1, + demangle_success = 0, }; // Base class of all AST nodes. The AST is built by the parser, then is @@ -272,7 +149,7 @@ // Print the "right". This distinction is necessary to represent C++ types // that appear on the RHS of their subtype, such as arrays or functions. // Since most types don't have such a component, provide a default - // implemenation. + // implementation. virtual void printRight(OutputStream &) const {} virtual StringView getBaseName() const { return StringView(); } @@ -748,7 +625,7 @@ bool hasRHSComponentSlow(OutputStream &) const override { return true; } bool hasFunctionSlow(OutputStream &) const override { return true; } - // Handle C++'s ... quirky decl grammer by using the left & right + // Handle C++'s ... quirky decl grammar by using the left & right // distinction. Consider: // int (*f(float))(char) {} // f is a function that takes a float and returns a pointer to a function @@ -1057,7 +934,7 @@ } }; -/// A variadic template argument. This node represents an occurance of +/// A variadic template argument. This node represents an occurrence of /// JE in some . It isn't itself unexpanded, unless /// one of it's Elements is. The parser inserts a ParameterPack into the /// TemplateParams table if the this pack belongs to apply to an @@ -2053,7 +1930,7 @@ const char *Last; // Name stack, this is used by the parser to hold temporary names that were - // parsed. The parser colapses multiple names into new nodes to construct + // parsed. The parser collapses multiple names into new nodes to construct // the AST. Once the parser is finished, names.size() == 1. PODSmallVector Names; @@ -2927,7 +2804,7 @@ // // extension ::= srN [] * E // ::= [gs] # x or (with "gs") ::x -// ::= [gs] sr + E +// ::= [gs] sr + E // # A::x, N::y, A::z; "gs" means leading "::" // ::= sr # T::x / decltype(p)::x // extension ::= sr @@ -2977,7 +2854,7 @@ return SoFar; } - // [gs] sr + E + // [gs] sr + E if (std::isdigit(look())) { do { Node *Qual = parseSimpleId(); @@ -5058,33 +4935,25 @@ } // unnamed namespace -enum { - unknown_error = -4, - invalid_args = -3, - invalid_mangled_name = -2, - memory_alloc_failure = -1, - success = 0, -}; - namespace __cxxabiv1 { extern "C" _LIBCXXABI_FUNC_VIS char * __cxa_demangle(const char *MangledName, char *Buf, size_t *N, int *Status) { if (MangledName == nullptr || (Buf != nullptr && N == nullptr)) { if (Status) - *Status = invalid_args; + *Status = demangle_invalid_args; return nullptr; } - int InternalStatus = success; + int InternalStatus = demangle_success; Db Parser(MangledName, MangledName + std::strlen(MangledName)); OutputStream S; Node *AST = Parser.parse(); if (AST == nullptr) - InternalStatus = invalid_mangled_name; + InternalStatus = demangle_invalid_mangled_name; else if (initializeOutputStream(Buf, N, S, 1024)) - InternalStatus = memory_alloc_failure; + InternalStatus = demangle_memory_alloc_failure; else { assert(Parser.ForwardTemplateRefs.empty()); AST->print(S); @@ -5096,6 +4965,6 @@ if (Status) *Status = InternalStatus; - return InternalStatus == success ? Buf : nullptr; + return InternalStatus == demangle_success ? Buf : nullptr; } } // __cxxabiv1 Index: libcxxabi/trunk/src/demangle/Compiler.h =================================================================== --- libcxxabi/trunk/src/demangle/Compiler.h +++ libcxxabi/trunk/src/demangle/Compiler.h @@ -0,0 +1,34 @@ +//===--- Compiler.h ---------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +// This file is contains a subset of macros copied from +// llvm/lib/Demangle/Compiler.h. +//===----------------------------------------------------------------------===// + +#ifndef LIBCXX_DEMANGLE_COMPILER_H +#define LIBCXX_DEMANGLE_COMPILER_H + +#ifdef _MSC_VER +// snprintf is implemented in VS 2015 +#if _MSC_VER < 1900 +#define snprintf _snprintf_s +#endif +#endif + +#ifndef __has_attribute +#define __has_attribute(x) 0 +#endif + +#ifndef NDEBUG +#if __has_attribute(noinline) && __has_attribute(used) +#define DUMP_METHOD __attribute__((noinline, used)) +#else +#define DUMP_METHOD +#endif +#endif + +#endif Index: libcxxabi/trunk/src/demangle/StringView.h =================================================================== --- libcxxabi/trunk/src/demangle/StringView.h +++ libcxxabi/trunk/src/demangle/StringView.h @@ -0,0 +1,98 @@ +//===--- StringView.h -------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +// +// This file is copied from llvm/lib/Demangle/StringView.h. +//===----------------------------------------------------------------------===// + +#ifndef LIBCXX_DEMANGLE_STRINGVIEW_H +#define LIBCXX_DEMANGLE_STRINGVIEW_H + +#include +#include +#include + +namespace { +class StringView { + const char *First; + const char *Last; + +public: + template + StringView(const char (&Str)[N]) : First(Str), Last(Str + N - 1) {} + StringView(const char *First_, const char *Last_) + : First(First_), Last(Last_) {} + StringView(const char *First_, size_t Len) + : First(First_), Last(First_ + Len) {} + StringView(const char *Str) : First(Str), Last(Str + std::strlen(Str)) {} + StringView() : First(nullptr), Last(nullptr) {} + + StringView substr(size_t From) const { + return StringView(begin() + From, size() - From); + } + + 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 { + if (N >= size()) + N = size() - 1; + return StringView(First + N, Last); + } + + char front() const { + assert(!empty()); + return *begin(); + } + + char popFront() { + assert(!empty()); + return *First++; + } + + bool consumeFront(char C) { + if (!startsWith(C)) + return false; + *this = dropFront(1); + return true; + } + + bool consumeFront(StringView S) { + if (!startsWith(S)) + return false; + *this = dropFront(S.size()); + return true; + } + + bool startsWith(char C) const { return !empty() && *begin() == C; } + + bool startsWith(StringView Str) const { + if (Str.size() > size()) + return false; + return std::equal(Str.begin(), Str.end(), begin()); + } + + const char &operator[](size_t Idx) const { return *(begin() + Idx); } + + const char *begin() const { return First; } + const char *end() const { return Last; } + size_t size() const { return static_cast(Last - First); } + bool empty() const { return First == Last; } +}; + +inline bool operator==(const StringView &LHS, const StringView &RHS) { + return LHS.size() == RHS.size() && + std::equal(LHS.begin(), LHS.end(), RHS.begin()); +} +} // namespace + +#endif Index: libcxxabi/trunk/src/demangle/Utility.h =================================================================== --- libcxxabi/trunk/src/demangle/Utility.h +++ libcxxabi/trunk/src/demangle/Utility.h @@ -0,0 +1,187 @@ +//===--- Utility.h ----------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +// +// This file is copied from llvm/lib/Demangle/Utility.h. +//===----------------------------------------------------------------------===// + +#ifndef LIBCXX_DEMANGLE_UTILITY_H +#define LIBCXX_DEMANGLE_UTILITY_H + +#include "StringView.h" + +#include +#include +#include +#include +#include + +namespace { +// Stream that AST nodes write their string representation into after the AST +// has been parsed. +class OutputStream { + char *Buffer; + size_t CurrentPosition; + size_t BufferCapacity; + + // Ensure there is at least n more positions in buffer. + void grow(size_t N) { + if (N + CurrentPosition >= BufferCapacity) { + BufferCapacity *= 2; + if (BufferCapacity < N + CurrentPosition) + BufferCapacity = N + CurrentPosition; + Buffer = static_cast(std::realloc(Buffer, BufferCapacity)); + } + } + + void writeUnsigned(uint64_t N, bool isNeg = false) { + // Handle special case... + if (N == 0) { + *this << '0'; + return; + } + + char Temp[21]; + char *TempPtr = std::end(Temp); + + while (N) { + *--TempPtr = '0' + char(N % 10); + N /= 10; + } + + // Add negative sign... + if (isNeg) + *--TempPtr = '-'; + this->operator<<(StringView(TempPtr, std::end(Temp))); + } + +public: + OutputStream(char *StartBuf, size_t Size) + : Buffer(StartBuf), CurrentPosition(0), BufferCapacity(Size) {} + OutputStream() = default; + void reset(char *Buffer_, size_t BufferCapacity_) { + CurrentPosition = 0; + Buffer = Buffer_; + BufferCapacity = BufferCapacity_; + } + + /// Create an OutputStream from a buffer and a size. If either of these are + /// null a buffer is allocated. + static OutputStream create(char *StartBuf, size_t *Size, size_t AllocSize) { + OutputStream Result; + + if (!StartBuf || !Size) { + StartBuf = static_cast(std::malloc(AllocSize)); + Size = &AllocSize; + } + + Result.reset(StartBuf, *Size); + return Result; + } + + /// If a ParameterPackExpansion (or similar type) is encountered, the offset + /// into the pack that we're currently printing. + unsigned CurrentPackIndex = std::numeric_limits::max(); + unsigned CurrentPackMax = std::numeric_limits::max(); + + OutputStream &operator+=(StringView R) { + size_t Size = R.size(); + if (Size == 0) + return *this; + grow(Size); + std::memmove(Buffer + CurrentPosition, R.begin(), Size); + CurrentPosition += Size; + return *this; + } + + OutputStream &operator+=(char C) { + grow(1); + Buffer[CurrentPosition++] = C; + return *this; + } + + OutputStream &operator<<(StringView R) { return (*this += R); } + + OutputStream &operator<<(char C) { return (*this += C); } + + OutputStream &operator<<(long long N) { + if (N < 0) + writeUnsigned(static_cast(-N), true); + else + writeUnsigned(static_cast(N)); + return *this; + } + + OutputStream &operator<<(unsigned long long N) { + writeUnsigned(N, false); + return *this; + } + + OutputStream &operator<<(long N) { + return this->operator<<(static_cast(N)); + } + + OutputStream &operator<<(unsigned long N) { + return this->operator<<(static_cast(N)); + } + + OutputStream &operator<<(int N) { + return this->operator<<(static_cast(N)); + } + + OutputStream &operator<<(unsigned int N) { + return this->operator<<(static_cast(N)); + } + + size_t getCurrentPosition() const { return CurrentPosition; } + void setCurrentPosition(size_t NewPos) { CurrentPosition = NewPos; } + + char back() const { + return CurrentPosition ? Buffer[CurrentPosition - 1] : '\0'; + } + + bool empty() const { return CurrentPosition == 0; } + + char *getBuffer() { return Buffer; } + char *getBufferEnd() { return Buffer + CurrentPosition - 1; } + size_t getBufferCapacity() { return BufferCapacity; } +}; + +template class SwapAndRestore { + T &Restore; + T OriginalValue; + bool ShouldRestore = true; + +public: + SwapAndRestore(T &Restore_) : SwapAndRestore(Restore_, Restore_) {} + + SwapAndRestore(T &Restore_, T NewVal) + : Restore(Restore_), OriginalValue(Restore) { + Restore = std::move(NewVal); + } + ~SwapAndRestore() { + if (ShouldRestore) + Restore = std::move(OriginalValue); + } + + void shouldRestore(bool ShouldRestore_) { ShouldRestore = ShouldRestore_; } + + void restoreNow(bool Force) { + if (!Force && !ShouldRestore) + return; + + Restore = std::move(OriginalValue); + ShouldRestore = false; + } + + SwapAndRestore(const SwapAndRestore &) = delete; + SwapAndRestore &operator=(const SwapAndRestore &) = delete; +}; + +} // namespace + +#endif