[lldb] Add expression command options in dwim-print
authorDave Lee <davelee.com@gmail.com>
Wed, 15 Feb 2023 16:23:57 +0000 (08:23 -0800)
committerDave Lee <davelee.com@gmail.com>
Sat, 18 Feb 2023 01:50:08 +0000 (17:50 -0800)
Adopt `expression`'s options in `dwim-print`.

This is primarily added to support the `--language`/`-l` flag.

Differential Revision: https://reviews.llvm.org/D144114

lldb/include/lldb/Interpreter/Options.h
lldb/source/Commands/CommandObjectDWIMPrint.cpp
lldb/source/Commands/CommandObjectDWIMPrint.h
lldb/source/Commands/CommandObjectExpression.cpp
lldb/source/Commands/CommandObjectExpression.h
lldb/source/Interpreter/Options.cpp
lldb/test/API/commands/dwim-print/TestDWIMPrint.py

index a952d5f..bf74927 100644 (file)
@@ -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 @@ public:
   ///     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<llvm::StringRef> exclude_long_options);
+
   void Finalize();
 
   bool DidFinalize() { return m_did_finalize; }
index 81da150..28c78af 100644 (file)
@@ -36,6 +36,8 @@ CommandObjectDWIMPrint::CommandObjectDWIMPrint(CommandInterpreter &interpreter)
                         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 @@ bool CommandObjectDWIMPrint::DoExecute(StringRef command,
                                   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 @@ bool CommandObjectDWIMPrint::DoExecute(StringRef command,
     Target &target = target_ptr ? *target_ptr : GetDummyTarget();
 
     auto *exe_scope = m_exe_ctx.GetBestExecutionContextScope();
+    const EvaluateExpressionOptions eval_options =
+        m_expr_options.GetEvaluateExpressionOptions(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())
index 94daa85..8a14a6c 100644 (file)
@@ -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 @@ private:
   OptionGroupOptions m_option_group;
   OptionGroupFormat m_format_options = lldb::eFormatDefault;
   OptionGroupValueObjectDisplay m_varobj_options;
+  CommandObjectExpression::CommandOptions m_expr_options;
 };
 
 } // namespace lldb_private
index 9402000..f576729 100644 (file)
@@ -181,6 +181,48 @@ CommandObjectExpression::CommandOptions::GetDefinitions() {
   return llvm::ArrayRef(g_expression_options);
 }
 
+EvaluateExpressionOptions
+CommandObjectExpression::CommandOptions::GetEvaluateExpressionOptions(
+    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 @@ CanBeUsedForElementCountPrinting(ValueObject &valobj) {
   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 @@ bool CommandObjectExpression::EvaluateExpression(llvm::StringRef expr,
     return false;
   }
 
-  const EvaluateExpressionOptions options = GetEvalOptions(target);
+  const EvaluateExpressionOptions options =
+      m_command_options.GetEvaluateExpressionOptions(target, m_varobj_options);
   ExpressionResults success = target.EvaluateExpression(
       expr, frame, result_valobj_sp, options, &m_fixed_expression);
 
index 1e59cbc..bcd76f8 100644 (file)
@@ -35,6 +35,12 @@ public:
 
     void OptionParsingStarting(ExecutionContext *execution_context) override;
 
+    /// Return the appropriate expression options used for evaluating the
+    /// expression in the given target.
+    EvaluateExpressionOptions GetEvaluateExpressionOptions(
+        const Target &target,
+        const OptionGroupValueObjectDisplay &display_opts);
+
     bool top_level;
     bool unwind_on_error;
     bool ignore_breakpoints;
@@ -67,10 +73,6 @@ protected:
 
   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.
index 8cb386f..7bfb88f 100644 (file)
@@ -781,6 +781,19 @@ void OptionGroupOptions::Append(OptionGroup *group, uint32_t src_mask,
   }
 }
 
+void OptionGroupOptions::Append(
+    OptionGroup *group, llvm::ArrayRef<llvm::StringRef> exclude_long_options) {
+  auto group_option_defs = group->GetDefinitions();
+  for (uint32_t i = 0; i < group_option_defs.size(); ++i) {
+    const auto &definition = group_option_defs[i];
+    if (llvm::is_contained(exclude_long_options, definition.long_option))
+      continue;
+
+    m_option_infos.push_back(OptionInfo(group, i));
+    m_option_defs.push_back(definition);
+  }
+}
+
 void OptionGroupOptions::Finalize() {
   m_did_finalize = true;
 }
index c176e91..89d4009 100644 (file)
@@ -103,3 +103,10 @@ class TestCase(TestBase):
         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")