Skip to content

Commit 98f8acf

Browse files
Merge pull request #6887 from apple/dl/lldb-delay-removal-of-persistent-results
[lldb] Delay removal of persistent results
2 parents 06707b3 + 14efe18 commit 98f8acf

File tree

6 files changed

+100
-13
lines changed

6 files changed

+100
-13
lines changed

lldb/source/Commands/CommandObjectDWIMPrint.cpp

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
#include "lldb/Core/ValueObject.h"
1212
#include "lldb/DataFormatters/DumpValueObjectOptions.h"
13+
#include "lldb/Expression/ExpressionVariable.h"
1314
#include "lldb/Interpreter/CommandInterpreter.h"
1415
#include "lldb/Interpreter/CommandObject.h"
1516
#include "lldb/Interpreter/CommandReturnObject.h"
@@ -78,28 +79,34 @@ bool CommandObjectDWIMPrint::DoExecute(StringRef command,
7879
// If the user has not specified, default to disabling persistent results.
7980
if (m_expr_options.suppress_persistent_result == eLazyBoolCalculate)
8081
m_expr_options.suppress_persistent_result = eLazyBoolYes;
82+
bool suppress_result = m_expr_options.ShouldSuppressResult(m_varobj_options);
8183

8284
auto verbosity = GetDebugger().GetDWIMPrintVerbosity();
8385

8486
Target *target_ptr = m_exe_ctx.GetTargetPtr();
8587
// Fallback to the dummy target, which can allow for expression evaluation.
8688
Target &target = target_ptr ? *target_ptr : GetDummyTarget();
8789

88-
const EvaluateExpressionOptions eval_options =
90+
EvaluateExpressionOptions eval_options =
8991
m_expr_options.GetEvaluateExpressionOptions(target, m_varobj_options);
92+
// This command manually removes the result variable, make sure expression
93+
// evaluation doesn't do it first.
94+
eval_options.SetSuppressPersistentResult(false);
9095

9196
DumpValueObjectOptions dump_options = m_varobj_options.GetAsDumpOptions(
9297
m_expr_options.m_verbosity, m_format_options.GetFormat());
93-
dump_options.SetHideRootName(eval_options.GetSuppressPersistentResult());
98+
dump_options.SetHideRootName(suppress_result);
9499

95100
StackFrame *frame = m_exe_ctx.GetFramePtr();
96101

97102
// First, try `expr` as the name of a frame variable.
98103
if (frame) {
99104
auto valobj_sp = frame->FindVariable(ConstString(expr));
100105
if (valobj_sp && valobj_sp->GetError().Success()) {
101-
if (!eval_options.GetSuppressPersistentResult())
102-
valobj_sp = valobj_sp->Persist();
106+
if (!suppress_result) {
107+
if (auto persisted_valobj = valobj_sp->Persist())
108+
valobj_sp = persisted_valobj;
109+
}
103110

104111
if (verbosity == eDWIMPrintVerbosityFull) {
105112
StringRef flags;
@@ -172,6 +179,16 @@ bool CommandObjectDWIMPrint::DoExecute(StringRef command,
172179
}
173180

174181
valobj_sp->Dump(result.GetOutputStream(), dump_options);
182+
183+
if (suppress_result)
184+
if (auto result_var_sp =
185+
target.GetPersistentVariable(valobj_sp->GetName())) {
186+
auto language = valobj_sp->GetPreferredDisplayLanguage();
187+
if (auto *persistent_state =
188+
target.GetPersistentExpressionStateForLanguage(language))
189+
persistent_state->RemovePersistentVariable(result_var_sp);
190+
}
191+
175192
result.SetStatus(eReturnStatusSuccessFinishResult);
176193
return true;
177194
} else {

lldb/source/Commands/CommandObjectExpression.cpp

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
#include "CommandObjectExpression.h"
1212
#include "lldb/Core/Debugger.h"
13+
#include "lldb/Expression/ExpressionVariable.h"
1314
#include "lldb/Expression/REPL.h"
1415
#include "lldb/Expression/UserExpression.h"
1516
#include "lldb/Host/OptionParser.h"
@@ -21,6 +22,7 @@
2122
#include "lldb/Target/Process.h"
2223
#include "lldb/Target/StackFrame.h"
2324
#include "lldb/Target/Target.h"
25+
#include "lldb/lldb-enumerations.h"
2426
#include "lldb/lldb-private-enumerations.h"
2527

2628
// BEGIN SWIFT
@@ -218,13 +220,6 @@ CommandObjectExpression::CommandOptions::GetEvaluateExpressionOptions(
218220
const Target &target, const OptionGroupValueObjectDisplay &display_opts) {
219221
EvaluateExpressionOptions options;
220222
options.SetCoerceToId(display_opts.use_objc);
221-
// Explicitly disabling persistent results takes precedence over the
222-
// m_verbosity/use_objc logic.
223-
if (suppress_persistent_result != eLazyBoolCalculate)
224-
options.SetSuppressPersistentResult(suppress_persistent_result ==
225-
eLazyBoolYes);
226-
else if (m_verbosity == eLanguageRuntimeDescriptionDisplayVerbosityCompact)
227-
options.SetSuppressPersistentResult(display_opts.use_objc);
228223
options.SetUnwindOnError(unwind_on_error);
229224
options.SetIgnoreBreakpoints(ignore_breakpoints);
230225
options.SetKeepInMemory(true);
@@ -272,6 +267,17 @@ CommandObjectExpression::CommandOptions::GetEvaluateExpressionOptions(
272267
return options;
273268
}
274269

270+
bool CommandObjectExpression::CommandOptions::ShouldSuppressResult(
271+
const OptionGroupValueObjectDisplay &display_opts) const {
272+
// Explicitly disabling persistent results takes precedence over the
273+
// m_verbosity/use_objc logic.
274+
if (suppress_persistent_result != eLazyBoolCalculate)
275+
return suppress_persistent_result == eLazyBoolYes;
276+
277+
return display_opts.use_objc &&
278+
m_verbosity == eLanguageRuntimeDescriptionDisplayVerbosityCompact;
279+
}
280+
275281
CommandObjectExpression::CommandObjectExpression(
276282
CommandInterpreter &interpreter)
277283
: CommandObjectRaw(interpreter, "expression",
@@ -456,8 +462,12 @@ bool CommandObjectExpression::EvaluateExpression(llvm::StringRef expr,
456462
return false;
457463
}
458464

459-
const EvaluateExpressionOptions eval_options =
465+
EvaluateExpressionOptions eval_options =
460466
m_command_options.GetEvaluateExpressionOptions(target, m_varobj_options);
467+
// This command manually removes the result variable, make sure expression
468+
// evaluation doesn't do it first.
469+
eval_options.SetSuppressPersistentResult(false);
470+
461471
ExpressionResults success = target.EvaluateExpression(
462472
expr, frame, result_valobj_sp, eval_options, &m_fixed_expression);
463473

@@ -486,14 +496,25 @@ bool CommandObjectExpression::EvaluateExpression(llvm::StringRef expr,
486496
}
487497
}
488498

499+
bool suppress_result =
500+
m_command_options.ShouldSuppressResult(m_varobj_options);
501+
489502
DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions(
490503
m_command_options.m_verbosity, format));
491-
options.SetHideRootName(eval_options.GetSuppressPersistentResult());
504+
options.SetHideRootName(suppress_result);
492505
options.SetVariableFormatDisplayLanguage(
493506
result_valobj_sp->GetPreferredDisplayLanguage());
494507

495508
result_valobj_sp->Dump(output_stream, options);
496509

510+
if (suppress_result)
511+
if (auto result_var_sp =
512+
target.GetPersistentVariable(result_valobj_sp->GetName())) {
513+
auto language = result_valobj_sp->GetPreferredDisplayLanguage();
514+
if (auto *persistent_state =
515+
target.GetPersistentExpressionStateForLanguage(language))
516+
persistent_state->RemovePersistentVariable(result_var_sp);
517+
}
497518
result.SetStatus(eReturnStatusSuccessFinishResult);
498519
}
499520
} else {

lldb/source/Commands/CommandObjectExpression.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ class CommandObjectExpression : public CommandObjectRaw,
4141
const Target &target,
4242
const OptionGroupValueObjectDisplay &display_opts);
4343

44+
bool ShouldSuppressResult(
45+
const OptionGroupValueObjectDisplay &display_opts) const;
46+
4447
bool top_level;
4548
bool unwind_on_error;
4649
bool ignore_breakpoints;
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
SWIFT_SOURCES := main.swift
2+
3+
include Makefile.rules
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
"""
2+
Test controlling `expression` result variables are persistent.
3+
"""
4+
5+
import lldb
6+
from lldbsuite.test.lldbtest import *
7+
from lldbsuite.test.decorators import *
8+
from lldbsuite.test import lldbutil
9+
10+
11+
class TestCase(TestBase):
12+
def setUp(self):
13+
TestBase.setUp(self)
14+
self.build()
15+
lldbutil.run_to_source_breakpoint(self, "break here", lldb.SBFileSpec("main.swift"))
16+
17+
def test_enable_persistent_result(self):
18+
"""Test explicitly enabling result variables persistence."""
19+
self.expect("expression --persistent-result on -- i", startstr="(Int) $R0 = 30")
20+
# Verify the lifetime of $R0 extends beyond the `expression` it was created in.
21+
self.expect("expression $R0", startstr="(Int) $R1 = 30")
22+
23+
def test_disable_persistent_result(self):
24+
"""Test explicitly disabling persistent result variables."""
25+
self.expect("expression --persistent-result off -- i", startstr="(Int) 30")
26+
# Verify a persistent result was not silently created.
27+
self.expect("expression $R0", error=True)
28+
29+
def test_expression_persists_result(self):
30+
"""Test `expression`'s default behavior is to persist a result variable."""
31+
self.expect("expression i", startstr="(Int) $R0 = 30")
32+
self.expect("expression $R0", startstr="(Int) $R1 = 30")
33+
34+
def test_p_does_not_persist_results(self):
35+
"""Test `p` does not persist a result variable."""
36+
self.expect("p i", startstr="(Int) 30")
37+
self.expect("p $R0", error=True)
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
func main() {
2+
var i = 30
3+
print("break here")
4+
}
5+
6+
main()

0 commit comments

Comments
 (0)