]> granicus.if.org Git - llvm/commitdiff
[llvm-cxxfilt] Re-enable split and demangle stdin input on certain non-alphanumerics.
authorMatt Davis <Matthew.Davis@sony.com>
Wed, 27 Feb 2019 21:39:11 +0000 (21:39 +0000)
committerMatt Davis <Matthew.Davis@sony.com>
Wed, 27 Feb 2019 21:39:11 +0000 (21:39 +0000)
This restores the patch that splits demangled stdin input on
non-alphanumerics.  I had reverted this patch earlier because it broke
Windows build-bots.  I have updated the test so that it passes on
Windows.

I was running the test from powershell and never saw the issue until I
switched to the mingw shell.

This reverts commit 628ab5c6820bdf3bb5a8e494b0fd9e7312ce7150.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@355031 91177308-0d34-0410-b5e6-96231b3b80d8

test/tools/llvm-cxxfilt/delimiters.test [new file with mode: 0644]
tools/llvm-cxxfilt/llvm-cxxfilt.cpp

diff --git a/test/tools/llvm-cxxfilt/delimiters.test b/test/tools/llvm-cxxfilt/delimiters.test
new file mode 100644 (file)
index 0000000..e70cc30
--- /dev/null
@@ -0,0 +1,63 @@
+RUN: echo ',,_Z3Foo!' \
+RUN:      '_Z3Foo"'   \
+RUN:      '_Z3Foo#'   \
+RUN:      '_Z3Foo%'   \
+RUN:      '_Z3Foo&'   \
+RUN:      "\"_Z3Foo'\"" \
+RUN:      '_Z3Foo('   \
+RUN:      '_Z3Foo)'   \
+RUN:      '_Z3Foo*'   \
+RUN:      '_Z3Foo+'   \
+RUN:      '_Z3Foo,'   \
+RUN:      '_Z3Foo-'   \
+RUN:      '_Z3Foo/'   \
+RUN:      '_Z3Foo:'   \
+RUN:      '_Z3Foo;'   \
+RUN:      '_Z3Foo<'   \
+RUN:      '_Z3Foo='   \
+RUN:      '_Z3Foo>'   \
+RUN:      '_Z3Foo?'   \
+RUN:      '_Z3Foo@'   \
+RUN:      '_Z3Foo['   \
+RUN:      '_Z3Foo\'   \
+RUN:      '_Z3Foo]'   \
+RUN:      '_Z3Foo^'   \
+RUN:      '_Z3Foo`'   \
+RUN:      "\"_Z3Foo{\"" \
+RUN:      '_Z3Foo|'   \
+RUN:      '_Z3Foo}'   \
+RUN:      '_Z3Foo~,,' \
+RUN:      '_Z3Foo,,_Z3Bar::_Z3Baz  _Z3Foo,_Z3Bar:_Z3Baz' \
+RUN:      '_Z3Foo$ ._Z3Foo' | llvm-cxxfilt | FileCheck %s
+
+CHECK: ,,Foo!
+CHECK: Foo"
+CHECK: Foo#
+CHECK: Foo%
+CHECK: Foo&
+CHECK: Foo'
+CHECK: Foo(
+CHECK: Foo)
+CHECK: Foo*
+CHECK: Foo+
+CHECK: Foo,
+CHECK: Foo-
+CHECK: Foo/
+CHECK: Foo:
+CHECK: Foo;
+CHECK: Foo<
+CHECK: Foo=
+CHECK: Foo>
+CHECK: Foo?
+CHECK: Foo@
+CHECK: Foo[
+CHECK: Foo\
+CHECK: Foo]
+CHECK: Foo^
+CHECK: Foo`
+CHECK: Foo{
+CHECK: Foo|
+CHECK: Foo}
+CHECK: Foo~,,
+CHECK: Foo,,Bar::Baz  Foo,Bar:Baz
+CHECK: _Z3Foo$ ._Z3Foo
index e0850444d6f444a6c5ec9af362a54d9d4ca1a910..a082dc7cfe85122f143e8b9d363327a93703d1fb 100644 (file)
@@ -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';