diff options
author | Michael Buch <michaelbuch12@gmail.com> | 2025-04-11 11:02:19 +0100 |
---|---|---|
committer | Michael Buch <michaelbuch12@gmail.com> | 2025-04-25 10:04:27 +0100 |
commit | 8b91b44a3be680788f914af72f38f90d35925c23 (patch) | |
tree | 1cc49f2e463d4401b1866b408244e629c989276e /lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp | |
parent | a2672250be871bdac18c1a955265a98704434218 (diff) | |
download | llvm-8b91b44a3be680788f914af72f38f90d35925c23.zip llvm-8b91b44a3be680788f914af72f38f90d35925c23.tar.gz llvm-8b91b44a3be680788f914af72f38f90d35925c23.tar.bz2 |
[lldb][Format] Introduce new frame-format variables for function parts (#131836)
Adds new frame-format variables and implements them in the CPlusPlusLanguage plugin.
We use the `DemangledNameInfo` type to retrieve the necessary part of the demangled name.
https://github.com/llvm/llvm-project/pull/131836
Diffstat (limited to 'lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp')
-rw-r--r-- | lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp | 233 |
1 files changed, 231 insertions, 2 deletions
diff --git a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp index 40b6563..cf425fc 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp +++ b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp @@ -235,6 +235,151 @@ static bool PrettyPrintFunctionNameWithArgs(Stream &out_stream, return true; } +static std::optional<llvm::StringRef> +GetDemangledBasename(const SymbolContext &sc) { + Mangled mangled = sc.GetPossiblyInlinedFunctionName(); + if (!mangled) + return std::nullopt; + + auto demangled_name = mangled.GetDemangledName().GetStringRef(); + if (demangled_name.empty()) + return std::nullopt; + + const std::optional<DemangledNameInfo> &info = mangled.GetDemangledInfo(); + if (!info) + return std::nullopt; + + // Function without a basename is nonsense. + if (!info->hasBasename()) + return std::nullopt; + + return demangled_name.slice(info->BasenameRange.first, + info->BasenameRange.second); +} + +static std::optional<llvm::StringRef> +GetDemangledTemplateArguments(const SymbolContext &sc) { + Mangled mangled = sc.GetPossiblyInlinedFunctionName(); + if (!mangled) + return std::nullopt; + + auto demangled_name = mangled.GetDemangledName().GetStringRef(); + if (demangled_name.empty()) + return std::nullopt; + + const std::optional<DemangledNameInfo> &info = mangled.GetDemangledInfo(); + if (!info) + return std::nullopt; + + // Function without a basename is nonsense. + if (!info->hasBasename()) + return std::nullopt; + + if (info->ArgumentsRange.first < info->BasenameRange.second) + return std::nullopt; + + return demangled_name.slice(info->BasenameRange.second, + info->ArgumentsRange.first); +} + +static std::optional<llvm::StringRef> +GetDemangledReturnTypeLHS(const SymbolContext &sc) { + Mangled mangled = sc.GetPossiblyInlinedFunctionName(); + if (!mangled) + return std::nullopt; + + auto demangled_name = mangled.GetDemangledName().GetStringRef(); + if (demangled_name.empty()) + return std::nullopt; + + const std::optional<DemangledNameInfo> &info = mangled.GetDemangledInfo(); + if (!info) + return std::nullopt; + + // Function without a basename is nonsense. + if (!info->hasBasename()) + return std::nullopt; + + if (info->ScopeRange.first >= demangled_name.size()) + return std::nullopt; + + return demangled_name.substr(0, info->ScopeRange.first); +} + +static std::optional<llvm::StringRef> +GetDemangledFunctionQualifiers(const SymbolContext &sc) { + Mangled mangled = sc.GetPossiblyInlinedFunctionName(); + if (!mangled) + return std::nullopt; + + auto demangled_name = mangled.GetDemangledName().GetStringRef(); + if (demangled_name.empty()) + return std::nullopt; + + const std::optional<DemangledNameInfo> &info = mangled.GetDemangledInfo(); + if (!info) + return std::nullopt; + + // Function without a basename is nonsense. + if (!info->hasBasename()) + return std::nullopt; + + if (info->QualifiersRange.second < info->QualifiersRange.first) + return std::nullopt; + + return demangled_name.slice(info->QualifiersRange.first, + info->QualifiersRange.second); +} + +static std::optional<llvm::StringRef> +GetDemangledReturnTypeRHS(const SymbolContext &sc) { + Mangled mangled = sc.GetPossiblyInlinedFunctionName(); + if (!mangled) + return std::nullopt; + + auto demangled_name = mangled.GetDemangledName().GetStringRef(); + if (demangled_name.empty()) + return std::nullopt; + + const std::optional<DemangledNameInfo> &info = mangled.GetDemangledInfo(); + if (!info) + return std::nullopt; + + // Function without a basename is nonsense. + if (!info->hasBasename()) + return std::nullopt; + + if (info->QualifiersRange.first < info->ArgumentsRange.second) + return std::nullopt; + + return demangled_name.slice(info->ArgumentsRange.second, + info->QualifiersRange.first); +} + +static std::optional<llvm::StringRef> +GetDemangledScope(const SymbolContext &sc) { + Mangled mangled = sc.GetPossiblyInlinedFunctionName(); + if (!mangled) + return std::nullopt; + + auto demangled_name = mangled.GetDemangledName().GetStringRef(); + if (demangled_name.empty()) + return std::nullopt; + + const std::optional<DemangledNameInfo> &info = mangled.GetDemangledInfo(); + if (!info) + return std::nullopt; + + // Function without a basename is nonsense. + if (!info->hasBasename()) + return std::nullopt; + + if (info->ScopeRange.second < info->ScopeRange.first) + return std::nullopt; + + return demangled_name.slice(info->ScopeRange.first, info->ScopeRange.second); +} + bool CPlusPlusLanguage::CxxMethodName::TrySimplifiedParse() { // This method tries to parse simple method definitions which are presumably // most comman in user programs. Definitions that can be parsed by this @@ -1694,8 +1839,9 @@ static bool PrintFunctionNameWithArgs(Stream &s, ExecutionContextScope *exe_scope = exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr; - const char *cstr = sc.GetPossiblyInlinedFunctionName( - Mangled::NamePreference::ePreferDemangled); + const char *cstr = sc.GetPossiblyInlinedFunctionName() + .GetName(Mangled::NamePreference::ePreferDemangled) + .AsCString(); if (!cstr) return false; @@ -1739,3 +1885,86 @@ bool CPlusPlusLanguage::GetFunctionDisplayName( return false; } } +bool CPlusPlusLanguage::HandleFrameFormatVariable( + const SymbolContext &sc, const ExecutionContext *exe_ctx, + FormatEntity::Entry::Type type, Stream &s) { + assert(sc.function); + + switch (type) { + case FormatEntity::Entry::Type::FunctionScope: { + std::optional<llvm::StringRef> scope = GetDemangledScope(sc); + if (!scope) + return false; + + s << *scope; + + return true; + } + + case FormatEntity::Entry::Type::FunctionBasename: { + std::optional<llvm::StringRef> name = GetDemangledBasename(sc); + if (!name) + return false; + + s << *name; + + return true; + } + + case FormatEntity::Entry::Type::FunctionTemplateArguments: { + std::optional<llvm::StringRef> template_args = + GetDemangledTemplateArguments(sc); + if (!template_args) + return false; + + s << *template_args; + + return true; + } + + case FormatEntity::Entry::Type::FunctionFormattedArguments: { + VariableList args; + if (auto variable_list_sp = GetFunctionVariableList(sc)) + variable_list_sp->AppendVariablesWithScope(eValueTypeVariableArgument, + args); + + ExecutionContextScope *exe_scope = + exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr; + + s << '('; + FormatEntity::PrettyPrintFunctionArguments(s, args, exe_scope); + s << ')'; + + return true; + } + case FormatEntity::Entry::Type::FunctionReturnRight: { + std::optional<llvm::StringRef> return_rhs = GetDemangledReturnTypeRHS(sc); + if (!return_rhs) + return false; + + s << *return_rhs; + + return true; + } + case FormatEntity::Entry::Type::FunctionReturnLeft: { + std::optional<llvm::StringRef> return_lhs = GetDemangledReturnTypeLHS(sc); + if (!return_lhs) + return false; + + s << *return_lhs; + + return true; + } + case FormatEntity::Entry::Type::FunctionQualifiers: { + std::optional<llvm::StringRef> quals = GetDemangledFunctionQualifiers(sc); + if (!quals) + return false; + + s << *quals; + + return true; + } + default: + return false; + } +} |