[Lldb-commits] [lldb] [lldb] Store the return ValueObject in the CommandReturnObject (PR #127566)

Jonas Devlieghere via lldb-commits lldb-commits at lists.llvm.org
Tue Feb 18 11:20:20 PST 2025


https://github.com/JDevlieghere updated https://github.com/llvm/llvm-project/pull/127566

>From 6f59b1116dd83b9cce526103cca98a5d2056720f Mon Sep 17 00:00:00 2001
From: Jonas Devlieghere <jonas at devlieghere.com>
Date: Mon, 17 Feb 2025 20:58:30 -0800
Subject: [PATCH 1/2] [lldb] Store the return ValueObject in the
 CommandReturnObject

There are a lot of lldb commands whose result is really a ValueObject
that we then print with the ValueObjectPrinter. Now that we have the
ability to access the SBCommandReturnObject through a callback
(#125006), we can store the resultant ValueObject in the return object,
allowing an IDE  to access the SBValue and do its own rich formatting.

rdar://143965453
---
 lldb/include/lldb/API/SBCommandReturnObject.h       |  2 ++
 lldb/include/lldb/API/SBValue.h                     |  1 +
 lldb/include/lldb/Interpreter/CommandReturnObject.h |  9 +++++++++
 lldb/source/API/SBCommandReturnObject.cpp           | 10 ++++++++++
 lldb/source/Commands/CommandObjectDWIMPrint.cpp     |  3 +++
 lldb/source/Commands/CommandObjectExpression.cpp    |  2 ++
 lldb/source/Commands/CommandObjectFrame.cpp         |  1 +
 .../TestSBCommandReturnObject.py                    | 13 +++++++++++++
 8 files changed, 41 insertions(+)

diff --git a/lldb/include/lldb/API/SBCommandReturnObject.h b/lldb/include/lldb/API/SBCommandReturnObject.h
index 9a63c1f96aa70..96dda239d3c97 100644
--- a/lldb/include/lldb/API/SBCommandReturnObject.h
+++ b/lldb/include/lldb/API/SBCommandReturnObject.h
@@ -136,6 +136,8 @@ class LLDB_API SBCommandReturnObject {
 
   void SetError(const char *error_cstr);
 
+  lldb::SBValue GetReturnValue(lldb::DynamicValueType use_dynamic);
+
 protected:
   friend class SBCommandInterpreter;
   friend class SBOptions;
diff --git a/lldb/include/lldb/API/SBValue.h b/lldb/include/lldb/API/SBValue.h
index 46ef6daa95264..75d20a4378f09 100644
--- a/lldb/include/lldb/API/SBValue.h
+++ b/lldb/include/lldb/API/SBValue.h
@@ -442,6 +442,7 @@ class LLDB_API SBValue {
 
 protected:
   friend class SBBlock;
+  friend class SBCommandReturnObject;
   friend class SBFrame;
   friend class SBModule;
   friend class SBTarget;
diff --git a/lldb/include/lldb/Interpreter/CommandReturnObject.h b/lldb/include/lldb/Interpreter/CommandReturnObject.h
index 803bcd76995ed..1a6cc5c6de060 100644
--- a/lldb/include/lldb/Interpreter/CommandReturnObject.h
+++ b/lldb/include/lldb/Interpreter/CommandReturnObject.h
@@ -165,6 +165,12 @@ class CommandReturnObject {
     return m_diagnostic_indent;
   }
 
+  lldb::ValueObjectSP GetValueObjectSP() const { return m_value_object_sp; }
+
+  void SetValueObjectSP(lldb::ValueObjectSP value_object_sp) {
+    m_value_object_sp = value_object_sp;
+  }
+
   lldb::ReturnStatus GetStatus() const;
 
   void SetStatus(lldb::ReturnStatus status);
@@ -197,6 +203,9 @@ class CommandReturnObject {
 
   lldb::ReturnStatus m_status = lldb::eReturnStatusStarted;
 
+  /// An optional return ValueObjectSP.
+  lldb::ValueObjectSP m_value_object_sp;
+
   bool m_did_change_process_state = false;
   bool m_suppress_immediate_output = false;
 
diff --git a/lldb/source/API/SBCommandReturnObject.cpp b/lldb/source/API/SBCommandReturnObject.cpp
index 6f54581e64ef4..085bfac57c0a8 100644
--- a/lldb/source/API/SBCommandReturnObject.cpp
+++ b/lldb/source/API/SBCommandReturnObject.cpp
@@ -12,6 +12,7 @@
 #include "lldb/API/SBFile.h"
 #include "lldb/API/SBStream.h"
 #include "lldb/API/SBStructuredData.h"
+#include "lldb/API/SBValue.h"
 #include "lldb/Core/StructuredDataImpl.h"
 #include "lldb/Interpreter/CommandReturnObject.h"
 #include "lldb/Utility/ConstString.h"
@@ -356,3 +357,12 @@ void SBCommandReturnObject::SetError(const char *error_cstr) {
   if (error_cstr)
     ref().AppendError(error_cstr);
 }
+
+SBValue
+SBCommandReturnObject::GetReturnValue(lldb::DynamicValueType use_dynamic) {
+  LLDB_INSTRUMENT_VA(this, use_dynamic);
+
+  SBValue sb_value;
+  sb_value.SetSP(ref().GetValueObjectSP(), use_dynamic);
+  return sb_value;
+}
diff --git a/lldb/source/Commands/CommandObjectDWIMPrint.cpp b/lldb/source/Commands/CommandObjectDWIMPrint.cpp
index d4d038d28f675..aab99441c63a3 100644
--- a/lldb/source/Commands/CommandObjectDWIMPrint.cpp
+++ b/lldb/source/Commands/CommandObjectDWIMPrint.cpp
@@ -205,6 +205,9 @@ void CommandObjectDWIMPrint::DoExecute(StringRef command,
     ExpressionResults expr_result = target.EvaluateExpression(
         expr, exe_scope, valobj_sp, eval_options, &fixed_expression);
 
+    if (valobj_sp)
+      result.SetValueObjectSP(valobj_sp);
+
     // Record the position of the expression in the command.
     std::optional<uint16_t> indent;
     if (fixed_expression.empty()) {
diff --git a/lldb/source/Commands/CommandObjectExpression.cpp b/lldb/source/Commands/CommandObjectExpression.cpp
index 7e26381c92405..b0c92d9391b13 100644
--- a/lldb/source/Commands/CommandObjectExpression.cpp
+++ b/lldb/source/Commands/CommandObjectExpression.cpp
@@ -434,6 +434,8 @@ bool CommandObjectExpression::EvaluateExpression(llvm::StringRef expr,
   }
 
   if (result_valobj_sp) {
+    result.SetValueObjectSP(result_valobj_sp);
+
     Format format = m_format_options.GetFormat();
 
     if (result_valobj_sp->GetError().Success()) {
diff --git a/lldb/source/Commands/CommandObjectFrame.cpp b/lldb/source/Commands/CommandObjectFrame.cpp
index a5709b36f52ee..96612fdbec6d5 100644
--- a/lldb/source/Commands/CommandObjectFrame.cpp
+++ b/lldb/source/Commands/CommandObjectFrame.cpp
@@ -152,6 +152,7 @@ class CommandObjectFrameDiagnose : public CommandObjectParsed {
       return;
     }
 
+    result.SetValueObjectSP(valobj_sp);
     DumpValueObjectOptions::DeclPrintingHelper helper =
         [&valobj_sp](ConstString type, ConstString var,
                      const DumpValueObjectOptions &opts,
diff --git a/lldb/test/API/api/command-return-object/TestSBCommandReturnObject.py b/lldb/test/API/api/command-return-object/TestSBCommandReturnObject.py
index 2193b7270d0b4..0fee54eb5fe1d 100644
--- a/lldb/test/API/api/command-return-object/TestSBCommandReturnObject.py
+++ b/lldb/test/API/api/command-return-object/TestSBCommandReturnObject.py
@@ -33,3 +33,16 @@ def test_get_command(self):
         ci.HandleCommand("help help", res)
         self.assertTrue(res.Succeeded())
         self.assertEqual(res.GetCommand(), "help help")
+
+        value = res.GetReturnValue(lldb.eNoDynamicValues)
+        self.assertFalse(value)
+
+    def test_get_value(self):
+        res = lldb.SBCommandReturnObject()
+        ci = self.dbg.GetCommandInterpreter()
+        ci.HandleCommand("p 1 + 1", res)
+        self.assertTrue(res.Succeeded())
+
+        value = res.GetReturnValue(lldb.eNoDynamicValues)
+        self.assertTrue(value)
+        self.assertEqual(value.GetValue(), "2")

>From 83ea8516bdd5b127b5e5046fd35c213ab46b51c2 Mon Sep 17 00:00:00 2001
From: Jonas Devlieghere <jonas at devlieghere.com>
Date: Tue, 18 Feb 2025 11:20:08 -0800
Subject: [PATCH 2/2] Store SBValueList instead of SBValue

---
 lldb/include/lldb/API/SBCommandReturnObject.h |  2 +-
 .../lldb/Interpreter/CommandReturnObject.h    | 17 ++++++++---------
 .../lldb/ValueObject/ValueObjectList.h        |  2 --
 lldb/source/API/SBCommandReturnObject.cpp     | 18 +++++++++++++-----
 .../Commands/CommandObjectDWIMPrint.cpp       |  2 +-
 .../Commands/CommandObjectExpression.cpp      |  2 +-
 lldb/source/Commands/CommandObjectFrame.cpp   | 17 ++++++++++++-----
 lldb/source/Commands/CommandObjectTarget.cpp  | 19 ++++++++++++-------
 lldb/source/ValueObject/ValueObjectList.cpp   |  6 ------
 .../TestSBCommandReturnObject.py              | 10 +++++-----
 .../API/commands/frame/var/TestFrameVar.py    |  9 ++++++++-
 .../target_var/TestTargetVar.py               |  9 +++++++++
 12 files changed, 70 insertions(+), 43 deletions(-)

diff --git a/lldb/include/lldb/API/SBCommandReturnObject.h b/lldb/include/lldb/API/SBCommandReturnObject.h
index 96dda239d3c97..6386bd250afa5 100644
--- a/lldb/include/lldb/API/SBCommandReturnObject.h
+++ b/lldb/include/lldb/API/SBCommandReturnObject.h
@@ -136,7 +136,7 @@ class LLDB_API SBCommandReturnObject {
 
   void SetError(const char *error_cstr);
 
-  lldb::SBValue GetReturnValue(lldb::DynamicValueType use_dynamic);
+  lldb::SBValueList GetValues(lldb::DynamicValueType use_dynamic);
 
 protected:
   friend class SBCommandInterpreter;
diff --git a/lldb/include/lldb/Interpreter/CommandReturnObject.h b/lldb/include/lldb/Interpreter/CommandReturnObject.h
index 1a6cc5c6de060..d53aeb81be2ba 100644
--- a/lldb/include/lldb/Interpreter/CommandReturnObject.h
+++ b/lldb/include/lldb/Interpreter/CommandReturnObject.h
@@ -14,6 +14,7 @@
 #include "lldb/Utility/StreamString.h"
 #include "lldb/Utility/StreamTee.h"
 #include "lldb/Utility/StructuredData.h"
+#include "lldb/ValueObject/ValueObjectList.h"
 #include "lldb/lldb-private.h"
 
 #include "llvm/ADT/StringRef.h"
@@ -134,7 +135,7 @@ class CommandReturnObject {
       __attribute__((format(printf, 2, 3)));
 
   template <typename... Args>
-  void AppendMessageWithFormatv(const char *format, Args &&... args) {
+  void AppendMessageWithFormatv(const char *format, Args &&...args) {
     AppendMessage(llvm::formatv(format, std::forward<Args>(args)...).str());
   }
 
@@ -144,12 +145,12 @@ class CommandReturnObject {
   }
 
   template <typename... Args>
-  void AppendWarningWithFormatv(const char *format, Args &&... args) {
+  void AppendWarningWithFormatv(const char *format, Args &&...args) {
     AppendWarning(llvm::formatv(format, std::forward<Args>(args)...).str());
   }
 
   template <typename... Args>
-  void AppendErrorWithFormatv(const char *format, Args &&... args) {
+  void AppendErrorWithFormatv(const char *format, Args &&...args) {
     AppendError(llvm::formatv(format, std::forward<Args>(args)...).str());
   }
 
@@ -165,11 +166,9 @@ class CommandReturnObject {
     return m_diagnostic_indent;
   }
 
-  lldb::ValueObjectSP GetValueObjectSP() const { return m_value_object_sp; }
+  const ValueObjectList &GetValueObjectList() const { return m_value_objects; }
 
-  void SetValueObjectSP(lldb::ValueObjectSP value_object_sp) {
-    m_value_object_sp = value_object_sp;
-  }
+  ValueObjectList &GetValueObjectList() { return m_value_objects; }
 
   lldb::ReturnStatus GetStatus() const;
 
@@ -203,8 +202,8 @@ class CommandReturnObject {
 
   lldb::ReturnStatus m_status = lldb::eReturnStatusStarted;
 
-  /// An optional return ValueObjectSP.
-  lldb::ValueObjectSP m_value_object_sp;
+  /// An optionally empty list of values produced by this command.
+  ValueObjectList m_value_objects;
 
   bool m_did_change_process_state = false;
   bool m_suppress_immediate_output = false;
diff --git a/lldb/include/lldb/ValueObject/ValueObjectList.h b/lldb/include/lldb/ValueObject/ValueObjectList.h
index 5d63c65a96e5f..524b66b209c23 100644
--- a/lldb/include/lldb/ValueObject/ValueObjectList.h
+++ b/lldb/include/lldb/ValueObject/ValueObjectList.h
@@ -22,8 +22,6 @@ class ValueObject;
 /// A collection of ValueObject values that.
 class ValueObjectList {
 public:
-  const ValueObjectList &operator=(const ValueObjectList &rhs);
-
   void Append(const lldb::ValueObjectSP &val_obj_sp);
 
   void Append(const ValueObjectList &valobj_list);
diff --git a/lldb/source/API/SBCommandReturnObject.cpp b/lldb/source/API/SBCommandReturnObject.cpp
index 085bfac57c0a8..e78e213aa23af 100644
--- a/lldb/source/API/SBCommandReturnObject.cpp
+++ b/lldb/source/API/SBCommandReturnObject.cpp
@@ -13,11 +13,13 @@
 #include "lldb/API/SBStream.h"
 #include "lldb/API/SBStructuredData.h"
 #include "lldb/API/SBValue.h"
+#include "lldb/API/SBValueList.h"
 #include "lldb/Core/StructuredDataImpl.h"
 #include "lldb/Interpreter/CommandReturnObject.h"
 #include "lldb/Utility/ConstString.h"
 #include "lldb/Utility/Instrumentation.h"
 #include "lldb/Utility/Status.h"
+#include "lldb/lldb-forward.h"
 
 using namespace lldb;
 using namespace lldb_private;
@@ -358,11 +360,17 @@ void SBCommandReturnObject::SetError(const char *error_cstr) {
     ref().AppendError(error_cstr);
 }
 
-SBValue
-SBCommandReturnObject::GetReturnValue(lldb::DynamicValueType use_dynamic) {
+SBValueList
+SBCommandReturnObject::GetValues(lldb::DynamicValueType use_dynamic) {
   LLDB_INSTRUMENT_VA(this, use_dynamic);
 
-  SBValue sb_value;
-  sb_value.SetSP(ref().GetValueObjectSP(), use_dynamic);
-  return sb_value;
+  SBValueList value_list;
+  for (ValueObjectSP value_object_sp :
+       ref().GetValueObjectList().GetObjects()) {
+    SBValue value_sb;
+    value_sb.SetSP(value_object_sp, use_dynamic);
+    value_list.Append(value_sb);
+  }
+
+  return value_list;
 }
diff --git a/lldb/source/Commands/CommandObjectDWIMPrint.cpp b/lldb/source/Commands/CommandObjectDWIMPrint.cpp
index aab99441c63a3..04142427717bd 100644
--- a/lldb/source/Commands/CommandObjectDWIMPrint.cpp
+++ b/lldb/source/Commands/CommandObjectDWIMPrint.cpp
@@ -206,7 +206,7 @@ void CommandObjectDWIMPrint::DoExecute(StringRef command,
         expr, exe_scope, valobj_sp, eval_options, &fixed_expression);
 
     if (valobj_sp)
-      result.SetValueObjectSP(valobj_sp);
+      result.GetValueObjectList().Append(valobj_sp);
 
     // Record the position of the expression in the command.
     std::optional<uint16_t> indent;
diff --git a/lldb/source/Commands/CommandObjectExpression.cpp b/lldb/source/Commands/CommandObjectExpression.cpp
index b0c92d9391b13..18526c4de2cb0 100644
--- a/lldb/source/Commands/CommandObjectExpression.cpp
+++ b/lldb/source/Commands/CommandObjectExpression.cpp
@@ -434,7 +434,7 @@ bool CommandObjectExpression::EvaluateExpression(llvm::StringRef expr,
   }
 
   if (result_valobj_sp) {
-    result.SetValueObjectSP(result_valobj_sp);
+    result.GetValueObjectList().Append(result_valobj_sp);
 
     Format format = m_format_options.GetFormat();
 
diff --git a/lldb/source/Commands/CommandObjectFrame.cpp b/lldb/source/Commands/CommandObjectFrame.cpp
index 96612fdbec6d5..7e42ef2615319 100644
--- a/lldb/source/Commands/CommandObjectFrame.cpp
+++ b/lldb/source/Commands/CommandObjectFrame.cpp
@@ -152,7 +152,7 @@ class CommandObjectFrameDiagnose : public CommandObjectParsed {
       return;
     }
 
-    result.SetValueObjectSP(valobj_sp);
+    result.GetValueObjectList().Append(valobj_sp);
     DumpValueObjectOptions::DeclPrintingHelper helper =
         [&valobj_sp](ConstString type, ConstString var,
                      const DumpValueObjectOptions &opts,
@@ -318,10 +318,10 @@ class CommandObjectFrameSelect : public CommandObjectParsed {
       } else if (*m_options.relative_frame_offset > 0) {
         // I don't want "up 20" where "20" takes you past the top of the stack
         // to produce an error, but rather to just go to the top.  OTOH, start
-        // by seeing if the requested frame exists, in which case we can avoid 
+        // by seeing if the requested frame exists, in which case we can avoid
         // counting the stack here...
-        const uint32_t frame_requested = frame_idx 
-            + *m_options.relative_frame_offset;
+        const uint32_t frame_requested =
+            frame_idx + *m_options.relative_frame_offset;
         StackFrameSP frame_sp = thread->GetStackFrameAtIndex(frame_requested);
         if (frame_sp)
           frame_idx = frame_requested;
@@ -516,8 +516,8 @@ may even involve JITing and running code in the target program.)");
 
     if (error.Fail() && (!variable_list || variable_list->GetSize() == 0)) {
       result.AppendError(error.AsCString());
-
     }
+
     ValueObjectSP valobj_sp;
 
     TypeSummaryImplSP summary_format_sp;
@@ -565,6 +565,8 @@ may even involve JITing and running code in the target program.)");
                 valobj_sp = frame->GetValueObjectForFrameVariable(
                     var_sp, m_varobj_options.use_dynamic);
                 if (valobj_sp) {
+                  result.GetValueObjectList().Append(valobj_sp);
+
                   std::string scope_string;
                   if (m_option_variable.show_scope)
                     scope_string = GetScopeString(var_sp).str();
@@ -605,6 +607,8 @@ may even involve JITing and running code in the target program.)");
                 entry.ref(), m_varobj_options.use_dynamic, expr_path_options,
                 var_sp, error);
             if (valobj_sp) {
+              result.GetValueObjectList().Append(valobj_sp);
+
               std::string scope_string;
               if (m_option_variable.show_scope)
                 scope_string = GetScopeString(var_sp).str();
@@ -654,6 +658,8 @@ may even involve JITing and running code in the target program.)");
             valobj_sp = frame->GetValueObjectForFrameVariable(
                 var_sp, m_varobj_options.use_dynamic);
             if (valobj_sp) {
+              result.GetValueObjectList().Append(valobj_sp);
+
               // When dumping all variables, don't print any variables that are
               // not in scope to avoid extra unneeded output
               if (valobj_sp->IsInScope()) {
@@ -695,6 +701,7 @@ may even involve JITing and running code in the target program.)");
             recognized_frame->GetRecognizedArguments();
         if (recognized_arg_list) {
           for (auto &rec_value_sp : recognized_arg_list->GetObjects()) {
+            result.GetValueObjectList().Append(rec_value_sp);
             options.SetFormat(m_option_format.GetFormat());
             options.SetVariableFormatDisplayLanguage(
                 rec_value_sp->GetPreferredDisplayLanguage());
diff --git a/lldb/source/Commands/CommandObjectTarget.cpp b/lldb/source/Commands/CommandObjectTarget.cpp
index da50fe04fa2b6..71ddc8d933e1e 100644
--- a/lldb/source/Commands/CommandObjectTarget.cpp
+++ b/lldb/source/Commands/CommandObjectTarget.cpp
@@ -803,7 +803,9 @@ class CommandObjectTargetVariable : public CommandObjectParsed {
 protected:
   void DumpGlobalVariableList(const ExecutionContext &exe_ctx,
                               const SymbolContext &sc,
-                              const VariableList &variable_list, Stream &s) {
+                              const VariableList &variable_list,
+                              CommandReturnObject &result) {
+    Stream &s = result.GetOutputStream();
     if (variable_list.Empty())
       return;
     if (sc.module_sp) {
@@ -824,15 +826,16 @@ class CommandObjectTargetVariable : public CommandObjectParsed {
       ValueObjectSP valobj_sp(ValueObjectVariable::Create(
           exe_ctx.GetBestExecutionContextScope(), var_sp));
 
-      if (valobj_sp)
+      if (valobj_sp) {
+        result.GetValueObjectList().Append(valobj_sp);
         DumpValueObject(s, var_sp, valobj_sp, var_sp->GetName().GetCString());
+      }
     }
   }
 
   void DoExecute(Args &args, CommandReturnObject &result) override {
     Target *target = m_exe_ctx.GetTargetPtr();
     const size_t argc = args.GetArgumentCount();
-    Stream &s = result.GetOutputStream();
 
     if (argc > 0) {
       for (const Args::ArgEntry &arg : args) {
@@ -874,7 +877,7 @@ class CommandObjectTargetVariable : public CommandObjectParsed {
                     m_exe_ctx.GetBestExecutionContextScope(), var_sp);
 
               if (valobj_sp)
-                DumpValueObject(s, var_sp, valobj_sp,
+                DumpValueObject(result.GetOutputStream(), var_sp, valobj_sp,
                                 use_var_name ? var_sp->GetName().GetCString()
                                              : arg.c_str());
             }
@@ -903,7 +906,8 @@ class CommandObjectTargetVariable : public CommandObjectParsed {
             if (comp_unit_varlist_sp) {
               size_t count = comp_unit_varlist_sp->GetSize();
               if (count > 0) {
-                DumpGlobalVariableList(m_exe_ctx, sc, *comp_unit_varlist_sp, s);
+                DumpGlobalVariableList(m_exe_ctx, sc, *comp_unit_varlist_sp,
+                                       result);
                 success = true;
               }
             }
@@ -964,7 +968,8 @@ class CommandObjectTargetVariable : public CommandObjectParsed {
             VariableListSP comp_unit_varlist_sp(
                 sc.comp_unit->GetVariableList(can_create));
             if (comp_unit_varlist_sp)
-              DumpGlobalVariableList(m_exe_ctx, sc, *comp_unit_varlist_sp, s);
+              DumpGlobalVariableList(m_exe_ctx, sc, *comp_unit_varlist_sp,
+                                     result);
           } else if (sc.module_sp) {
             // Get all global variables for this module
             lldb_private::RegularExpression all_globals_regex(
@@ -972,7 +977,7 @@ class CommandObjectTargetVariable : public CommandObjectParsed {
             VariableList variable_list;
             sc.module_sp->FindGlobalVariables(all_globals_regex, UINT32_MAX,
                                               variable_list);
-            DumpGlobalVariableList(m_exe_ctx, sc, variable_list, s);
+            DumpGlobalVariableList(m_exe_ctx, sc, variable_list, result);
           }
         }
       }
diff --git a/lldb/source/ValueObject/ValueObjectList.cpp b/lldb/source/ValueObject/ValueObjectList.cpp
index a79a040bdf7fd..fdee9579b093b 100644
--- a/lldb/source/ValueObject/ValueObjectList.cpp
+++ b/lldb/source/ValueObject/ValueObjectList.cpp
@@ -16,12 +16,6 @@
 using namespace lldb;
 using namespace lldb_private;
 
-const ValueObjectList &ValueObjectList::operator=(const ValueObjectList &rhs) {
-  if (this != &rhs)
-    m_value_objects = rhs.m_value_objects;
-  return *this;
-}
-
 void ValueObjectList::Append(const ValueObjectSP &val_obj_sp) {
   m_value_objects.push_back(val_obj_sp);
 }
diff --git a/lldb/test/API/api/command-return-object/TestSBCommandReturnObject.py b/lldb/test/API/api/command-return-object/TestSBCommandReturnObject.py
index 0fee54eb5fe1d..f8632fd720325 100644
--- a/lldb/test/API/api/command-return-object/TestSBCommandReturnObject.py
+++ b/lldb/test/API/api/command-return-object/TestSBCommandReturnObject.py
@@ -34,8 +34,8 @@ def test_get_command(self):
         self.assertTrue(res.Succeeded())
         self.assertEqual(res.GetCommand(), "help help")
 
-        value = res.GetReturnValue(lldb.eNoDynamicValues)
-        self.assertFalse(value)
+        value_list = res.GetValues(lldb.eNoDynamicValues)
+        self.assertEqual(value_list.GetSize(), 0)
 
     def test_get_value(self):
         res = lldb.SBCommandReturnObject()
@@ -43,6 +43,6 @@ def test_get_value(self):
         ci.HandleCommand("p 1 + 1", res)
         self.assertTrue(res.Succeeded())
 
-        value = res.GetReturnValue(lldb.eNoDynamicValues)
-        self.assertTrue(value)
-        self.assertEqual(value.GetValue(), "2")
+        value_list = res.GetValues(lldb.eNoDynamicValues)
+        self.assertEqual(value_list.GetSize(), 1)
+        self.assertEqual(value_list.GetValueAtIndex(0).GetValue(), "2")
diff --git a/lldb/test/API/commands/frame/var/TestFrameVar.py b/lldb/test/API/commands/frame/var/TestFrameVar.py
index 7211cade5c7c8..d8260a5657618 100644
--- a/lldb/test/API/commands/frame/var/TestFrameVar.py
+++ b/lldb/test/API/commands/frame/var/TestFrameVar.py
@@ -2,7 +2,6 @@
 Make sure the frame variable -g, -a, and -l flags work.
 """
 
-
 import lldb
 import lldbsuite.test.lldbutil as lldbutil
 from lldbsuite.test.decorators import *
@@ -79,6 +78,14 @@ def do_test(self):
         self.assertNotIn("test_var", output, "Args found a local")
         self.assertNotIn("g_var", output, "Args found a global")
 
+        value_list = command_result.GetValues(lldb.eNoDynamicValues)
+        self.assertGreaterEqual(value_list.GetSize(), 2)
+        value_names = []
+        for value in value_list:
+            value_names.append(value.GetName())
+        self.assertIn("argc", value_names)
+        self.assertIn("argv", value_names)
+
         # Just get locals:
         result = interp.HandleCommand("frame var -a", command_result)
         self.assertEqual(
diff --git a/lldb/test/API/functionalities/target_var/TestTargetVar.py b/lldb/test/API/functionalities/target_var/TestTargetVar.py
index 54b7b77b6773c..0ef3d008e8f19 100644
--- a/lldb/test/API/functionalities/target_var/TestTargetVar.py
+++ b/lldb/test/API/functionalities/target_var/TestTargetVar.py
@@ -34,3 +34,12 @@ def testTargetVarExpr(self):
             error=True,
             substrs=["can't find global variable 'var[0]'"],
         )
+
+        command_result = lldb.SBCommandReturnObject()
+        result = self.ci.HandleCommand("target var", command_result)
+        value_list = command_result.GetValues(lldb.eNoDynamicValues)
+        self.assertGreaterEqual(value_list.GetSize(), 2)
+        value_names = []
+        for value in value_list:
+            value_names.append(value.GetName())
+        self.assertIn("i", value_names)



More information about the lldb-commits mailing list