diff --git a/lldb/source/Commands/CommandObjectDWIMPrint.h b/lldb/source/Commands/CommandObjectDWIMPrint.h --- a/lldb/source/Commands/CommandObjectDWIMPrint.h +++ b/lldb/source/Commands/CommandObjectDWIMPrint.h @@ -9,6 +9,7 @@ #ifndef LLDB_SOURCE_COMMANDS_COMMANDOBJECTDWIMPRINT_H #define LLDB_SOURCE_COMMANDS_COMMANDOBJECTDWIMPRINT_H +#include "CommandObjectExpression.h" #include "lldb/Interpreter/CommandObject.h" #include "lldb/Interpreter/OptionGroupFormat.h" #include "lldb/Interpreter/OptionGroupValueObjectDisplay.h" @@ -42,6 +43,7 @@ OptionGroupOptions m_option_group; OptionGroupFormat m_format_options = lldb::eFormatDefault; OptionGroupValueObjectDisplay m_varobj_options; + CommandObjectExpression::CommandOptions m_expr_options; }; } // namespace lldb_private 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 @@ -36,6 +36,7 @@ OptionGroupFormat::OPTION_GROUP_FORMAT | OptionGroupFormat::OPTION_GROUP_GDB_FMT, LLDB_OPT_SET_1); + m_option_group.Append(&m_expr_options); m_option_group.Append(&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); m_option_group.Finalize(); } @@ -87,9 +88,13 @@ Target &target = target_ptr ? *target_ptr : GetDummyTarget(); auto *exe_scope = m_exe_ctx.GetBestExecutionContextScope(); + const EvaluateExpressionOptions eval_options = + m_expr_options.GetEvalateExpressionOptions( + target, m_varobj_options.use_objc, m_varobj_options.use_dynamic); ValueObjectSP valobj_sp; - if (target.EvaluateExpression(expr, exe_scope, valobj_sp) == - eExpressionCompleted) { + ExpressionResults expr_result = + target.EvaluateExpression(expr, exe_scope, valobj_sp, eval_options); + if (expr_result == eExpressionCompleted) { if (verbosity != eDWIMPrintVerbosityNone) { StringRef flags; if (args.HasArgs()) diff --git a/lldb/source/Commands/CommandObjectExpression.h b/lldb/source/Commands/CommandObjectExpression.h --- a/lldb/source/Commands/CommandObjectExpression.h +++ b/lldb/source/Commands/CommandObjectExpression.h @@ -35,6 +35,12 @@ void OptionParsingStarting(ExecutionContext *execution_context) override; + /// Return the appropriate expression options used for evaluating the + /// expression in the given target. + EvaluateExpressionOptions + GetEvalateExpressionOptions(const Target &target, bool use_objc, + lldb::DynamicValueType use_dynamic); + bool top_level; bool unwind_on_error; bool ignore_breakpoints; @@ -67,10 +73,6 @@ bool DoExecute(llvm::StringRef command, CommandReturnObject &result) override; - /// Return the appropriate expression options used for evaluating the - /// expression in the given target. - EvaluateExpressionOptions GetEvalOptions(const Target &target); - /// Evaluates the given expression. /// \param output_stream The stream to which the evaluation result will be /// printed. diff --git a/lldb/source/Commands/CommandObjectExpression.cpp b/lldb/source/Commands/CommandObjectExpression.cpp --- a/lldb/source/Commands/CommandObjectExpression.cpp +++ b/lldb/source/Commands/CommandObjectExpression.cpp @@ -181,6 +181,48 @@ return llvm::ArrayRef(g_expression_options); } +EvaluateExpressionOptions +CommandObjectExpression::CommandOptions::GetEvalateExpressionOptions( + const Target &target, bool use_objc, lldb::DynamicValueType use_dynamic) { + EvaluateExpressionOptions options; + options.SetCoerceToId(use_objc); + if (m_verbosity == eLanguageRuntimeDescriptionDisplayVerbosityCompact) + options.SetSuppressPersistentResult(use_objc); + options.SetUnwindOnError(unwind_on_error); + options.SetIgnoreBreakpoints(ignore_breakpoints); + options.SetKeepInMemory(true); + options.SetUseDynamic(use_dynamic); + options.SetTryAllThreads(try_all_threads); + options.SetDebug(debug); + options.SetLanguage(language); + options.SetExecutionPolicy( + allow_jit ? EvaluateExpressionOptions::default_execution_policy + : lldb_private::eExecutionPolicyNever); + + bool auto_apply_fixits; + if (this->auto_apply_fixits == eLazyBoolCalculate) + auto_apply_fixits = target.GetEnableAutoApplyFixIts(); + else + auto_apply_fixits = this->auto_apply_fixits == eLazyBoolYes; + + options.SetAutoApplyFixIts(auto_apply_fixits); + options.SetRetriesWithFixIts(target.GetNumberOfRetriesWithFixits()); + + if (top_level) + options.SetExecutionPolicy(eExecutionPolicyTopLevel); + + // If there is any chance we are going to stop and want to see what went + // wrong with our expression, we should generate debug info + if (!ignore_breakpoints || !unwind_on_error) + options.SetGenerateDebugInfo(true); + + if (timeout > 0) + options.SetTimeout(std::chrono::microseconds(timeout)); + else + options.SetTimeout(std::nullopt); + return options; +} + CommandObjectExpression::CommandObjectExpression( CommandInterpreter &interpreter) : CommandObjectRaw(interpreter, "expression", @@ -343,50 +385,6 @@ return Status(); } -EvaluateExpressionOptions -CommandObjectExpression::GetEvalOptions(const Target &target) { - EvaluateExpressionOptions options; - options.SetCoerceToId(m_varobj_options.use_objc); - if (m_command_options.m_verbosity == - eLanguageRuntimeDescriptionDisplayVerbosityCompact) - options.SetSuppressPersistentResult(m_varobj_options.use_objc); - options.SetUnwindOnError(m_command_options.unwind_on_error); - options.SetIgnoreBreakpoints(m_command_options.ignore_breakpoints); - options.SetKeepInMemory(true); - options.SetUseDynamic(m_varobj_options.use_dynamic); - options.SetTryAllThreads(m_command_options.try_all_threads); - options.SetDebug(m_command_options.debug); - options.SetLanguage(m_command_options.language); - options.SetExecutionPolicy( - m_command_options.allow_jit - ? EvaluateExpressionOptions::default_execution_policy - : lldb_private::eExecutionPolicyNever); - - bool auto_apply_fixits; - if (m_command_options.auto_apply_fixits == eLazyBoolCalculate) - auto_apply_fixits = target.GetEnableAutoApplyFixIts(); - else - auto_apply_fixits = m_command_options.auto_apply_fixits == eLazyBoolYes; - - options.SetAutoApplyFixIts(auto_apply_fixits); - options.SetRetriesWithFixIts(target.GetNumberOfRetriesWithFixits()); - - if (m_command_options.top_level) - options.SetExecutionPolicy(eExecutionPolicyTopLevel); - - // If there is any chance we are going to stop and want to see what went - // wrong with our expression, we should generate debug info - if (!m_command_options.ignore_breakpoints || - !m_command_options.unwind_on_error) - options.SetGenerateDebugInfo(true); - - if (m_command_options.timeout > 0) - options.SetTimeout(std::chrono::microseconds(m_command_options.timeout)); - else - options.SetTimeout(std::nullopt); - return options; -} - bool CommandObjectExpression::EvaluateExpression(llvm::StringRef expr, Stream &output_stream, Stream &error_stream, @@ -407,7 +405,9 @@ return false; } - const EvaluateExpressionOptions options = GetEvalOptions(target); + const EvaluateExpressionOptions options = + m_command_options.GetEvalateExpressionOptions( + target, m_varobj_options.use_objc, m_varobj_options.use_dynamic); ExpressionResults success = target.EvaluateExpression( expr, frame, result_valobj_sp, options, &m_fixed_expression); 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 @@ -103,3 +103,14 @@ lldbutil.run_to_name_breakpoint(self, "main") self._expect_cmd(f"dwim-print -T -- argc", "frame variable") self._expect_cmd(f"dwim-print -T -- argc + 1", "expression") + + def test_expression_language(self): + self.build() + lldbutil.run_to_name_breakpoint(self, "main") + self._expect_cmd(f"dwim-print -l c++ -- argc + 1", "expression") + + def test_expression_top_level(self): + self.build() + lldbutil.run_to_name_breakpoint(self, "main") + with self.assertRaises(AssertionError): + self._expect_cmd(f"dwim-print -p -- argc + 1", "expression")