diff --git a/lldb/include/lldb/Interpreter/Options.h b/lldb/include/lldb/Interpreter/Options.h --- a/lldb/include/lldb/Interpreter/Options.h +++ b/lldb/include/lldb/Interpreter/Options.h @@ -20,6 +20,7 @@ #include "lldb/lldb-private.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/StringRef.h" namespace lldb_private { @@ -290,6 +291,21 @@ /// copying the option definition. void Append(OptionGroup *group, uint32_t src_mask, uint32_t dst_mask); + /// Append selected options from a OptionGroup class. + /// + /// Append the subset of options from \a group, where the "long_option" value + /// is _not_ in \a exclude_long_options. + /// + /// \param[in] group + /// A group of options to take option values from and copy their + /// definitions into this class. + /// + /// \param[in] exclude_long_options + /// A set of long option strings which indicate which option values values + /// to limit from \a group. + void Append(OptionGroup *group, + llvm::ArrayRef exclude_long_options); + void Finalize(); bool DidFinalize() { return m_did_finalize; } 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,8 @@ OptionGroupFormat::OPTION_GROUP_FORMAT | OptionGroupFormat::OPTION_GROUP_GDB_FMT, LLDB_OPT_SET_1); + StringRef exclude_expr_options[] = {"debug", "top-level"}; + m_option_group.Append(&m_expr_options, exclude_expr_options); m_option_group.Append(&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); m_option_group.Finalize(); } @@ -57,11 +59,11 @@ m_cmd_name); return false; } + auto verbosity = GetDebugger().GetDWIMPrintVerbosity(); DumpValueObjectOptions dump_options = m_varobj_options.GetAsDumpOptions( - eLanguageRuntimeDescriptionDisplayVerbosityFull, - m_format_options.GetFormat()); + m_expr_options.m_verbosity, m_format_options.GetFormat()); // First, try `expr` as the name of a frame variable. if (StackFrame *frame = m_exe_ctx.GetFramePtr()) { @@ -87,9 +89,12 @@ 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); 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, + const OptionGroupValueObjectDisplay &display_opts); + 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, const OptionGroupValueObjectDisplay &display_opts) { + EvaluateExpressionOptions options; + options.SetCoerceToId(display_opts.use_objc); + if (m_verbosity == eLanguageRuntimeDescriptionDisplayVerbosityCompact) + options.SetSuppressPersistentResult(display_opts.use_objc); + options.SetUnwindOnError(unwind_on_error); + options.SetIgnoreBreakpoints(ignore_breakpoints); + options.SetKeepInMemory(true); + options.SetUseDynamic(display_opts.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,8 @@ return false; } - const EvaluateExpressionOptions options = GetEvalOptions(target); + const EvaluateExpressionOptions options = + m_command_options.GetEvalateExpressionOptions(target, m_varobj_options); ExpressionResults success = target.EvaluateExpression( expr, frame, result_valobj_sp, options, &m_fixed_expression); diff --git a/lldb/source/Interpreter/Options.cpp b/lldb/source/Interpreter/Options.cpp --- a/lldb/source/Interpreter/Options.cpp +++ b/lldb/source/Interpreter/Options.cpp @@ -781,6 +781,19 @@ } } +void OptionGroupOptions::Append( + OptionGroup *group, llvm::ArrayRef exclude_long_options) { + uint32_t option_index = 0; + for (auto &&definition : group->GetDefinitions()) { + if (llvm::is_contained(exclude_long_options, definition.long_option)) + continue; + + m_option_infos.push_back(OptionInfo(group, option_index)); + m_option_defs.push_back(definition); + ++option_index; + } +} + void OptionGroupOptions::Finalize() { m_did_finalize = true; } 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,10 @@ 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): + """Test that the language flag doesn't affect the choice of command.""" + self.build() + lldbutil.run_to_name_breakpoint(self, "main") + self._expect_cmd(f"dwim-print -l c++ -- argc", "frame variable") + self._expect_cmd(f"dwim-print -l c++ -- argc + 1", "expression")