diff options
author | Matt Davis <Matthew.Davis@sony.com> | 2019-02-27 16:29:50 +0000 |
---|---|---|
committer | Matt Davis <Matthew.Davis@sony.com> | 2019-02-27 16:29:50 +0000 |
commit | 5cd5f8f2563395f8767f94604eb4c4bea8dcbea0 (patch) | |
tree | 45264447b48ec5afdcbab0c363dee3cabcf78876 /llvm/tools/llvm-cxxfilt | |
parent | a54fe15610d6d592590659186731daf1063dc153 (diff) | |
download | bcm5719-llvm-5cd5f8f2563395f8767f94604eb4c4bea8dcbea0.tar.gz bcm5719-llvm-5cd5f8f2563395f8767f94604eb4c4bea8dcbea0.zip |
[llvm-cxxfilt] Split and demangle stdin input on certain non-alphanumerics.
Summary:
This patch attempts to replicate GNU c++-filt behavior when splitting stdin input for demangling.
Previously, cxx-filt would split input only on spaces. Each delimited item is then demangled.
From what I have tested, GNU c++filt also splits input on any character that does not make
up the mangled name (notably commas, but also a large set of non-alphanumeric characters).
This patch splits stdin input on any character that does not belong to the Itanium mangling
format (since Itanium is currently the only supported format in llvm-cxxfilt).
This is an update to PR39990
Reviewers: jhenderson, tejohnson, compnerd
Reviewed By: compnerd
Subscribers: erik.pilkington, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D58416
llvm-svn: 354998
Diffstat (limited to 'llvm/tools/llvm-cxxfilt')
-rw-r--r-- | llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp | 45 |
1 files changed, 38 insertions, 7 deletions
diff --git a/llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp b/llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp index e0850444d6f..a082dc7cfe8 100644 --- a/llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp +++ b/llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp @@ -78,19 +78,50 @@ static std::string demangle(llvm::raw_ostream &OS, const std::string &Mangled) { return Result; } +// Split 'Source' on any character that fails to pass 'IsLegalChar'. The +// returned vector consists of pairs where 'first' is the delimited word, and +// 'second' are the delimiters following that word. +static void SplitStringDelims( + StringRef Source, + SmallVectorImpl<std::pair<StringRef, StringRef>> &OutFragments, + function_ref<bool(char)> IsLegalChar) { + // The beginning of the input string. + const auto Head = Source.begin(); + + // Obtain any leading delimiters. + auto Start = std::find_if(Head, Source.end(), IsLegalChar); + if (Start != Head) + OutFragments.push_back({"", Source.slice(0, Start - Head)}); + + // Capture each word and the delimiters following that word. + while (Start != Source.end()) { + Start = std::find_if(Start, Source.end(), IsLegalChar); + auto End = std::find_if_not(Start, Source.end(), IsLegalChar); + auto DEnd = std::find_if(End, Source.end(), IsLegalChar); + OutFragments.push_back({Source.slice(Start - Head, End - Head), + Source.slice(End - Head, DEnd - Head)}); + Start = DEnd; + } +} + +// This returns true if 'C' is a character that can show up in an +// Itanium-mangled string. +static bool IsLegalItaniumChar(char C) { + // Itanium CXX ABI [External Names]p5.1.1: + // '$' and '.' in mangled names are reserved for private implementations. + return isalnum(C) || C == '.' || C == '$' || C == '_'; +} + // If 'Split' is true, then 'Mangled' is broken into individual words and each // word is demangled. Otherwise, the entire string is treated as a single // mangled item. The result is output to 'OS'. static void demangleLine(llvm::raw_ostream &OS, StringRef Mangled, bool Split) { std::string Result; if (Split) { - SmallVector<StringRef, 16> Words; - SplitString(Mangled, Words); - for (auto Word : Words) - Result += demangle(OS, Word) + ' '; - // Remove the trailing space character. - if (Result.back() == ' ') - Result.pop_back(); + SmallVector<std::pair<StringRef, StringRef>, 16> Words; + SplitStringDelims(Mangled, Words, IsLegalItaniumChar); + for (const auto &Word : Words) + Result += demangle(OS, Word.first) + Word.second.str(); } else Result = demangle(OS, Mangled); OS << Result << '\n'; |