diff --git a/lldb/source/Commands/CommandObjectDWIMPrint.cpp b/lldb/source/Commands/CommandObjectDWIMPrint.cpp --- a/lldb/source/Commands/CommandObjectDWIMPrint.cpp +++ b/lldb/source/Commands/CommandObjectDWIMPrint.cpp @@ -22,12 +22,11 @@ using namespace lldb_private; CommandObjectDWIMPrint::CommandObjectDWIMPrint(CommandInterpreter &interpreter) - : CommandObjectRaw( - interpreter, "dwim-print", "Print a variable or expression.", - "dwim-print [ | ]", - eCommandProcessMustBePaused | eCommandTryTargetAPILock | - eCommandRequiresFrame | eCommandProcessMustBeLaunched | - eCommandRequiresProcess) {} + : CommandObjectRaw(interpreter, "dwim-print", + "Print a variable or expression.", + "dwim-print [ | ]", + eCommandProcessMustBePaused | eCommandTryTargetAPILock) { +} bool CommandObjectDWIMPrint::DoExecute(StringRef expr, CommandReturnObject &result) { @@ -40,14 +39,10 @@ return false; } - // eCommandRequiresFrame guarantees a frame. - StackFrame *frame = m_exe_ctx.GetFramePtr(); - assert(frame); - auto verbosity = GetDebugger().GetDWIMPrintVerbosity(); - // First, try `expr` as the name of a variable. - { + // First, try `expr` as the name of a frame variable. + if (StackFrame *frame = m_exe_ctx.GetFramePtr()) { auto valobj_sp = frame->FindVariable(ConstString(expr)); if (valobj_sp && valobj_sp->GetError().Success()) { if (verbosity == eDWIMPrintVerbosityFull) @@ -60,12 +55,13 @@ // Second, also lastly, try `expr` as a source expression to evaluate. { - // eCommandRequiresProcess guarantees a target. - Target *target = m_exe_ctx.GetTargetPtr(); - assert(target); + Target *target_ptr = m_exe_ctx.GetTargetPtr(); + // Fallback to the dummy target, which can allow for expression evaluation. + Target &target = target_ptr ? *target_ptr : GetDummyTarget(); + auto *exe_scope = m_exe_ctx.GetBestExecutionContextScope(); ValueObjectSP valobj_sp; - if (target->EvaluateExpression(expr, frame, valobj_sp) == + if (target.EvaluateExpression(expr, exe_scope, valobj_sp) == eExpressionCompleted) { if (verbosity != eDWIMPrintVerbosityNone) result.AppendMessageWithFormatv("note: ran `expression -- {0}`", expr); diff --git a/lldb/test/API/commands/dwim-print/TestDWIMPrint.py b/lldb/test/API/commands/dwim-print/TestDWIMPrint.py --- a/lldb/test/API/commands/dwim-print/TestDWIMPrint.py +++ b/lldb/test/API/commands/dwim-print/TestDWIMPrint.py @@ -10,11 +10,6 @@ class TestCase(TestBase): - def setUp(self): - TestBase.setUp(self) - self.build() - lldbutil.run_to_name_breakpoint(self, "main") - def _run_cmd(self, cmd: str) -> str: """Run the given lldb command and return its output.""" result = lldb.SBCommandReturnObject() @@ -51,18 +46,28 @@ def test_variables(self): """Test dwim-print with variables.""" + self.build() + lldbutil.run_to_name_breakpoint(self, "main") vars = ("argc", "argv") for var in vars: self._expect_cmd(var, "frame variable") def test_variable_paths(self): """Test dwim-print with variable path expressions.""" + self.build() + lldbutil.run_to_name_breakpoint(self, "main") exprs = ("&argc", "*argv", "argv[0]") for expr in exprs: self._expect_cmd(expr, "expression --") def test_expressions(self): """Test dwim-print with expressions.""" + self.build() + lldbutil.run_to_name_breakpoint(self, "main") exprs = ("argc + 1", "(void)argc", "(int)abs(argc)") for expr in exprs: self._expect_cmd(expr, "expression --") + + def test_dummy_target_expressions(self): + """Test dwim-print's ability to evaluate expressions without a target.""" + self._expect_cmd("1 + 2", "expression --")