Skip to content

Commit 0b3a9bc

Browse files
authored
Merge pull request #6306 from apple/dl/expression-dwim-print-updates
[lldb] Cherry pick expression and dwim-print updates
2 parents 64e3309 + 2ac7c4c commit 0b3a9bc

File tree

22 files changed

+263
-86
lines changed

22 files changed

+263
-86
lines changed

lldb/include/lldb/Interpreter/Options.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "lldb/lldb-private.h"
2121

2222
#include "llvm/ADT/ArrayRef.h"
23+
#include "llvm/ADT/StringRef.h"
2324

2425
namespace lldb_private {
2526

@@ -290,6 +291,21 @@ class OptionGroupOptions : public Options {
290291
/// copying the option definition.
291292
void Append(OptionGroup *group, uint32_t src_mask, uint32_t dst_mask);
292293

294+
/// Append selected options from a OptionGroup class.
295+
///
296+
/// Append the subset of options from \a group, where the "long_option" value
297+
/// is _not_ in \a exclude_long_options.
298+
///
299+
/// \param[in] group
300+
/// A group of options to take option values from and copy their
301+
/// definitions into this class.
302+
///
303+
/// \param[in] exclude_long_options
304+
/// A set of long option strings which indicate which option values values
305+
/// to limit from \a group.
306+
void Append(OptionGroup *group,
307+
llvm::ArrayRef<llvm::StringRef> exclude_long_options);
308+
293309
void Finalize();
294310

295311
bool DidFinalize() { return m_did_finalize; }

lldb/include/lldb/Target/Target.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -478,9 +478,11 @@ class EvaluateExpressionOptions {
478478

479479
uint32_t GetExpressionNumber() const;
480480

481-
void SetResultIsInternal(bool b) { m_result_is_internal = b; }
481+
void SetSuppressPersistentResult(bool b) { m_suppress_persistent_result = b; }
482482

483-
bool GetResultIsInternal() const { return m_result_is_internal; }
483+
bool GetSuppressPersistentResult() const {
484+
return m_suppress_persistent_result;
485+
}
484486

485487
void SetAutoApplyFixIts(bool b) { m_auto_apply_fixits = b; }
486488

@@ -517,7 +519,7 @@ class EvaluateExpressionOptions {
517519
bool m_playground_transforms_hp = true;
518520
bool m_generate_debug_info = false;
519521
bool m_ansi_color_errors = false;
520-
bool m_result_is_internal = false;
522+
bool m_suppress_persistent_result = false;
521523
bool m_auto_apply_fixits = true;
522524
uint64_t m_retries_with_fixits = 1;
523525
/// True if the executed code should be treated as utility code that is only

lldb/source/API/SBExpressionOptions.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -212,13 +212,13 @@ void SBExpressionOptions::SetGenerateDebugInfo(bool b) {
212212
bool SBExpressionOptions::GetSuppressPersistentResult() {
213213
LLDB_INSTRUMENT_VA(this);
214214

215-
return m_opaque_up->GetResultIsInternal();
215+
return m_opaque_up->GetSuppressPersistentResult();
216216
}
217217

218218
void SBExpressionOptions::SetSuppressPersistentResult(bool b) {
219219
LLDB_INSTRUMENT_VA(this, b);
220220

221-
return m_opaque_up->SetResultIsInternal(b);
221+
return m_opaque_up->SetSuppressPersistentResult(b);
222222
}
223223

224224
const char *SBExpressionOptions::GetPrefix() const {

lldb/source/Breakpoint/BreakpointLocation.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,7 @@ bool BreakpointLocation::ConditionSaysStop(ExecutionContext &exe_ctx,
290290
options.SetUnwindOnError(true);
291291
options.SetIgnoreBreakpoints(true);
292292
options.SetTryAllThreads(true);
293-
options.SetResultIsInternal(
293+
options.SetSuppressPersistentResult(
294294
true); // Don't generate a user variable for condition expressions.
295295

296296
Status expr_error;

lldb/source/Commands/CommandObjectDWIMPrint.cpp

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ CommandObjectDWIMPrint::CommandObjectDWIMPrint(CommandInterpreter &interpreter)
3636
OptionGroupFormat::OPTION_GROUP_FORMAT |
3737
OptionGroupFormat::OPTION_GROUP_GDB_FMT,
3838
LLDB_OPT_SET_1);
39+
StringRef exclude_expr_options[] = {"debug", "top-level"};
40+
m_option_group.Append(&m_expr_options, exclude_expr_options);
3941
m_option_group.Append(&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
4042
m_option_group.Finalize();
4143
}
@@ -57,23 +59,35 @@ bool CommandObjectDWIMPrint::DoExecute(StringRef command,
5759
m_cmd_name);
5860
return false;
5961
}
62+
6063
auto verbosity = GetDebugger().GetDWIMPrintVerbosity();
6164

65+
Target *target_ptr = m_exe_ctx.GetTargetPtr();
66+
// Fallback to the dummy target, which can allow for expression evaluation.
67+
Target &target = target_ptr ? *target_ptr : GetDummyTarget();
68+
69+
const EvaluateExpressionOptions eval_options =
70+
m_expr_options.GetEvaluateExpressionOptions(target, m_varobj_options);
71+
6272
DumpValueObjectOptions dump_options = m_varobj_options.GetAsDumpOptions(
63-
eLanguageRuntimeDescriptionDisplayVerbosityFull,
64-
m_format_options.GetFormat());
73+
m_expr_options.m_verbosity, m_format_options.GetFormat());
74+
dump_options.SetHideName(eval_options.GetSuppressPersistentResult());
6575

6676
// First, try `expr` as the name of a frame variable.
6777
if (StackFrame *frame = m_exe_ctx.GetFramePtr()) {
6878
auto valobj_sp = frame->FindVariable(ConstString(expr));
6979
if (valobj_sp && valobj_sp->GetError().Success()) {
80+
if (!eval_options.GetSuppressPersistentResult())
81+
valobj_sp = valobj_sp->Persist();
82+
7083
if (verbosity == eDWIMPrintVerbosityFull) {
7184
StringRef flags;
7285
if (args.HasArgs())
7386
flags = args.GetArgString();
7487
result.AppendMessageWithFormatv("note: ran `frame variable {0}{1}`",
7588
flags, expr);
7689
}
90+
7791
valobj_sp->Dump(result.GetOutputStream(), dump_options);
7892
result.SetStatus(eReturnStatusSuccessFinishResult);
7993
return true;
@@ -82,21 +96,19 @@ bool CommandObjectDWIMPrint::DoExecute(StringRef command,
8296

8397
// Second, also lastly, try `expr` as a source expression to evaluate.
8498
{
85-
Target *target_ptr = m_exe_ctx.GetTargetPtr();
86-
// Fallback to the dummy target, which can allow for expression evaluation.
87-
Target &target = target_ptr ? *target_ptr : GetDummyTarget();
88-
8999
auto *exe_scope = m_exe_ctx.GetBestExecutionContextScope();
90100
ValueObjectSP valobj_sp;
91-
if (target.EvaluateExpression(expr, exe_scope, valobj_sp) ==
92-
eExpressionCompleted) {
101+
ExpressionResults expr_result =
102+
target.EvaluateExpression(expr, exe_scope, valobj_sp, eval_options);
103+
if (expr_result == eExpressionCompleted) {
93104
if (verbosity != eDWIMPrintVerbosityNone) {
94105
StringRef flags;
95106
if (args.HasArgs())
96107
flags = args.GetArgStringWithDelimiter();
97108
result.AppendMessageWithFormatv("note: ran `expression {0}{1}`", flags,
98109
expr);
99110
}
111+
100112
valobj_sp->Dump(result.GetOutputStream(), dump_options);
101113
result.SetStatus(eReturnStatusSuccessFinishResult);
102114
return true;

lldb/source/Commands/CommandObjectDWIMPrint.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#ifndef LLDB_SOURCE_COMMANDS_COMMANDOBJECTDWIMPRINT_H
1010
#define LLDB_SOURCE_COMMANDS_COMMANDOBJECTDWIMPRINT_H
1111

12+
#include "CommandObjectExpression.h"
1213
#include "lldb/Interpreter/CommandObject.h"
1314
#include "lldb/Interpreter/OptionGroupFormat.h"
1415
#include "lldb/Interpreter/OptionGroupValueObjectDisplay.h"
@@ -42,6 +43,7 @@ class CommandObjectDWIMPrint : public CommandObjectRaw {
4243
OptionGroupOptions m_option_group;
4344
OptionGroupFormat m_format_options = lldb::eFormatDefault;
4445
OptionGroupValueObjectDisplay m_varobj_options;
46+
CommandObjectExpression::CommandOptions m_expr_options;
4547
};
4648

4749
} // namespace lldb_private

lldb/source/Commands/CommandObjectExpression.cpp

Lines changed: 78 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "lldb/Target/Process.h"
2222
#include "lldb/Target/StackFrame.h"
2323
#include "lldb/Target/Target.h"
24+
#include "lldb/lldb-private-enumerations.h"
2425

2526
// BEGIN SWIFT
2627
#include "lldb/Symbol/CompileUnit.h"
@@ -144,8 +145,21 @@ Status CommandObjectExpression::CommandOptions::SetOptionValue(
144145
break;
145146
}
146147

147-
// BEGIN SWIFT
148148
case '\x01': {
149+
bool success;
150+
bool persist_result =
151+
OptionArgParser::ToBoolean(option_arg, true, &success);
152+
if (success)
153+
suppress_persistent_result = !persist_result;
154+
else
155+
error.SetErrorStringWithFormat(
156+
"could not convert \"%s\" to a boolean value.",
157+
option_arg.str().c_str());
158+
break;
159+
}
160+
161+
// BEGIN SWIFT
162+
case '\x31': {
149163
int32_t result;
150164
result = OptionArgParser::ToOptionEnum(option_arg, BindGenTypeParamValue(),
151165
0, error);
@@ -183,6 +197,7 @@ void CommandObjectExpression::CommandOptions::OptionParsingStarting(
183197
auto_apply_fixits = eLazyBoolCalculate;
184198
top_level = false;
185199
allow_jit = true;
200+
suppress_persistent_result = false;
186201
// BEGIN SWIFT
187202
bind_generic_types = eBindAuto;
188203
// END SWIFT
@@ -193,6 +208,64 @@ CommandObjectExpression::CommandOptions::GetDefinitions() {
193208
return llvm::makeArrayRef(g_expression_options);
194209
}
195210

211+
EvaluateExpressionOptions
212+
CommandObjectExpression::CommandOptions::GetEvaluateExpressionOptions(
213+
const Target &target, const OptionGroupValueObjectDisplay &display_opts) {
214+
EvaluateExpressionOptions options;
215+
options.SetCoerceToId(display_opts.use_objc);
216+
// Explicitly disabling persistent results takes precedence over the
217+
// m_verbosity/use_objc logic.
218+
if (suppress_persistent_result)
219+
options.SetSuppressPersistentResult(true);
220+
else if (m_verbosity == eLanguageRuntimeDescriptionDisplayVerbosityCompact)
221+
options.SetSuppressPersistentResult(display_opts.use_objc);
222+
options.SetUnwindOnError(unwind_on_error);
223+
options.SetIgnoreBreakpoints(ignore_breakpoints);
224+
options.SetKeepInMemory(true);
225+
options.SetUseDynamic(display_opts.use_dynamic);
226+
options.SetTryAllThreads(try_all_threads);
227+
options.SetDebug(debug);
228+
229+
// BEGIN SWIFT
230+
options.SetBindGenericTypes(bind_generic_types);
231+
// If the language was not specified in the expression command,
232+
// set it to the language in the target's properties if
233+
// specified, else default to the language for the frame.
234+
if (language != eLanguageTypeUnknown) {
235+
// END SWIFT
236+
options.SetLanguage(language);
237+
// BEGIN SWIFT
238+
}
239+
// END SWIFT
240+
241+
options.SetExecutionPolicy(
242+
allow_jit ? EvaluateExpressionOptions::default_execution_policy
243+
: lldb_private::eExecutionPolicyNever);
244+
245+
bool auto_apply_fixits;
246+
if (this->auto_apply_fixits == eLazyBoolCalculate)
247+
auto_apply_fixits = target.GetEnableAutoApplyFixIts();
248+
else
249+
auto_apply_fixits = this->auto_apply_fixits == eLazyBoolYes;
250+
251+
options.SetAutoApplyFixIts(auto_apply_fixits);
252+
options.SetRetriesWithFixIts(target.GetNumberOfRetriesWithFixits());
253+
254+
if (top_level)
255+
options.SetExecutionPolicy(eExecutionPolicyTopLevel);
256+
257+
// If there is any chance we are going to stop and want to see what went
258+
// wrong with our expression, we should generate debug info
259+
if (!ignore_breakpoints || !unwind_on_error)
260+
options.SetGenerateDebugInfo(true);
261+
262+
if (timeout > 0)
263+
options.SetTimeout(std::chrono::microseconds(timeout));
264+
else
265+
options.SetTimeout(std::nullopt);
266+
return options;
267+
}
268+
196269
CommandObjectExpression::CommandObjectExpression(
197270
CommandInterpreter &interpreter)
198271
: CommandObjectRaw(interpreter, "expression",
@@ -357,59 +430,6 @@ CanBeUsedForElementCountPrinting(ValueObject &valobj) {
357430
return Status();
358431
}
359432

360-
EvaluateExpressionOptions
361-
CommandObjectExpression::GetEvalOptions(const Target &target) {
362-
EvaluateExpressionOptions options;
363-
options.SetCoerceToId(m_varobj_options.use_objc);
364-
options.SetUnwindOnError(m_command_options.unwind_on_error);
365-
options.SetIgnoreBreakpoints(m_command_options.ignore_breakpoints);
366-
options.SetKeepInMemory(true);
367-
options.SetUseDynamic(m_varobj_options.use_dynamic);
368-
options.SetTryAllThreads(m_command_options.try_all_threads);
369-
options.SetDebug(m_command_options.debug);
370-
371-
// BEGIN SWIFT
372-
options.SetBindGenericTypes(m_command_options.bind_generic_types);
373-
// If the language was not specified in the expression command,
374-
// set it to the language in the target's properties if
375-
// specified, else default to the language for the frame.
376-
if (m_command_options.language != eLanguageTypeUnknown) {
377-
// END SWIFT
378-
options.SetLanguage(m_command_options.language);
379-
// BEGIN SWIFT
380-
}
381-
// END SWIFT
382-
383-
options.SetExecutionPolicy(
384-
m_command_options.allow_jit
385-
? EvaluateExpressionOptions::default_execution_policy
386-
: lldb_private::eExecutionPolicyNever);
387-
388-
bool auto_apply_fixits;
389-
if (m_command_options.auto_apply_fixits == eLazyBoolCalculate)
390-
auto_apply_fixits = target.GetEnableAutoApplyFixIts();
391-
else
392-
auto_apply_fixits = m_command_options.auto_apply_fixits == eLazyBoolYes;
393-
394-
options.SetAutoApplyFixIts(auto_apply_fixits);
395-
options.SetRetriesWithFixIts(target.GetNumberOfRetriesWithFixits());
396-
397-
if (m_command_options.top_level)
398-
options.SetExecutionPolicy(eExecutionPolicyTopLevel);
399-
400-
// If there is any chance we are going to stop and want to see what went
401-
// wrong with our expression, we should generate debug info
402-
if (!m_command_options.ignore_breakpoints ||
403-
!m_command_options.unwind_on_error)
404-
options.SetGenerateDebugInfo(true);
405-
406-
if (m_command_options.timeout > 0)
407-
options.SetTimeout(std::chrono::microseconds(m_command_options.timeout));
408-
else
409-
options.SetTimeout(llvm::None);
410-
return options;
411-
}
412-
413433
bool CommandObjectExpression::EvaluateExpression(llvm::StringRef expr,
414434
Stream &output_stream,
415435
Stream &error_stream,
@@ -430,9 +450,10 @@ bool CommandObjectExpression::EvaluateExpression(llvm::StringRef expr,
430450
return false;
431451
}
432452

433-
const EvaluateExpressionOptions options = GetEvalOptions(target);
453+
const EvaluateExpressionOptions eval_options =
454+
m_command_options.GetEvaluateExpressionOptions(target, m_varobj_options);
434455
ExpressionResults success = target.EvaluateExpression(
435-
expr, frame, result_valobj_sp, options, &m_fixed_expression);
456+
expr, frame, result_valobj_sp, eval_options, &m_fixed_expression);
436457

437458
// We only tell you about the FixIt if we applied it. The compiler errors
438459
// will suggest the FixIt if it parsed.
@@ -461,6 +482,7 @@ bool CommandObjectExpression::EvaluateExpression(llvm::StringRef expr,
461482

462483
DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions(
463484
m_command_options.m_verbosity, format));
485+
options.SetHideName(eval_options.GetSuppressPersistentResult());
464486
options.SetVariableFormatDisplayLanguage(
465487
result_valobj_sp->GetPreferredDisplayLanguage());
466488

lldb/source/Commands/CommandObjectExpression.h

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,12 @@ class CommandObjectExpression : public CommandObjectRaw,
3535

3636
void OptionParsingStarting(ExecutionContext *execution_context) override;
3737

38+
/// Return the appropriate expression options used for evaluating the
39+
/// expression in the given target.
40+
EvaluateExpressionOptions GetEvaluateExpressionOptions(
41+
const Target &target,
42+
const OptionGroupValueObjectDisplay &display_opts);
43+
3844
bool top_level;
3945
bool unwind_on_error;
4046
bool ignore_breakpoints;
@@ -47,6 +53,7 @@ class CommandObjectExpression : public CommandObjectRaw,
4753
lldb::LanguageType language;
4854
LanguageRuntimeDescriptionDisplayVerbosity m_verbosity;
4955
LazyBool auto_apply_fixits;
56+
bool suppress_persistent_result;
5057
// BEGIN SWIFT
5158
lldb::BindGenericTypes bind_generic_types;
5259
// END SWIFT
@@ -70,10 +77,6 @@ class CommandObjectExpression : public CommandObjectRaw,
7077

7178
bool DoExecute(llvm::StringRef command, CommandReturnObject &result) override;
7279

73-
/// Return the appropriate expression options used for evaluating the
74-
/// expression in the given target.
75-
EvaluateExpressionOptions GetEvalOptions(const Target &target);
76-
7780
/// Evaluates the given expression.
7881
/// \param output_stream The stream to which the evaluation result will be
7982
/// printed.

lldb/source/Commands/Options.td

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -387,8 +387,13 @@ let Command = "expression" in {
387387
Arg<"Boolean">,
388388
Desc<"Controls whether the expression can fall back to being JITted if it's "
389389
"not supported by the interpreter (defaults to true).">;
390+
def persistent_result : Option<"persistent-result", "\\x01">, Groups<[1,2]>,
391+
Arg<"Boolean">,
392+
Desc<"Persist expression result in a variable for subsequent use. "
393+
"Expression results will be labeled with $-prefixed variables, e.g. $0, "
394+
"$1, etc. Defaults to true.">;
390395
// BEGIN SWIFT
391-
def bind_generic_types : Option<"bind-generic-types", "\\x01">,
396+
def bind_generic_types : Option<"bind-generic-types", "\\x31">,
392397
EnumArg<"BindGenTypeParamValue">, Desc<"Controls whether any "
393398
"generic types in the current context should be bound to their dynamic "
394399
"type before evaluating. Defaults to auto.">;

0 commit comments

Comments
 (0)