This revision was automatically updated to reflect the committed changes.
Closed by commit rL346233: CPlusPlusLanguage: Use new demangler API to 
implement type substitution (authored by labath, committed by ).
Herald added a subscriber: llvm-commits.

Repository:
  rL LLVM

https://reviews.llvm.org/D54074

Files:
  lldb/trunk/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
  lldb/trunk/unittests/Language/CPlusPlus/CPlusPlusLanguageTest.cpp

Index: lldb/trunk/unittests/Language/CPlusPlus/CPlusPlusLanguageTest.cpp
===================================================================
--- lldb/trunk/unittests/Language/CPlusPlus/CPlusPlusLanguageTest.cpp
+++ lldb/trunk/unittests/Language/CPlusPlus/CPlusPlusLanguageTest.cpp
@@ -191,4 +191,5 @@
   EXPECT_THAT(FindAlternate("_ZN1A1fEx"), Contains("_ZN1A1fEl"));
   EXPECT_THAT(FindAlternate("_ZN1A1fEy"), Contains("_ZN1A1fEm"));
   EXPECT_THAT(FindAlternate("_ZN1A1fEai"), Contains("_ZN1A1fEci"));
+  EXPECT_THAT(FindAlternate("_bogus"), IsEmpty());
 }
Index: lldb/trunk/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
===================================================================
--- lldb/trunk/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
+++ lldb/trunk/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
@@ -21,7 +21,7 @@
 
 // Other libraries and framework includes
 #include "llvm/ADT/StringRef.h"
-#include "llvm/Demangle/Demangle.h"
+#include "llvm/Demangle/ItaniumDemangle.h"
 
 // Project includes
 #include "lldb/Core/PluginManager.h"
@@ -279,72 +279,89 @@
   return false;
 }
 
-/// Given a mangled function `mangled`, replace all the primitive function type
-/// arguments of `search` with type `replace`.
-static ConstString SubsPrimitiveParmItanium(llvm::StringRef mangled,
-                                            llvm::StringRef search,
-                                            llvm::StringRef replace) {
-  class PrimitiveParmSubs {
-    llvm::StringRef mangled;
-    llvm::StringRef search;
-    llvm::StringRef replace;
-    ptrdiff_t read_pos;
-    std::string output;
-    std::back_insert_iterator<std::string> writer;
+namespace {
+class NodeAllocator {
+  llvm::BumpPtrAllocator Alloc;
+
+public:
+  void reset() { Alloc.Reset(); }
+
+  template <typename T, typename... Args> T *makeNode(Args &&... args) {
+    return new (Alloc.Allocate(sizeof(T), alignof(T)))
+        T(std::forward<Args>(args)...);
+  }
 
-  public:
-    PrimitiveParmSubs(llvm::StringRef m, llvm::StringRef s, llvm::StringRef r)
-        : mangled(m), search(s), replace(r), read_pos(0),
-          writer(std::back_inserter(output)) {}
-
-    void Substitute(llvm::StringRef tail) {
-      assert(tail.data() >= mangled.data() &&
-             tail.data() < mangled.data() + mangled.size() &&
-             "tail must point into range of mangled");
-
-      if (tail.startswith(search)) {
-        auto reader = mangled.begin() + read_pos;
-        ptrdiff_t read_len = tail.data() - (mangled.data() + read_pos);
-
-        // First write the unmatched part of the original. Then write the
-        // replacement string. Finally skip the search string in the original.
-        writer = std::copy(reader, reader + read_len, writer);
-        writer = std::copy(replace.begin(), replace.end(), writer);
-        read_pos += read_len + search.size();
-      }
-    }
+  void *allocateNodeArray(size_t sz) {
+    return Alloc.Allocate(sizeof(llvm::itanium_demangle::Node *) * sz,
+                          alignof(llvm::itanium_demangle::Node *));
+  }
+};
 
-    ConstString Finalize() {
-      // If we did a substitution, write the remaining part of the original.
-      if (read_pos > 0) {
-        writer = std::copy(mangled.begin() + read_pos, mangled.end(), writer);
-        read_pos = mangled.size();
-      }
+/// Given a mangled function `Mangled`, replace all the primitive function type
+/// arguments of `Search` with type `Replace`.
+class TypeSubstitutor
+    : public llvm::itanium_demangle::AbstractManglingParser<TypeSubstitutor,
+                                                            NodeAllocator> {
+  /// Input character until which we have constructed the respective output
+  /// already
+  const char *Written;
+
+  llvm::StringRef Search;
+  llvm::StringRef Replace;
+  llvm::SmallString<128> Result;
+
+  /// Whether we have performed any substitutions.
+  bool Substituted;
+
+  void reset(llvm::StringRef Mangled, llvm::StringRef Search,
+             llvm::StringRef Replace) {
+    AbstractManglingParser::reset(Mangled.begin(), Mangled.end());
+    Written = Mangled.begin();
+    this->Search = Search;
+    this->Replace = Replace;
+    Result.clear();
+    Substituted = false;
+  }
 
-      return ConstString(output);
-    }
+  void appendUnchangedInput() {
+    Result += llvm::StringRef(Written, First - Written);
+    Written = First;
+  }
+
+public:
+  TypeSubstitutor() : AbstractManglingParser(nullptr, nullptr) {}
 
-    static void Callback(void *context, const char *match) {
-      ((PrimitiveParmSubs *)context)->Substitute(llvm::StringRef(match));
+  ConstString substitute(llvm::StringRef Mangled, llvm::StringRef From,
+                         llvm::StringRef To) {
+    Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE);
+
+    reset(Mangled, From, To);
+    if (parse() == nullptr) {
+      LLDB_LOG(log, "Failed to substitute mangling in {0}", Mangled);
+      return ConstString();
     }
-  };
+    if (!Substituted)
+      return ConstString();
 
-  // The demangler will call back for each instance of a primitive type,
-  // allowing us to perform substitution
-  PrimitiveParmSubs parmSubs(mangled, search, replace);
-  assert(mangled.data()[mangled.size()] == '\0' && "Expect C-String");
-  bool err = llvm::itaniumFindTypesInMangledName(mangled.data(), &parmSubs,
-                                                 PrimitiveParmSubs::Callback);
-  ConstString result = parmSubs.Finalize();
-
-  if (Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)) {
-    if (err)
-      LLDB_LOG(log, "Failed to substitute mangling in {0}", mangled);
-    else if (result)
-      LLDB_LOG(log, "Substituted mangling {0} -> {1}", mangled, result);
+    // Append any trailing unmodified input.
+    appendUnchangedInput();
+    LLDB_LOG(log, "Substituted mangling {0} -> {1}", Mangled, Result);
+    return ConstString(Result);
   }
 
-  return result;
+  llvm::itanium_demangle::Node *parseType() {
+    if (llvm::StringRef(First, numLeft()).startswith(Search)) {
+      // We found a match. Append unmodified input up to this point.
+      appendUnchangedInput();
+
+      // And then perform the replacement.
+      Result += Replace;
+      Written += Search.size();
+      Substituted = true;
+    }
+    return AbstractManglingParser::parseType();
+  }
+};
 }
 
 uint32_t CPlusPlusLanguage::FindAlternateFunctionManglings(
@@ -373,23 +390,24 @@
     alternates.insert(ConstString(fixed_scratch));
   }
 
+  TypeSubstitutor TS;
   // `char` is implementation defined as either `signed` or `unsigned`.  As a
   // result a char parameter has 3 possible manglings: 'c'-char, 'a'-signed
   // char, 'h'-unsigned char.  If we're looking for symbols with a signed char
   // parameter, try finding matches which have the general case 'c'.
   if (ConstString char_fixup =
-          SubsPrimitiveParmItanium(mangled_name.GetStringRef(), "a", "c"))
+          TS.substitute(mangled_name.GetStringRef(), "a", "c"))
     alternates.insert(char_fixup);
 
   // long long parameter mangling 'x', may actually just be a long 'l' argument
   if (ConstString long_fixup =
-          SubsPrimitiveParmItanium(mangled_name.GetStringRef(), "x", "l"))
+          TS.substitute(mangled_name.GetStringRef(), "x", "l"))
     alternates.insert(long_fixup);
 
   // unsigned long long parameter mangling 'y', may actually just be unsigned
   // long 'm' argument
   if (ConstString ulong_fixup =
-          SubsPrimitiveParmItanium(mangled_name.GetStringRef(), "y", "m"))
+          TS.substitute(mangled_name.GetStringRef(), "y", "m"))
     alternates.insert(ulong_fixup);
 
   return alternates.size() - start_size;
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to