Index: llvm/trunk/lib/Demangle/CMakeLists.txt =================================================================== --- llvm/trunk/lib/Demangle/CMakeLists.txt +++ llvm/trunk/lib/Demangle/CMakeLists.txt @@ -1,3 +1,6 @@ add_llvm_library(LLVMDemangle ItaniumDemangle.cpp + + ADDITIONAL_HEADER_DIRS + "${LLVM_MAIN_INCLUDE_DIR}/llvm/Demangle" ) Index: llvm/trunk/lib/Demangle/Compiler.h =================================================================== --- llvm/trunk/lib/Demangle/Compiler.h +++ llvm/trunk/lib/Demangle/Compiler.h @@ -0,0 +1,93 @@ +//===--- 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 contains a variety of feature test macros copied from +// include/llvm/Support/Compiler.h so that LLVMDemangle does not need to take +// a dependency on LLVMSupport. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEMANGLE_COMPILER_H +#define LLVM_DEMANGLE_COMPILER_H + +#ifdef _MSC_VER +// snprintf is implemented in VS 2015 +#if _MSC_VER < 1900 +#define snprintf _snprintf_s +#endif +#endif + +#ifndef __has_feature +#define __has_feature(x) 0 +#endif + +#ifndef __has_cpp_attribute +#define __has_cpp_attribute(x) 0 +#endif + +#ifndef __has_attribute +#define __has_attribute(x) 0 +#endif + +#ifndef __has_builtin +#define __has_builtin(x) 0 +#endif + +#ifndef LLVM_GNUC_PREREQ +#if defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) +#define LLVM_GNUC_PREREQ(maj, min, patch) \ + ((__GNUC__ << 20) + (__GNUC_MINOR__ << 10) + __GNUC_PATCHLEVEL__ >= \ + ((maj) << 20) + ((min) << 10) + (patch)) +#elif defined(__GNUC__) && defined(__GNUC_MINOR__) +#define LLVM_GNUC_PREREQ(maj, min, patch) \ + ((__GNUC__ << 20) + (__GNUC_MINOR__ << 10) >= ((maj) << 20) + ((min) << 10)) +#else +#define LLVM_GNUC_PREREQ(maj, min, patch) 0 +#endif +#endif + +#if __has_attribute(used) || LLVM_GNUC_PREREQ(3, 1, 0) +#define LLVM_ATTRIBUTE_USED __attribute__((__used__)) +#else +#define LLVM_ATTRIBUTE_USED +#endif + +#if __has_builtin(__builtin_unreachable) || LLVM_GNUC_PREREQ(4, 5, 0) +#define LLVM_BUILTIN_UNREACHABLE __builtin_unreachable() +#elif defined(_MSC_VER) +#define LLVM_BUILTIN_UNREACHABLE __assume(false) +#endif + +#if __has_attribute(noinline) || LLVM_GNUC_PREREQ(3, 4, 0) +#define LLVM_ATTRIBUTE_NOINLINE __attribute__((noinline)) +#elif defined(_MSC_VER) +#define LLVM_ATTRIBUTE_NOINLINE __declspec(noinline) +#else +#define LLVM_ATTRIBUTE_NOINLINE +#endif + +#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) +#define LLVM_DUMP_METHOD LLVM_ATTRIBUTE_NOINLINE LLVM_ATTRIBUTE_USED +#else +#define LLVM_DUMP_METHOD LLVM_ATTRIBUTE_NOINLINE +#endif + +#if __cplusplus > 201402L && __has_cpp_attribute(fallthrough) +#define LLVM_FALLTHROUGH [[fallthrough]] +#elif __has_cpp_attribute(gnu::fallthrough) +#define LLVM_FALLTHROUGH [[gnu::fallthrough]] +#elif !__cplusplus +// Workaround for llvm.org/PR23435, since clang 3.6 and below emit a spurious +// error when __has_cpp_attribute is given a scoped attribute in C mode. +#define LLVM_FALLTHROUGH +#elif __has_cpp_attribute(clang::fallthrough) +#define LLVM_FALLTHROUGH [[clang::fallthrough]] +#else +#define LLVM_FALLTHROUGH +#endif + +#endif Index: llvm/trunk/lib/Demangle/ItaniumDemangle.cpp =================================================================== --- llvm/trunk/lib/Demangle/ItaniumDemangle.cpp +++ llvm/trunk/lib/Demangle/ItaniumDemangle.cpp @@ -11,9 +11,11 @@ // file does not yet support: // - C++ modules TS +#include "Compiler.h" +#include "StringView.h" +#include "Utility.h" #include "llvm/Demangle/Demangle.h" -#include #include #include #include @@ -22,204 +24,9 @@ #include #include -#ifdef _MSC_VER -// snprintf is implemented in VS 2015 -#if _MSC_VER < 1900 -#define snprintf _snprintf_s -#endif -#endif - -// A variety of feature test macros copied from include/llvm/Support/Compiler.h -#ifndef __has_feature -#define __has_feature(x) 0 -#endif - -#ifndef __has_cpp_attribute -#define __has_cpp_attribute(x) 0 -#endif - -#ifndef __has_attribute -#define __has_attribute(x) 0 -#endif - -#ifndef __has_builtin -#define __has_builtin(x) 0 -#endif - -#ifndef LLVM_GNUC_PREREQ -#if defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) -#define LLVM_GNUC_PREREQ(maj, min, patch) \ - ((__GNUC__ << 20) + (__GNUC_MINOR__ << 10) + __GNUC_PATCHLEVEL__ >= \ - ((maj) << 20) + ((min) << 10) + (patch)) -#elif defined(__GNUC__) && defined(__GNUC_MINOR__) -#define LLVM_GNUC_PREREQ(maj, min, patch) \ - ((__GNUC__ << 20) + (__GNUC_MINOR__ << 10) >= ((maj) << 20) + ((min) << 10)) -#else -#define LLVM_GNUC_PREREQ(maj, min, patch) 0 -#endif -#endif - -#if __has_attribute(used) || LLVM_GNUC_PREREQ(3, 1, 0) -#define LLVM_ATTRIBUTE_USED __attribute__((__used__)) -#else -#define LLVM_ATTRIBUTE_USED -#endif - -#if __has_builtin(__builtin_unreachable) || LLVM_GNUC_PREREQ(4, 5, 0) -#define LLVM_BUILTIN_UNREACHABLE __builtin_unreachable() -#elif defined(_MSC_VER) -#define LLVM_BUILTIN_UNREACHABLE __assume(false) -#endif - -#if __has_attribute(noinline) || LLVM_GNUC_PREREQ(3, 4, 0) -#define LLVM_ATTRIBUTE_NOINLINE __attribute__((noinline)) -#elif defined(_MSC_VER) -#define LLVM_ATTRIBUTE_NOINLINE __declspec(noinline) -#else -#define LLVM_ATTRIBUTE_NOINLINE -#endif - -#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) -#define LLVM_DUMP_METHOD LLVM_ATTRIBUTE_NOINLINE LLVM_ATTRIBUTE_USED -#else -#define LLVM_DUMP_METHOD LLVM_ATTRIBUTE_NOINLINE -#endif - -#if __cplusplus > 201402L && __has_cpp_attribute(fallthrough) -#define LLVM_FALLTHROUGH [[fallthrough]] -#elif __has_cpp_attribute(gnu::fallthrough) -#define LLVM_FALLTHROUGH [[gnu::fallthrough]] -#elif !__cplusplus -// Workaround for llvm.org/PR23435, since clang 3.6 and below emit a spurious -// error when __has_cpp_attribute is given a scoped attribute in C mode. -#define LLVM_FALLTHROUGH -#elif __has_cpp_attribute(clang::fallthrough) -#define LLVM_FALLTHROUGH [[clang::fallthrough]] -#else -#define LLVM_FALLTHROUGH -#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; -}; // Base class of all AST nodes. The AST is built by the parser, then is // traversed by the printLeft/Right functions to produce a demangled string. @@ -2987,7 +2794,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 @@ -3037,7 +2844,7 @@ return SoFar; } - // [gs] sr + E + // [gs] sr + E if (std::isdigit(look())) { do { Node *Qual = parseSimpleId(); Index: llvm/trunk/lib/Demangle/StringView.h =================================================================== --- llvm/trunk/lib/Demangle/StringView.h +++ llvm/trunk/lib/Demangle/StringView.h @@ -0,0 +1,62 @@ +//===--- 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 contains a limited version of LLVM's StringView class. It is +// copied here so that LLVMDemangle need not take a dependency on LLVMSupport. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEMANGLE_STRINGVIEW_H +#define LLVM_DEMANGLE_STRINGVIEW_H + +#include + +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; } +}; + +inline bool operator==(const StringView &LHS, const StringView &RHS) { + return LHS.size() == RHS.size() && + std::equal(LHS.begin(), LHS.end(), RHS.begin()); +} + +#endif Index: llvm/trunk/lib/Demangle/Utility.h =================================================================== --- llvm/trunk/lib/Demangle/Utility.h +++ llvm/trunk/lib/Demangle/Utility.h @@ -0,0 +1,94 @@ +//===--- 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 contains several utility classes used by the demangle library. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEMANGLE_UTILITY_H +#define LLVM_DEMANGLE_UTILITY_H + +#include + +// 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); + std::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; +}; + +#endif