llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-lldb Author: Michael Buch (Michael137) <details> <summary>Changes</summary> This way we make sure that the logic to reconstruct demangled names in the tests is the same as the logic when reconstructing the actual frame-format variable. `DemangledNameInfo::SuffixRange` is currently the only one which we can't test in the same way until we set it from inside the `TrackingOutputBuffer`. I added TODOs to track this. --- Full diff: https://github.com/llvm/llvm-project/pull/152134.diff 4 Files Affected: - (modified) lldb/source/Core/Mangled.cpp (+1) - (modified) lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp (+93-36) - (modified) lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h (+26) - (modified) lldb/unittests/Core/MangledTest.cpp (+40-17) ``````````diff diff --git a/lldb/source/Core/Mangled.cpp b/lldb/source/Core/Mangled.cpp index 0027bfaeda4f7..3663f430111c2 100644 --- a/lldb/source/Core/Mangled.cpp +++ b/lldb/source/Core/Mangled.cpp @@ -172,6 +172,7 @@ GetItaniumDemangledStr(const char *M) { TrackingOutputBuffer OB(demangled_cstr, demangled_size); demangled_cstr = ipd.finishDemangle(&OB); + // TODO: we should set the SuffixRange inside the TrackingOutputBuffer. OB.NameInfo.SuffixRange.first = OB.NameInfo.QualifiersRange.second; OB.NameInfo.SuffixRange.second = std::string_view(OB).size(); info = std::move(OB.NameInfo); diff --git a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp index 46753c5efc331..d9b8cc5278075 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp +++ b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp @@ -19,6 +19,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/Demangle/ItaniumDemangle.h" +#include "lldb/Core/DemangledNameInfo.h" #include "lldb/Core/Mangled.h" #include "lldb/Core/Module.h" #include "lldb/Core/PluginManager.h" @@ -271,8 +272,14 @@ GetDemangledBasename(const SymbolContext &sc) { auto [demangled_name, info] = *info_or_err; - return demangled_name.slice(info.BasenameRange.first, - info.BasenameRange.second); + return CPlusPlusLanguage::GetDemangledBasename(demangled_name, info); +} + +llvm::StringRef +CPlusPlusLanguage::GetDemangledBasename(llvm::StringRef demangled, + const DemangledNameInfo &info) { + assert(info.hasBasename()); + return demangled.slice(info.BasenameRange.first, info.BasenameRange.second); } static llvm::Expected<llvm::StringRef> @@ -283,12 +290,27 @@ GetDemangledTemplateArguments(const SymbolContext &sc) { auto [demangled_name, info] = *info_or_err; + return CPlusPlusLanguage::GetDemangledTemplateArguments(demangled_name, info); +} + +llvm::Expected<llvm::StringRef> +CPlusPlusLanguage::GetDemangledTemplateArguments( + llvm::StringRef demangled, const DemangledNameInfo &info) { if (info.ArgumentsRange.first < info.BasenameRange.second) return llvm::createStringError("Arguments range for '%s' is invalid.", - demangled_name.data()); + demangled.data()); - return demangled_name.slice(info.BasenameRange.second, - info.ArgumentsRange.first); + return demangled.slice(info.BasenameRange.second, info.ArgumentsRange.first); +} + +llvm::Expected<llvm::StringRef> +CPlusPlusLanguage::GetDemangledReturnTypeLHS(llvm::StringRef demangled, + const DemangledNameInfo &info) { + if (info.ScopeRange.first >= demangled.size()) + return llvm::createStringError( + "Scope range for '%s' LHS return type is invalid.", demangled.data()); + + return demangled.substr(0, info.ScopeRange.first); } static llvm::Expected<llvm::StringRef> @@ -299,12 +321,18 @@ GetDemangledReturnTypeLHS(const SymbolContext &sc) { auto [demangled_name, info] = *info_or_err; - if (info.ScopeRange.first >= demangled_name.size()) - return llvm::createStringError( - "Scope range for '%s' LHS return type is invalid.", - demangled_name.data()); + return CPlusPlusLanguage::GetDemangledReturnTypeLHS(demangled_name, info); +} + +llvm::Expected<llvm::StringRef> +CPlusPlusLanguage::GetDemangledFunctionQualifiers( + llvm::StringRef demangled, const DemangledNameInfo &info) { + if (!info.hasQualifiers()) + return llvm::createStringError("Qualifiers range for '%s' is invalid.", + demangled.data()); - return demangled_name.substr(0, info.ScopeRange.first); + return demangled.slice(info.QualifiersRange.first, + info.QualifiersRange.second); } static llvm::Expected<llvm::StringRef> @@ -315,12 +343,20 @@ GetDemangledFunctionQualifiers(const SymbolContext &sc) { auto [demangled_name, info] = *info_or_err; - if (!info.hasQualifiers()) - return llvm::createStringError("Qualifiers range for '%s' is invalid.", - demangled_name.data()); + return CPlusPlusLanguage::GetDemangledFunctionQualifiers(demangled_name, + info); +} + +llvm::Expected<llvm::StringRef> +CPlusPlusLanguage::GetDemangledReturnTypeRHS(llvm::StringRef demangled, + const DemangledNameInfo &info) { + if (info.QualifiersRange.first < info.ArgumentsRange.second) + return llvm::createStringError( + "Qualifiers range for '%s' RHS return type is invalid.", + demangled.data()); - return demangled_name.slice(info.QualifiersRange.first, - info.QualifiersRange.second); + return demangled.slice(info.ArgumentsRange.second, + info.QualifiersRange.first); } static llvm::Expected<llvm::StringRef> @@ -331,13 +367,17 @@ GetDemangledReturnTypeRHS(const SymbolContext &sc) { auto [demangled_name, info] = *info_or_err; - if (info.QualifiersRange.first < info.ArgumentsRange.second) - return llvm::createStringError( - "Qualifiers range for '%s' RHS return type is invalid.", - demangled_name.data()); + return CPlusPlusLanguage::GetDemangledReturnTypeRHS(demangled_name, info); +} - return demangled_name.slice(info.ArgumentsRange.second, - info.QualifiersRange.first); +llvm::Expected<llvm::StringRef> +CPlusPlusLanguage::GetDemangledScope(llvm::StringRef demangled, + const DemangledNameInfo &info) { + if (!info.hasScope()) + return llvm::createStringError("Scope range for '%s' is invalid.", + demangled.data()); + + return demangled.slice(info.ScopeRange.first, info.ScopeRange.second); } static llvm::Expected<llvm::StringRef> @@ -348,15 +388,16 @@ GetDemangledScope(const SymbolContext &sc) { auto [demangled_name, info] = *info_or_err; - if (!info.hasScope()) - return llvm::createStringError("Scope range for '%s' is invalid.", - demangled_name.data()); - - return demangled_name.slice(info.ScopeRange.first, info.ScopeRange.second); + return CPlusPlusLanguage::GetDemangledScope(demangled_name, info); } /// Handles anything printed after the FunctionEncoding ItaniumDemangle -/// node. Most notably the DotSUffix node. +/// node. Most notably the DotSuffix node. +/// +/// FIXME: the suffix should also have an associated +/// CPlusPlusLanguage::GetDemangledFunctionSuffix +/// once we start setting the `DemangledNameInfo::SuffixRange` +/// from inside the `TrackingOutputBuffer`. static llvm::Expected<llvm::StringRef> GetDemangledFunctionSuffix(const SymbolContext &sc) { auto info_or_err = GetAndValidateInfo(sc); @@ -372,6 +413,16 @@ GetDemangledFunctionSuffix(const SymbolContext &sc) { return demangled_name.slice(info.SuffixRange.first, info.SuffixRange.second); } +llvm::Expected<llvm::StringRef> +CPlusPlusLanguage::GetDemangledFunctionArguments( + llvm::StringRef demangled, const DemangledNameInfo &info) { + if (!info.hasArguments()) + return llvm::createStringError( + "Function arguments range for '%s' is invalid.", demangled.data()); + + return demangled.slice(info.ArgumentsRange.first, info.ArgumentsRange.second); +} + static bool PrintDemangledArgumentList(Stream &s, const SymbolContext &sc) { assert(sc.symbol); @@ -382,13 +433,19 @@ static bool PrintDemangledArgumentList(Stream &s, const SymbolContext &sc) { "frame-format variable: {0}"); return false; } + auto [demangled_name, info] = *info_or_err; - if (!info.hasArguments()) + auto args_or_err = + CPlusPlusLanguage::GetDemangledFunctionArguments(demangled_name, info); + if (!args_or_err) { + LLDB_LOG_ERROR(GetLog(LLDBLog::Language), args_or_err.takeError(), + "Failed to handle ${{function.formatted-arguments}} " + "frame-format variable: {0}"); return false; + } - s << demangled_name.slice(info.ArgumentsRange.first, - info.ArgumentsRange.second); + s << *args_or_err; return true; } @@ -2261,7 +2318,7 @@ bool CPlusPlusLanguage::HandleFrameFormatVariable( FormatEntity::Entry::Type type, Stream &s) { switch (type) { case FormatEntity::Entry::Type::FunctionScope: { - auto scope_or_err = GetDemangledScope(sc); + auto scope_or_err = ::GetDemangledScope(sc); if (!scope_or_err) { LLDB_LOG_ERROR( GetLog(LLDBLog::Language), scope_or_err.takeError(), @@ -2275,7 +2332,7 @@ bool CPlusPlusLanguage::HandleFrameFormatVariable( } case FormatEntity::Entry::Type::FunctionBasename: { - auto name_or_err = GetDemangledBasename(sc); + auto name_or_err = ::GetDemangledBasename(sc); if (!name_or_err) { LLDB_LOG_ERROR( GetLog(LLDBLog::Language), name_or_err.takeError(), @@ -2289,7 +2346,7 @@ bool CPlusPlusLanguage::HandleFrameFormatVariable( } case FormatEntity::Entry::Type::FunctionTemplateArguments: { - auto template_args_or_err = GetDemangledTemplateArguments(sc); + auto template_args_or_err = ::GetDemangledTemplateArguments(sc); if (!template_args_or_err) { LLDB_LOG_ERROR(GetLog(LLDBLog::Language), template_args_or_err.takeError(), @@ -2327,7 +2384,7 @@ bool CPlusPlusLanguage::HandleFrameFormatVariable( return true; } case FormatEntity::Entry::Type::FunctionReturnRight: { - auto return_rhs_or_err = GetDemangledReturnTypeRHS(sc); + auto return_rhs_or_err = ::GetDemangledReturnTypeRHS(sc); if (!return_rhs_or_err) { LLDB_LOG_ERROR(GetLog(LLDBLog::Language), return_rhs_or_err.takeError(), "Failed to handle ${{function.return-right}} frame-format " @@ -2340,7 +2397,7 @@ bool CPlusPlusLanguage::HandleFrameFormatVariable( return true; } case FormatEntity::Entry::Type::FunctionReturnLeft: { - auto return_lhs_or_err = GetDemangledReturnTypeLHS(sc); + auto return_lhs_or_err = ::GetDemangledReturnTypeLHS(sc); if (!return_lhs_or_err) { LLDB_LOG_ERROR(GetLog(LLDBLog::Language), return_lhs_or_err.takeError(), "Failed to handle ${{function.return-left}} frame-format " @@ -2353,7 +2410,7 @@ bool CPlusPlusLanguage::HandleFrameFormatVariable( return true; } case FormatEntity::Entry::Type::FunctionQualifiers: { - auto quals_or_err = GetDemangledFunctionQualifiers(sc); + auto quals_or_err = ::GetDemangledFunctionQualifiers(sc); if (!quals_or_err) { LLDB_LOG_ERROR(GetLog(LLDBLog::Language), quals_or_err.takeError(), "Failed to handle ${{function.qualifiers}} frame-format " diff --git a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h index 22acdf3e8efe9..4f449f11257a6 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h +++ b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h @@ -112,6 +112,32 @@ class CPlusPlusLanguage : public Language { static bool IsCPPMangledName(llvm::StringRef name); + static llvm::StringRef GetDemangledBasename(llvm::StringRef demangled, + const DemangledNameInfo &info); + + static llvm::Expected<llvm::StringRef> + GetDemangledTemplateArguments(llvm::StringRef demangled, + const DemangledNameInfo &info); + + static llvm::Expected<llvm::StringRef> + GetDemangledReturnTypeLHS(llvm::StringRef demangled, + const DemangledNameInfo &info); + + static llvm::Expected<llvm::StringRef> + GetDemangledFunctionQualifiers(llvm::StringRef demangled, + const DemangledNameInfo &info); + + static llvm::Expected<llvm::StringRef> + GetDemangledScope(llvm::StringRef demangled, const DemangledNameInfo &info); + + static llvm::Expected<llvm::StringRef> + GetDemangledReturnTypeRHS(llvm::StringRef demangled, + const DemangledNameInfo &info); + + static llvm::Expected<llvm::StringRef> + GetDemangledFunctionArguments(llvm::StringRef demangled, + const DemangledNameInfo &info); + // Extract C++ context and identifier from a string using heuristic matching // (as opposed to // CPlusPlusLanguage::CxxMethodName which has to have a fully qualified C++ diff --git a/lldb/unittests/Core/MangledTest.cpp b/lldb/unittests/Core/MangledTest.cpp index 4bda657047541..92bd04699303b 100644 --- a/lldb/unittests/Core/MangledTest.cpp +++ b/lldb/unittests/Core/MangledTest.cpp @@ -6,6 +6,8 @@ // //===----------------------------------------------------------------------===// +#include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h" +#include "Plugins/Language/CPlusPlus/CPlusPlusNameParser.h" #include "Plugins/ObjectFile/ELF/ObjectFileELF.h" #include "Plugins/SymbolFile/Symtab/SymbolFileSymtab.h" #include "TestingSupport/SubsystemRAII.h" @@ -19,6 +21,7 @@ #include "lldb/Host/HostInfo.h" #include "lldb/Symbol/SymbolContext.h" +#include "llvm/Support/Error.h" #include "llvm/Support/FileUtilities.h" #include "llvm/Support/Path.h" #include "llvm/Support/Program.h" @@ -748,25 +751,45 @@ TEST_P(DemanglingInfoCorrectnessTestFixutre, Correctness) { auto tracked_name = llvm::StringRef(*OB); - auto return_left = tracked_name.slice(0, OB->NameInfo.ScopeRange.first); - auto scope = tracked_name.slice(OB->NameInfo.ScopeRange.first, - OB->NameInfo.ScopeRange.second); - auto basename = tracked_name.slice(OB->NameInfo.BasenameRange.first, - OB->NameInfo.BasenameRange.second); - auto template_args = tracked_name.slice(OB->NameInfo.BasenameRange.second, - OB->NameInfo.ArgumentsRange.first); - auto args = tracked_name.slice(OB->NameInfo.ArgumentsRange.first, - OB->NameInfo.ArgumentsRange.second); - auto return_right = tracked_name.slice(OB->NameInfo.ArgumentsRange.second, - OB->NameInfo.QualifiersRange.first); - auto qualifiers = tracked_name.slice(OB->NameInfo.QualifiersRange.first, - OB->NameInfo.QualifiersRange.second); + std::string reconstructed_name; + + auto return_left = + CPlusPlusLanguage::GetDemangledReturnTypeLHS(tracked_name, OB->NameInfo); + EXPECT_THAT_EXPECTED(return_left, llvm::Succeeded()); + reconstructed_name += *return_left; + + auto scope = CPlusPlusLanguage::GetDemangledScope(tracked_name, OB->NameInfo); + EXPECT_THAT_EXPECTED(scope, llvm::Succeeded()); + reconstructed_name += *scope; + + auto basename = + CPlusPlusLanguage::GetDemangledBasename(tracked_name, OB->NameInfo); + reconstructed_name += basename; + + auto template_args = CPlusPlusLanguage::GetDemangledTemplateArguments( + tracked_name, OB->NameInfo); + EXPECT_THAT_EXPECTED(template_args, llvm::Succeeded()); + reconstructed_name += *template_args; + + auto args = CPlusPlusLanguage::GetDemangledFunctionArguments(tracked_name, + OB->NameInfo); + EXPECT_THAT_EXPECTED(args, llvm::Succeeded()); + reconstructed_name += *args; + + auto return_right = + CPlusPlusLanguage::GetDemangledReturnTypeRHS(tracked_name, OB->NameInfo); + EXPECT_THAT_EXPECTED(return_right, llvm::Succeeded()); + reconstructed_name += *return_right; + + auto qualifiers = CPlusPlusLanguage::GetDemangledFunctionQualifiers( + tracked_name, OB->NameInfo); + EXPECT_THAT_EXPECTED(qualifiers, llvm::Succeeded()); + reconstructed_name += *qualifiers; + + // TODO: should retrieve suffix using the plugin too. auto suffix = tracked_name.slice(OB->NameInfo.QualifiersRange.second, llvm::StringRef::npos); - - auto reconstructed_name = - llvm::join_items("", return_left, scope, basename, template_args, args, - return_right, qualifiers, suffix); + reconstructed_name += suffix; EXPECT_EQ(reconstructed_name, demangled); } `````````` </details> https://github.com/llvm/llvm-project/pull/152134 _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits