Index: source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp =================================================================== --- source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp +++ 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" @@ -274,72 +274,67 @@ 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 writer; +namespace { +class NodeAllocator { + llvm::BumpPtrAllocator Alloc; - 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(); - } - } +public: + void reset() { Alloc.Reset(); } - 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(); - } + template T *makeNode(Args &&... args) { + return new (Alloc.Allocate(sizeof(T), alignof(T))) + T(std::forward(args)...); + } - return ConstString(output); + void *allocateNodeArray(size_t sz) { + return Alloc.Allocate(sizeof(llvm::itanium_demangle::Node *) * sz, + alignof(llvm::itanium_demangle::Node *)); + } +}; + +/// Given a mangled function `Mangled`, replace all the primitive function type +/// arguments of `Search` with type `Replace`. +class TypeSubstitutor + : public llvm::itanium_demangle::AbstractManglingParser { + const char *Written; + llvm::StringRef Search; + llvm::StringRef Replace; + llvm::SmallString<128> Result; + llvm::raw_svector_ostream OS{Result}; + bool Substituted = false; + + TypeSubstitutor(llvm::StringRef Mangled, llvm::StringRef Search, + llvm::StringRef Replace) + : AbstractManglingParser(Mangled.begin(), Mangled.end()), + Written(Mangled.begin()), Search(Search), Replace(Replace) {} + +public: + static ConstString substitute(llvm::StringRef Mangled, llvm::StringRef From, + llvm::StringRef To) { + Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE); + + TypeSubstitutor TS(Mangled, From, To); + if (TS.parse() == nullptr) { + LLDB_LOG(log, "Failed to substitute mangling in {0}", Mangled); + return ConstString(); } + if (!TS.Substituted) + return ConstString(); + TS.OS << llvm::StringRef(TS.Written, TS.First - TS.Written); + LLDB_LOG(log, "Substituted mangling {0} -> {1}", Mangled, TS.OS.str()); + return ConstString(TS.OS.str()); + } - static void Callback(void *context, const char *match) { - ((PrimitiveParmSubs *)context)->Substitute(llvm::StringRef(match)); + llvm::itanium_demangle::Node *parseType() { + if (llvm::StringRef(First, Last - First).startswith(Search)) { + OS << llvm::StringRef(Written, First - Written) << Replace; + Written = First + Search.size(); + Substituted = true; } - }; - - // 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); + return AbstractManglingParser::parseType(); } - - return result; +}; } uint32_t CPlusPlusLanguage::FindAlternateFunctionManglings( @@ -373,18 +368,18 @@ // 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")) + TypeSubstitutor::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")) + TypeSubstitutor::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")) + TypeSubstitutor::substitute(mangled_name.GetStringRef(), "y", "m")) alternates.insert(ulong_fixup); return alternates.size() - start_size;