[Lldb-commits] [lldb] 3a677b2 - [lldb] Add deref support to libc++ unique_ptr synthetic

Dave Lee via lldb-commits lldb-commits at lists.llvm.org
Fri Feb 26 07:39:08 PST 2021


Author: Dave Lee
Date: 2021-02-26T07:39:01-08:00
New Revision: 3a677b29a3b3f6a2539843db4d56ba59689fc0a0

URL: https://github.com/llvm/llvm-project/commit/3a677b29a3b3f6a2539843db4d56ba59689fc0a0
DIFF: https://github.com/llvm/llvm-project/commit/3a677b29a3b3f6a2539843db4d56ba59689fc0a0.diff

LOG: [lldb] Add deref support to libc++ unique_ptr synthetic

Add frame variable dereference suppport to libc++ `std::unique_ptr`.

This change allows for commands like `v *thing_up` and `v thing_up->m_id`. These commands now work the same way they would with raw pointers, and as they would with expression. This is done by adding an unaccounted for child member named `$$dereference$$`.

Without this change, the command would have to be written as `v *thing_up.__value_` or v thing_up.__value_->m_id` which exposes internal structure and is more clumsy to type.

Additionally, the existing tests were updated. See also https://reviews.llvm.org/D97165 which added deref support for `std::shared_ptr`.

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

Added: 
    

Modified: 
    lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp
    lldb/source/Plugins/Language/CPlusPlus/LibCxx.h
    lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/unique_ptr/TestDataFormatterLibcxxUniquePtr.py
    lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/unique_ptr/main.cpp

Removed: 
    


################################################################################
diff  --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp
index 925076f10d72..8eda422f3145 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp
@@ -463,7 +463,7 @@ lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEndCreator(
 
 lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEnd::
     LibcxxUniquePtrSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
-    : SyntheticChildrenFrontEnd(*valobj_sp), m_compressed_pair_sp() {
+    : SyntheticChildrenFrontEnd(*valobj_sp) {
   if (valobj_sp)
     Update();
 }
@@ -480,19 +480,27 @@ lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEndCreator(
 
 size_t lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEnd::
     CalculateNumChildren() {
-  return (m_compressed_pair_sp ? 1 : 0);
+  return (m_value_ptr_sp ? 1 : 0);
 }
 
 lldb::ValueObjectSP
 lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEnd::GetChildAtIndex(
     size_t idx) {
-  if (!m_compressed_pair_sp)
+  if (!m_value_ptr_sp)
     return lldb::ValueObjectSP();
 
-  if (idx != 0)
-    return lldb::ValueObjectSP();
+  if (idx == 0)
+    return m_value_ptr_sp;
 
-  return m_compressed_pair_sp;
+  if (idx == 1) {
+    Status status;
+    auto value_sp = m_value_ptr_sp->Dereference(status);
+    if (status.Success()) {
+      return value_sp;
+    }
+  }
+
+  return lldb::ValueObjectSP();
 }
 
 bool lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEnd::Update() {
@@ -505,7 +513,7 @@ bool lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEnd::Update() {
   if (!ptr_sp)
     return false;
 
-  m_compressed_pair_sp = GetValueOfLibCXXCompressedPair(*ptr_sp);
+  m_value_ptr_sp = GetValueOfLibCXXCompressedPair(*ptr_sp);
 
   return false;
 }
@@ -519,6 +527,8 @@ size_t lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEnd::
     GetIndexOfChildWithName(ConstString name) {
   if (name == "__value_")
     return 0;
+  if (name == "$$dereference$$")
+    return 1;
   return UINT32_MAX;
 }
 

diff  --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h
index 907025fe8ac8..99e206543197 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h
+++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h
@@ -124,7 +124,7 @@ class LibcxxUniquePtrSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
   ~LibcxxUniquePtrSyntheticFrontEnd() override;
 
 private:
-  lldb::ValueObjectSP m_compressed_pair_sp;
+  lldb::ValueObjectSP m_value_ptr_sp;
 };
 
 SyntheticChildrenFrontEnd *

diff  --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/unique_ptr/TestDataFormatterLibcxxUniquePtr.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/unique_ptr/TestDataFormatterLibcxxUniquePtr.py
index b91e494258bf..825513a0b49b 100644
--- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/unique_ptr/TestDataFormatterLibcxxUniquePtr.py
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/unique_ptr/TestDataFormatterLibcxxUniquePtr.py
@@ -3,45 +3,85 @@
 """
 
 
-
 import lldb
 from lldbsuite.test.decorators import *
 from lldbsuite.test.lldbtest import *
 from lldbsuite.test import lldbutil
 
-class LibcxUniquePtrDataFormatterTestCase(TestBase):
+
+class TestCase(TestBase):
 
     mydir = TestBase.compute_mydir(__file__)
 
     @add_test_categories(["libc++"])
-    def test_with_run_command(self):
-        """Test that that file and class static variables display correctly."""
+    def test_unique_ptr_variables(self):
+        """Test `frame variable` output for `std::unique_ptr` types."""
         self.build()
 
-        (self.target, self.process, _, bkpt) = lldbutil.run_to_source_breakpoint(self, '// break here',
-                lldb.SBFileSpec("main.cpp", False))
-
-        self.expect("frame variable up_empty",
-            substrs=['(std::unique_ptr<int, std::default_delete<int> >) up_empty = nullptr {',
-                               '__value_ = ',
-                               '}'])
-
-        self.expect("frame variable up_int",
-            substrs=['(std::unique_ptr<int, std::default_delete<int> >) up_int = 10 {',
-                               '__value_ = ',
-                               '}'])
-
-        self.expect("frame variable up_int_ref",
-            substrs=['(std::unique_ptr<int, std::default_delete<int> > &) up_int_ref = 10: {',
-                               '__value_ = ',
-                               '}'])
-
-        self.expect("frame variable up_int_ref_ref",
-            substrs=['(std::unique_ptr<int, std::default_delete<int> > &&) up_int_ref_ref = 10: {',
-                               '__value_ = ',
-                               '}'])
-
-        self.expect("frame variable up_str",
-            substrs=['up_str = "hello" {',
-                               '__value_ = ',
-                               '}'])
+        lldbutil.run_to_source_breakpoint(
+            self, "// break here", lldb.SBFileSpec("main.cpp")
+        )
+
+        valobj = self.expect_var_path(
+            "up_empty",
+            type="std::unique_ptr<int, std::default_delete<int> >",
+            summary="nullptr",
+            children=[ValueCheck(name="__value_")],
+        )
+        self.assertEqual(
+            valobj.child[0].GetValueAsUnsigned(lldb.LLDB_INVALID_ADDRESS), 0
+        )
+
+        self.expect(
+            "frame variable *up_empty", substrs=["(int) *up_empty = <parent is NULL>"]
+        )
+
+        valobj = self.expect_var_path(
+            "up_int",
+            type="std::unique_ptr<int, std::default_delete<int> >",
+            summary="10",
+            children=[ValueCheck(name="__value_")],
+        )
+        self.assertNotEqual(valobj.child[0].unsigned, 0)
+
+        valobj = self.expect_var_path(
+            "up_int_ref",
+            type="std::unique_ptr<int, std::default_delete<int> > &",
+            summary="10",
+            children=[ValueCheck(name="__value_")],
+        )
+        self.assertNotEqual(valobj.child[0].unsigned, 0)
+
+        valobj = self.expect_var_path(
+            "up_int_ref_ref",
+            type="std::unique_ptr<int, std::default_delete<int> > &&",
+            summary="10",
+            children=[ValueCheck(name="__value_")],
+        )
+        self.assertNotEqual(valobj.child[0].unsigned, 0)
+
+        valobj = self.expect_var_path(
+            "up_str",
+            type="std::unique_ptr<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::default_delete<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >",
+            summary='"hello"',
+            children=[ValueCheck(name="__value_", summary='"hello"')],
+        )
+
+        valobj = self.expect_var_path(
+            "up_user", type="std::unique_ptr<User, std::default_delete<User> >"
+        )
+        self.assertRegex(valobj.summary, "^User @ 0x0*[1-9a-f][0-9a-f]+$")
+        self.assertNotEqual(valobj.child[0].unsigned, 0)
+
+        valobj = self.expect_var_path(
+            "*up_user",
+            type="User",
+            children=[
+                ValueCheck(name="id", value="30"),
+                ValueCheck(name="name", summary='"steph"'),
+            ],
+        )
+        self.assertEqual(str(valobj), '(User) *__value_ = (id = 30, name = "steph")')
+
+        self.expect_var_path("up_user->id", type="int", value="30")
+        self.expect_var_path("up_user->name", type="std::string", summary='"steph"')

diff  --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/unique_ptr/main.cpp b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/unique_ptr/main.cpp
index 4ccffe2a006d..5201b2a6e9cb 100644
--- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/unique_ptr/main.cpp
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/unique_ptr/main.cpp
@@ -1,13 +1,18 @@
-#include <cstdio>
 #include <memory>
 #include <string>
 
+struct User {
+  int id = 30;
+  std::string name = "steph";
+};
+
 int main() {
   std::unique_ptr<int> up_empty;
   std::unique_ptr<int> up_int = std::make_unique<int>(10);
   std::unique_ptr<std::string> up_str = std::make_unique<std::string>("hello");
   std::unique_ptr<int> &up_int_ref = up_int;
   std::unique_ptr<int> &&up_int_ref_ref = std::make_unique<int>(10);
+  std::unique_ptr<User> up_user = std::make_unique<User>();
 
   return 0; // break here
 }


        


More information about the lldb-commits mailing list