https://github.com/felipepiovezan updated https://github.com/llvm/llvm-project/pull/153258
>From 34ae693c7731538ec00274072c4beb3100c43848 Mon Sep 17 00:00:00 2001 From: Felipe de Azevedo Piovezan <[email protected]> Date: Tue, 12 Aug 2025 09:34:46 -0700 Subject: [PATCH 1/3] [LLDB][NFC] Remove redundant target/process checks in SBFrame This is a follow up to https://github.com/llvm/llvm-project/pull/152020, continuing the removal of now-redundant `if(process && target)` checks. Since this causes a diff in every line of the affected functions, this commit also uses the opportunity to create some helper functions and reduce nesting of the affected methods by rewriting all pre-condition checks as early returns, while remaining strictly NFC. This has exposed some odd behaviors: 1. `SBFrame::GetVariables` has a variable `num_produced` which is clearly meant to be incremented on every iteration of the loop but it is only incremented once, after the loop. So its value is always 0 or 1. The variable now lives in `FetchVariablesUnlessInterrupted`. 2. `SBFrame::GetVariables` has an interruption mechanism for local variables, but not for "recognized arguments". It's unclear if this is by design or not, but it is now evident that there is a discrepancy there. 3. In `SBFrame::EvaluateExpression` we only log some error paths, but not all of them. To stick to the strictly NFC nature of this patch, it does not address any of these issues. --- lldb/include/lldb/API/SBFrame.h | 19 ++ lldb/source/API/SBFrame.cpp | 510 ++++++++++++++++---------------- 2 files changed, 273 insertions(+), 256 deletions(-) diff --git a/lldb/include/lldb/API/SBFrame.h b/lldb/include/lldb/API/SBFrame.h index 5283cdfe53faa..59a7343f9eaf3 100644 --- a/lldb/include/lldb/API/SBFrame.h +++ b/lldb/include/lldb/API/SBFrame.h @@ -13,6 +13,8 @@ #include "lldb/API/SBValueList.h" namespace lldb_private { +class StackFrame; +class Debugger; namespace python { class SWIGBridge; } @@ -241,6 +243,23 @@ class LLDB_API SBFrame { /// not currently stopped. static SBValue CreateProcessIsRunningExprEvalError(); + enum WasInterrupted { Yes, No }; + + /// Populates `value_list` with the variables from `frame` according to + /// `options`. This method checks whether the Debugger received an interrupt + /// before processing every variable, returning `WasInterrupted::yes` in that + /// case. + static WasInterrupted FetchVariablesUnlessInterrupted( + const lldb::SBVariablesOptions &options, lldb_private::StackFrame &frame, + SBValueList &value_list, lldb_private::Debugger &dbg); + + /// Populates `value_list` with recognized arguments of `frame` according to + /// `options`. + static void FetchRecognizedArguments(const SBVariablesOptions &options, + lldb_private::StackFrame &frame, + SBTarget target, + SBValueList &value_list); + lldb::ExecutionContextRefSP m_opaque_sp; }; diff --git a/lldb/source/API/SBFrame.cpp b/lldb/source/API/SBFrame.cpp index 42dbed490a33d..ed09fd2f2f90d 100644 --- a/lldb/source/API/SBFrame.cpp +++ b/lldb/source/API/SBFrame.cpp @@ -490,99 +490,85 @@ SBValue SBFrame::FindValue(const char *name, ValueType value_type, if (!exe_ctx) { LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); return value_sp; - } else { - Target *target = exe_ctx->GetTargetPtr(); - Process *process = exe_ctx->GetProcessPtr(); - if (target && process) { // FIXME: this check is redundant. - if (StackFrame *frame = exe_ctx->GetFramePtr()) { - VariableList variable_list; - - switch (value_type) { - case eValueTypeVariableGlobal: // global variable - case eValueTypeVariableStatic: // static variable - case eValueTypeVariableArgument: // function argument variables - case eValueTypeVariableLocal: // function local variables - case eValueTypeVariableThreadLocal: // thread local variables - { - SymbolContext sc(frame->GetSymbolContext(eSymbolContextBlock)); - - const bool can_create = true; - const bool get_parent_variables = true; - const bool stop_if_block_is_inlined_function = true; - - if (sc.block) - sc.block->AppendVariables( - can_create, get_parent_variables, - stop_if_block_is_inlined_function, - [frame](Variable *v) { return v->IsInScope(frame); }, - &variable_list); - if (value_type == eValueTypeVariableGlobal - || value_type == eValueTypeVariableStatic) { - const bool get_file_globals = true; - VariableList *frame_vars = frame->GetVariableList(get_file_globals, - nullptr); - if (frame_vars) - frame_vars->AppendVariablesIfUnique(variable_list); - } - ConstString const_name(name); - VariableSP variable_sp( - variable_list.FindVariable(const_name, value_type)); - if (variable_sp) { - value_sp = frame->GetValueObjectForFrameVariable(variable_sp, - eNoDynamicValues); - sb_value.SetSP(value_sp, use_dynamic); - } - } break; - - case eValueTypeRegister: // stack frame register value - { - RegisterContextSP reg_ctx(frame->GetRegisterContext()); - if (reg_ctx) { - if (const RegisterInfo *reg_info = - reg_ctx->GetRegisterInfoByName(name)) { - value_sp = ValueObjectRegister::Create(frame, reg_ctx, reg_info); - sb_value.SetSP(value_sp); - } - } - } break; - - case eValueTypeRegisterSet: // A collection of stack frame register - // values - { - RegisterContextSP reg_ctx(frame->GetRegisterContext()); - if (reg_ctx) { - const uint32_t num_sets = reg_ctx->GetRegisterSetCount(); - for (uint32_t set_idx = 0; set_idx < num_sets; ++set_idx) { - const RegisterSet *reg_set = reg_ctx->GetRegisterSet(set_idx); - if (reg_set && - (llvm::StringRef(reg_set->name).equals_insensitive(name) || - llvm::StringRef(reg_set->short_name) - .equals_insensitive(name))) { - value_sp = - ValueObjectRegisterSet::Create(frame, reg_ctx, set_idx); - sb_value.SetSP(value_sp); - break; - } - } - } - } break; - - case eValueTypeConstResult: // constant result variables - { - ConstString const_name(name); - ExpressionVariableSP expr_var_sp( - target->GetPersistentVariable(const_name)); - if (expr_var_sp) { - value_sp = expr_var_sp->GetValueObject(); - sb_value.SetSP(value_sp, use_dynamic); - } - } break; - - default: + } + + StackFrame *frame = exe_ctx->GetFramePtr(); + if (!frame) + return value_sp; + + VariableList variable_list; + + switch (value_type) { + case eValueTypeVariableGlobal: // global variable + case eValueTypeVariableStatic: // static variable + case eValueTypeVariableArgument: // function argument variables + case eValueTypeVariableLocal: // function local variables + case eValueTypeVariableThreadLocal: { // thread local variables + SymbolContext sc(frame->GetSymbolContext(eSymbolContextBlock)); + + const bool can_create = true; + const bool get_parent_variables = true; + const bool stop_if_block_is_inlined_function = true; + + if (sc.block) + sc.block->AppendVariables( + can_create, get_parent_variables, stop_if_block_is_inlined_function, + [frame](Variable *v) { return v->IsInScope(frame); }, &variable_list); + if (value_type == eValueTypeVariableGlobal || + value_type == eValueTypeVariableStatic) { + const bool get_file_globals = true; + VariableList *frame_vars = + frame->GetVariableList(get_file_globals, nullptr); + if (frame_vars) + frame_vars->AppendVariablesIfUnique(variable_list); + } + ConstString const_name(name); + VariableSP variable_sp(variable_list.FindVariable(const_name, value_type)); + if (variable_sp) { + value_sp = + frame->GetValueObjectForFrameVariable(variable_sp, eNoDynamicValues); + sb_value.SetSP(value_sp, use_dynamic); + } + } break; + + case eValueTypeRegister: { // stack frame register value + if (RegisterContextSP reg_ctx = frame->GetRegisterContext()) { + if (const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(name)) { + value_sp = ValueObjectRegister::Create(frame, reg_ctx, reg_info); + sb_value.SetSP(value_sp); + } + } + } break; + + case eValueTypeRegisterSet: { // A collection of stack frame register + // values + if (RegisterContextSP reg_ctx = frame->GetRegisterContext()) { + const uint32_t num_sets = reg_ctx->GetRegisterSetCount(); + for (uint32_t set_idx = 0; set_idx < num_sets; ++set_idx) { + const RegisterSet *reg_set = reg_ctx->GetRegisterSet(set_idx); + if (reg_set && + (llvm::StringRef(reg_set->name).equals_insensitive(name) || + llvm::StringRef(reg_set->short_name).equals_insensitive(name))) { + value_sp = ValueObjectRegisterSet::Create(frame, reg_ctx, set_idx); + sb_value.SetSP(value_sp); break; } } } + } break; + + case eValueTypeConstResult: { // constant result variables + ConstString const_name(name); + Target *target = exe_ctx->GetTargetPtr(); + ExpressionVariableSP expr_var_sp(target->GetPersistentVariable(const_name)); + if (expr_var_sp) { + value_sp = expr_var_sp->GetValueObject(); + sb_value.SetSP(value_sp, use_dynamic); + } + } break; + + default: + break; } return sb_value; @@ -698,169 +684,184 @@ lldb::SBValueList SBFrame::GetVariables(bool arguments, bool locals, return GetVariables(options); } +/// Returns true if the variable is in any of the requested scopes. +static bool IsInRequestedScope(bool statics, bool arguments, bool locals, + Variable &var) { + switch (var.GetScope()) { + case eValueTypeVariableGlobal: + case eValueTypeVariableStatic: + case eValueTypeVariableThreadLocal: + return statics; + + case eValueTypeVariableArgument: + return arguments; + + case eValueTypeVariableLocal: + return locals; + + default: + break; + } + return false; +} + +SBFrame::WasInterrupted SBFrame::FetchVariablesUnlessInterrupted( + const lldb::SBVariablesOptions &options, StackFrame &frame, + SBValueList &value_list, Debugger &dbg) { + const bool statics = options.GetIncludeStatics(); + const bool arguments = options.GetIncludeArguments(); + const bool locals = options.GetIncludeLocals(); + const bool in_scope_only = options.GetInScopeOnly(); + const bool include_runtime_support_values = + options.GetIncludeRuntimeSupportValues(); + const lldb::DynamicValueType use_dynamic = options.GetUseDynamic(); + + Status var_error; + VariableList *variable_list = frame.GetVariableList(true, &var_error); + + std::set<VariableSP> variable_set; + + if (var_error.Fail()) + value_list.SetError(std::move(var_error)); + + if (!variable_list) + return WasInterrupted::No; + const size_t num_variables = variable_list->GetSize(); + size_t num_produced = 0; + for (const VariableSP &variable_sp : *variable_list) { + if (!variable_sp || + !IsInRequestedScope(statics, arguments, locals, *variable_sp)) + continue; + + if (INTERRUPT_REQUESTED( + dbg, + "Interrupted getting frame variables with {0} of {1} " + "produced.", + num_produced, num_variables)) + return WasInterrupted::Yes; + + // Only add variables once so we don't end up with duplicates + if (variable_set.insert(variable_sp).second == false) + continue; + if (in_scope_only && !variable_sp->IsInScope(&frame)) + continue; + + ValueObjectSP valobj_sp( + frame.GetValueObjectForFrameVariable(variable_sp, eNoDynamicValues)); + + if (!include_runtime_support_values && valobj_sp != nullptr && + valobj_sp->IsRuntimeSupportValue()) + continue; + + SBValue value_sb; + value_sb.SetSP(valobj_sp, use_dynamic); + value_list.Append(value_sb); + } + num_produced++; + + return WasInterrupted::No; +} + +void SBFrame::FetchRecognizedArguments(const SBVariablesOptions &options, + StackFrame &frame, SBTarget target, + SBValueList &value_list) { + if (!options.GetIncludeRecognizedArguments(target)) + return; + RecognizedStackFrameSP recognized_frame = frame.GetRecognizedFrame(); + if (!recognized_frame) + return; + + ValueObjectListSP recognized_arg_list = + recognized_frame->GetRecognizedArguments(); + if (!recognized_arg_list) + return; + + const lldb::DynamicValueType use_dynamic = options.GetUseDynamic(); + for (auto &rec_value_sp : recognized_arg_list->GetObjects()) { + SBValue value_sb; + value_sb.SetSP(rec_value_sp, use_dynamic); + value_list.Append(value_sb); + } +} + SBValueList SBFrame::GetVariables(const lldb::SBVariablesOptions &options) { LLDB_INSTRUMENT_VA(this, options); - SBValueList value_list; llvm::Expected<StoppedExecutionContext> exe_ctx = GetStoppedExecutionContext(m_opaque_sp); if (!exe_ctx) { LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); return SBValueList(); - } else { - const bool statics = options.GetIncludeStatics(); - const bool arguments = options.GetIncludeArguments(); - const bool recognized_arguments = - options.GetIncludeRecognizedArguments(SBTarget(exe_ctx->GetTargetSP())); - const bool locals = options.GetIncludeLocals(); - const bool in_scope_only = options.GetInScopeOnly(); - const bool include_runtime_support_values = - options.GetIncludeRuntimeSupportValues(); - const lldb::DynamicValueType use_dynamic = options.GetUseDynamic(); - - std::set<VariableSP> variable_set; - Process *process = exe_ctx->GetProcessPtr(); - if (process) { // FIXME: this check is redundant. - if (StackFrame *frame = exe_ctx->GetFramePtr()) { - Debugger &dbg = process->GetTarget().GetDebugger(); - VariableList *variable_list = nullptr; - Status var_error; - variable_list = frame->GetVariableList(true, &var_error); - if (var_error.Fail()) - value_list.SetError(std::move(var_error)); - if (variable_list) { - const size_t num_variables = variable_list->GetSize(); - if (num_variables) { - size_t num_produced = 0; - for (const VariableSP &variable_sp : *variable_list) { - if (INTERRUPT_REQUESTED(dbg, - "Interrupted getting frame variables with {0} of {1} " - "produced.", num_produced, num_variables)) - return {}; - - if (variable_sp) { - bool add_variable = false; - switch (variable_sp->GetScope()) { - case eValueTypeVariableGlobal: - case eValueTypeVariableStatic: - case eValueTypeVariableThreadLocal: - add_variable = statics; - break; - - case eValueTypeVariableArgument: - add_variable = arguments; - break; - - case eValueTypeVariableLocal: - add_variable = locals; - break; - - default: - break; - } - if (add_variable) { - // Only add variables once so we don't end up with duplicates - if (variable_set.find(variable_sp) == variable_set.end()) - variable_set.insert(variable_sp); - else - continue; - - if (in_scope_only && !variable_sp->IsInScope(frame)) - continue; - - ValueObjectSP valobj_sp(frame->GetValueObjectForFrameVariable( - variable_sp, eNoDynamicValues)); - - if (!include_runtime_support_values && valobj_sp != nullptr && - valobj_sp->IsRuntimeSupportValue()) - continue; - - SBValue value_sb; - value_sb.SetSP(valobj_sp, use_dynamic); - value_list.Append(value_sb); - } - } - } - num_produced++; - } - } - if (recognized_arguments) { - auto recognized_frame = frame->GetRecognizedFrame(); - if (recognized_frame) { - ValueObjectListSP recognized_arg_list = - recognized_frame->GetRecognizedArguments(); - if (recognized_arg_list) { - for (auto &rec_value_sp : recognized_arg_list->GetObjects()) { - SBValue value_sb; - value_sb.SetSP(rec_value_sp, use_dynamic); - value_list.Append(value_sb); - } - } - } - } - } - } } + StackFrame *frame = exe_ctx->GetFramePtr(); + if (!frame) + return SBValueList(); + + SBValueList value_list; + if (WasInterrupted::Yes == + FetchVariablesUnlessInterrupted(options, *frame, value_list, + exe_ctx->GetTargetPtr()->GetDebugger())) + return value_list; + + FetchRecognizedArguments(options, *frame, SBTarget(exe_ctx->GetTargetSP()), + value_list); return value_list; } SBValueList SBFrame::GetRegisters() { LLDB_INSTRUMENT_VA(this); - SBValueList value_list; llvm::Expected<StoppedExecutionContext> exe_ctx = GetStoppedExecutionContext(m_opaque_sp); if (!exe_ctx) { LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); return SBValueList(); - } else { - Target *target = exe_ctx->GetTargetPtr(); - Process *process = exe_ctx->GetProcessPtr(); - if (target && process) { // FIXME: this check is redundant. - if (StackFrame *frame = exe_ctx->GetFramePtr()) { - RegisterContextSP reg_ctx(frame->GetRegisterContext()); - if (reg_ctx) { - const uint32_t num_sets = reg_ctx->GetRegisterSetCount(); - for (uint32_t set_idx = 0; set_idx < num_sets; ++set_idx) { - value_list.Append( - ValueObjectRegisterSet::Create(frame, reg_ctx, set_idx)); - } - } - } - } } + StackFrame *frame = exe_ctx->GetFramePtr(); + if (!frame) + return SBValueList(); + + RegisterContextSP reg_ctx(frame->GetRegisterContext()); + if (!reg_ctx) + return SBValueList(); + + SBValueList value_list; + const uint32_t num_sets = reg_ctx->GetRegisterSetCount(); + for (uint32_t set_idx = 0; set_idx < num_sets; ++set_idx) + value_list.Append(ValueObjectRegisterSet::Create(frame, reg_ctx, set_idx)); + return value_list; } SBValue SBFrame::FindRegister(const char *name) { LLDB_INSTRUMENT_VA(this, name); - SBValue result; ValueObjectSP value_sp; llvm::Expected<StoppedExecutionContext> exe_ctx = GetStoppedExecutionContext(m_opaque_sp); if (!exe_ctx) { LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); return SBValue(); - } else { - Target *target = exe_ctx->GetTargetPtr(); - Process *process = exe_ctx->GetProcessPtr(); - if (target && process) { // FIXME: this check is redundant. - if (StackFrame *frame = exe_ctx->GetFramePtr()) { - RegisterContextSP reg_ctx(frame->GetRegisterContext()); - if (reg_ctx) { - if (const RegisterInfo *reg_info = - reg_ctx->GetRegisterInfoByName(name)) { - value_sp = ValueObjectRegister::Create(frame, reg_ctx, reg_info); - result.SetSP(value_sp); - } - } - } - } } + StackFrame *frame = exe_ctx->GetFramePtr(); + if (!frame) + return SBValue(); + + RegisterContextSP reg_ctx(frame->GetRegisterContext()); + if (!reg_ctx) + return SBValue(); + + const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(name); + if (!reg_info) + return SBValue(); + + SBValue result; + value_sp = ValueObjectRegister::Create(frame, reg_ctx, reg_info); + result.SetSP(value_sp); + return result; } @@ -1000,58 +1001,55 @@ lldb::SBValue SBFrame::EvaluateExpression(const char *expr, const SBExpressionOptions &options) { LLDB_INSTRUMENT_VA(this, expr, options); - Log *expr_log = GetLog(LLDBLog::Expressions); - - SBValue expr_result; + auto LogResult = [](SBValue expr_result) { + Log *expr_log = GetLog(LLDBLog::Expressions); + if (expr_result.GetError().Success()) + LLDB_LOGF(expr_log, + "** [SBFrame::EvaluateExpression] Expression result is " + "%s, summary %s **", + expr_result.GetValue(), expr_result.GetSummary()); + else + LLDB_LOGF( + expr_log, + "** [SBFrame::EvaluateExpression] Expression evaluation failed: " + "%s **", + expr_result.GetError().GetCString()); + }; if (expr == nullptr || expr[0] == '\0') { - return expr_result; + return SBValue(); } - ValueObjectSP expr_value_sp; - llvm::Expected<StoppedExecutionContext> exe_ctx = GetStoppedExecutionContext(m_opaque_sp); if (!exe_ctx) { LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}"); - expr_result = CreateProcessIsRunningExprEvalError(); - } else { - Target *target = exe_ctx->GetTargetPtr(); - Process *process = exe_ctx->GetProcessPtr(); - if (target && process) { // FIXME: this check is redundant. - if (StackFrame *frame = exe_ctx->GetFramePtr()) { - std::unique_ptr<llvm::PrettyStackTraceFormat> stack_trace; - if (target->GetDisplayExpressionsInCrashlogs()) { - StreamString frame_description; - frame->DumpUsingSettingsFormat(&frame_description); - stack_trace = std::make_unique<llvm::PrettyStackTraceFormat>( - "SBFrame::EvaluateExpression (expr = \"%s\", fetch_dynamic_value " - "= %u) %s", - expr, options.GetFetchDynamicValue(), - frame_description.GetData()); - } + SBValue error_result = CreateProcessIsRunningExprEvalError(); + LogResult(error_result); + return error_result; + } - target->EvaluateExpression(expr, frame, expr_value_sp, options.ref()); - expr_result.SetSP(expr_value_sp, options.GetFetchDynamicValue()); - } - } else { - Status error; - error = Status::FromErrorString("sbframe object is not valid."); - expr_value_sp = ValueObjectConstResult::Create(nullptr, std::move(error)); - expr_result.SetSP(expr_value_sp, false); - } + StackFrame *frame = exe_ctx->GetFramePtr(); + if (!frame) + return SBValue(); + + std::unique_ptr<llvm::PrettyStackTraceFormat> stack_trace; + Target *target = exe_ctx->GetTargetPtr(); + if (target->GetDisplayExpressionsInCrashlogs()) { + StreamString frame_description; + frame->DumpUsingSettingsFormat(&frame_description); + stack_trace = std::make_unique<llvm::PrettyStackTraceFormat>( + "SBFrame::EvaluateExpression (expr = \"%s\", fetch_dynamic_value " + "= %u) %s", + expr, options.GetFetchDynamicValue(), frame_description.GetData()); } - if (expr_result.GetError().Success()) - LLDB_LOGF(expr_log, - "** [SBFrame::EvaluateExpression] Expression result is " - "%s, summary %s **", - expr_result.GetValue(), expr_result.GetSummary()); - else - LLDB_LOGF(expr_log, - "** [SBFrame::EvaluateExpression] Expression evaluation failed: " - "%s **", - expr_result.GetError().GetCString()); + ValueObjectSP expr_value_sp; + target->EvaluateExpression(expr, frame, expr_value_sp, options.ref()); + + SBValue expr_result; + expr_result.SetSP(expr_value_sp, options.GetFetchDynamicValue()); + LogResult(expr_result); return expr_result; } >From 7c3779816ca48a4ced20573d57052b89bc6cfa3e Mon Sep 17 00:00:00 2001 From: Felipe de Azevedo Piovezan <[email protected]> Date: Tue, 12 Aug 2025 13:56:12 -0700 Subject: [PATCH 2/3] fixup! Move FetchRecognizedArguments out of SB header --- lldb/include/lldb/API/SBFrame.h | 7 ------- lldb/source/API/SBFrame.cpp | 31 +++++++++++++++++-------------- 2 files changed, 17 insertions(+), 21 deletions(-) diff --git a/lldb/include/lldb/API/SBFrame.h b/lldb/include/lldb/API/SBFrame.h index 59a7343f9eaf3..69636822b2c57 100644 --- a/lldb/include/lldb/API/SBFrame.h +++ b/lldb/include/lldb/API/SBFrame.h @@ -253,13 +253,6 @@ class LLDB_API SBFrame { const lldb::SBVariablesOptions &options, lldb_private::StackFrame &frame, SBValueList &value_list, lldb_private::Debugger &dbg); - /// Populates `value_list` with recognized arguments of `frame` according to - /// `options`. - static void FetchRecognizedArguments(const SBVariablesOptions &options, - lldb_private::StackFrame &frame, - SBTarget target, - SBValueList &value_list); - lldb::ExecutionContextRefSP m_opaque_sp; }; diff --git a/lldb/source/API/SBFrame.cpp b/lldb/source/API/SBFrame.cpp index ed09fd2f2f90d..29f72b4d68acb 100644 --- a/lldb/source/API/SBFrame.cpp +++ b/lldb/source/API/SBFrame.cpp @@ -762,26 +762,23 @@ SBFrame::WasInterrupted SBFrame::FetchVariablesUnlessInterrupted( return WasInterrupted::No; } -void SBFrame::FetchRecognizedArguments(const SBVariablesOptions &options, - StackFrame &frame, SBTarget target, - SBValueList &value_list) { +/// Populates `value_list` with recognized arguments of `frame` according to +/// `options`. +static llvm::SmallVector<ValueObjectSP> +FetchRecognizedArguments(const SBVariablesOptions &options, StackFrame &frame, + SBTarget target) { if (!options.GetIncludeRecognizedArguments(target)) - return; + return {}; RecognizedStackFrameSP recognized_frame = frame.GetRecognizedFrame(); if (!recognized_frame) - return; + return {}; ValueObjectListSP recognized_arg_list = recognized_frame->GetRecognizedArguments(); if (!recognized_arg_list) - return; + return {}; - const lldb::DynamicValueType use_dynamic = options.GetUseDynamic(); - for (auto &rec_value_sp : recognized_arg_list->GetObjects()) { - SBValue value_sb; - value_sb.SetSP(rec_value_sp, use_dynamic); - value_list.Append(value_sb); - } + return llvm::to_vector(recognized_arg_list->GetObjects()); } SBValueList SBFrame::GetVariables(const lldb::SBVariablesOptions &options) { @@ -804,8 +801,14 @@ SBValueList SBFrame::GetVariables(const lldb::SBVariablesOptions &options) { exe_ctx->GetTargetPtr()->GetDebugger())) return value_list; - FetchRecognizedArguments(options, *frame, SBTarget(exe_ctx->GetTargetSP()), - value_list); + const lldb::DynamicValueType use_dynamic = options.GetUseDynamic(); + llvm::SmallVector<ValueObjectSP> args = FetchRecognizedArguments( + options, *frame, SBTarget(exe_ctx->GetTargetSP())); + for (ValueObjectSP arg : args) { + SBValue value_sb; + value_sb.SetSP(arg, use_dynamic); + value_list.Append(value_sb); + } return value_list; } >From 85554976d322e7e26357f96648c58420fa9d4e55 Mon Sep 17 00:00:00 2001 From: Felipe de Azevedo Piovezan <[email protected]> Date: Thu, 14 Aug 2025 11:27:02 -0700 Subject: [PATCH 3/3] fixup! Remove all changes from SBFrame.h --- lldb/include/lldb/API/SBFrame.h | 12 ----------- lldb/source/API/SBFrame.cpp | 38 ++++++++++++++++++++++----------- 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/lldb/include/lldb/API/SBFrame.h b/lldb/include/lldb/API/SBFrame.h index 69636822b2c57..5283cdfe53faa 100644 --- a/lldb/include/lldb/API/SBFrame.h +++ b/lldb/include/lldb/API/SBFrame.h @@ -13,8 +13,6 @@ #include "lldb/API/SBValueList.h" namespace lldb_private { -class StackFrame; -class Debugger; namespace python { class SWIGBridge; } @@ -243,16 +241,6 @@ class LLDB_API SBFrame { /// not currently stopped. static SBValue CreateProcessIsRunningExprEvalError(); - enum WasInterrupted { Yes, No }; - - /// Populates `value_list` with the variables from `frame` according to - /// `options`. This method checks whether the Debugger received an interrupt - /// before processing every variable, returning `WasInterrupted::yes` in that - /// case. - static WasInterrupted FetchVariablesUnlessInterrupted( - const lldb::SBVariablesOptions &options, lldb_private::StackFrame &frame, - SBValueList &value_list, lldb_private::Debugger &dbg); - lldb::ExecutionContextRefSP m_opaque_sp; }; diff --git a/lldb/source/API/SBFrame.cpp b/lldb/source/API/SBFrame.cpp index 29f72b4d68acb..31947a054aaaf 100644 --- a/lldb/source/API/SBFrame.cpp +++ b/lldb/source/API/SBFrame.cpp @@ -705,9 +705,16 @@ static bool IsInRequestedScope(bool statics, bool arguments, bool locals, return false; } -SBFrame::WasInterrupted SBFrame::FetchVariablesUnlessInterrupted( +enum WasInterrupted { Yes, No }; + +/// Populates `value_list` with the variables from `frame` according to +/// `options`. This method checks whether the Debugger received an interrupt +/// before processing every variable, returning `WasInterrupted::yes` in that +/// case. +static std::pair<WasInterrupted, Status> FetchVariablesUnlessInterrupted( const lldb::SBVariablesOptions &options, StackFrame &frame, - SBValueList &value_list, Debugger &dbg) { + SBValueList &value_list, Debugger &dbg, + std::function<SBValue(ValueObjectSP, bool)> to_sbvalue) { const bool statics = options.GetIncludeStatics(); const bool arguments = options.GetIncludeArguments(); const bool locals = options.GetIncludeLocals(); @@ -721,11 +728,8 @@ SBFrame::WasInterrupted SBFrame::FetchVariablesUnlessInterrupted( std::set<VariableSP> variable_set; - if (var_error.Fail()) - value_list.SetError(std::move(var_error)); - if (!variable_list) - return WasInterrupted::No; + return {WasInterrupted::No, std::move(var_error)}; const size_t num_variables = variable_list->GetSize(); size_t num_produced = 0; for (const VariableSP &variable_sp : *variable_list) { @@ -738,7 +742,7 @@ SBFrame::WasInterrupted SBFrame::FetchVariablesUnlessInterrupted( "Interrupted getting frame variables with {0} of {1} " "produced.", num_produced, num_variables)) - return WasInterrupted::Yes; + return {WasInterrupted::Yes, std::move(var_error)}; // Only add variables once so we don't end up with duplicates if (variable_set.insert(variable_sp).second == false) @@ -753,13 +757,11 @@ SBFrame::WasInterrupted SBFrame::FetchVariablesUnlessInterrupted( valobj_sp->IsRuntimeSupportValue()) continue; - SBValue value_sb; - value_sb.SetSP(valobj_sp, use_dynamic); - value_list.Append(value_sb); + value_list.Append(to_sbvalue(valobj_sp, use_dynamic)); } num_produced++; - return WasInterrupted::No; + return {WasInterrupted::No, std::move(var_error)}; } /// Populates `value_list` with recognized arguments of `frame` according to @@ -795,10 +797,20 @@ SBValueList SBFrame::GetVariables(const lldb::SBVariablesOptions &options) { if (!frame) return SBValueList(); + auto valobj_to_sbvalue = [](ValueObjectSP valobj, bool use_dynamic) { + SBValue value_sb; + value_sb.SetSP(valobj, use_dynamic); + return value_sb; + }; SBValueList value_list; - if (WasInterrupted::Yes == + std::pair<WasInterrupted, Status> fetch_result = FetchVariablesUnlessInterrupted(options, *frame, value_list, - exe_ctx->GetTargetPtr()->GetDebugger())) + exe_ctx->GetTargetPtr()->GetDebugger(), + valobj_to_sbvalue); + if (fetch_result.second.Fail()) + value_list.SetError(std::move(fetch_result.second)); + + if (fetch_result.first == WasInterrupted::Yes) return value_list; const lldb::DynamicValueType use_dynamic = options.GetUseDynamic(); _______________________________________________ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
