diff --git a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp --- a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp +++ b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp @@ -284,46 +284,34 @@ } }; -/// Given a mangled function `Mangled`, replace all the primitive function type -/// arguments of `Search` with type `Replace`. -class TypeSubstitutor - : public llvm::itanium_demangle::AbstractManglingParser +class ManglingSubstitutor + : public llvm::itanium_demangle::AbstractManglingParser { - /// Input character until which we have constructed the respective output - /// already - const char *Written; + using Base = + llvm::itanium_demangle::AbstractManglingParser; - llvm::StringRef Search; - llvm::StringRef Replace; - llvm::SmallString<128> Result; +public: + ManglingSubstitutor() : Base(nullptr, nullptr) {} - /// Whether we have performed any substitutions. - bool Substituted; + template + ConstString substitute(llvm::StringRef Mangled, Ts &&... Vals) { + this->getDerived().reset(Mangled, std::forward(Vals)...); + return substituteImpl(Mangled); + } - void reset(llvm::StringRef Mangled, llvm::StringRef Search, - llvm::StringRef Replace) { - AbstractManglingParser::reset(Mangled.begin(), Mangled.end()); + +protected: + void reset(llvm::StringRef Mangled) { + Base::reset(Mangled.begin(), Mangled.end()); Written = Mangled.begin(); - this->Search = Search; - this->Replace = Replace; Result.clear(); Substituted = false; } - void appendUnchangedInput() { - Result += llvm::StringRef(Written, First - Written); - Written = First; - } - -public: - TypeSubstitutor() : AbstractManglingParser(nullptr, nullptr) {} - - ConstString substitute(llvm::StringRef Mangled, llvm::StringRef From, - llvm::StringRef To) { + ConstString substituteImpl(llvm::StringRef Mangled) { Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE); - - reset(Mangled, From, To); - if (parse() == nullptr) { + if (this->parse() == nullptr) { LLDB_LOG(log, "Failed to substitute mangling in {0}", Mangled); return ConstString(); } @@ -336,20 +324,69 @@ return ConstString(Result); } + void trySubstitute(llvm::StringRef From, llvm::StringRef To) { + if (!llvm::StringRef(currentParserPos(), this->numLeft()).startswith(From)) + return; + + // We found a match. Append unmodified input up to this point. + appendUnchangedInput(); + + // And then perform the replacement. + Result += To; + Written += From.size(); + Substituted = true; + } + +private: + /// Input character until which we have constructed the respective output + /// already. + const char *Written; + + llvm::SmallString<128> Result; + + /// Whether we have performed any substitutions. + bool Substituted; + + const char *currentParserPos() const { return this->First; } + + void appendUnchangedInput() { + Result += + llvm::StringRef(Written, std::distance(Written, currentParserPos())); + Written = currentParserPos(); + } + +}; + +/// Given a mangled function `Mangled`, replace all the primitive function type +/// arguments of `Search` with type `Replace`. +class TypeSubstitutor : public ManglingSubstitutor { + llvm::StringRef Search; + llvm::StringRef Replace; + +public: + void reset(llvm::StringRef Mangled, llvm::StringRef Search, + llvm::StringRef Replace) { + ManglingSubstitutor::reset(Mangled); + this->Search = Search; + this->Replace = Replace; + } + 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(); + trySubstitute(Search, Replace); + return ManglingSubstitutor::parseType(); } }; -} + +class CtorDtorSubstitutor : public ManglingSubstitutor { +public: + llvm::itanium_demangle::Node * + parseCtorDtorName(llvm::itanium_demangle::Node *&SoFar, NameState *State) { + trySubstitute("C1", "C2"); + trySubstitute("D1", "D2"); + return ManglingSubstitutor::parseCtorDtorName(SoFar, State); + } +}; +} // namespace uint32_t CPlusPlusLanguage::FindAlternateFunctionManglings( const ConstString mangled_name, std::set &alternates) { @@ -397,6 +434,10 @@ TS.substitute(mangled_name.GetStringRef(), "y", "m")) alternates.insert(ulong_fixup); + if (ConstString ctor_fixup = + CtorDtorSubstitutor().substitute(mangled_name.GetStringRef())) + alternates.insert(ctor_fixup); + return alternates.size() - start_size; } diff --git a/lldb/unittests/Language/CPlusPlus/CPlusPlusLanguageTest.cpp b/lldb/unittests/Language/CPlusPlus/CPlusPlusLanguageTest.cpp --- a/lldb/unittests/Language/CPlusPlus/CPlusPlusLanguageTest.cpp +++ b/lldb/unittests/Language/CPlusPlus/CPlusPlusLanguageTest.cpp @@ -191,6 +191,8 @@ EXPECT_THAT(FindAlternate("_ZN1A1fEx"), Contains("_ZN1A1fEl")); EXPECT_THAT(FindAlternate("_ZN1A1fEy"), Contains("_ZN1A1fEm")); EXPECT_THAT(FindAlternate("_ZN1A1fEai"), Contains("_ZN1A1fEci")); + EXPECT_THAT(FindAlternate("_ZN1AC1Ev"), Contains("_ZN1AC2Ev")); + EXPECT_THAT(FindAlternate("_ZN1AD1Ev"), Contains("_ZN1AD2Ev")); EXPECT_THAT(FindAlternate("_bogus"), IsEmpty()); }