[Lldb-commits] [lldb] 0ac42fd - [lldb] Add deref support and tests to shared_ptr synthetic

Dave Lee via lldb-commits lldb-commits at lists.llvm.org
Tue Feb 23 09:04:03 PST 2021


Author: Dave Lee
Date: 2021-02-23T09:03:46-08:00
New Revision: 0ac42fd26d738b2d7b2811fc995bd7cacf994144

URL: https://github.com/llvm/llvm-project/commit/0ac42fd26d738b2d7b2811fc995bd7cacf994144
DIFF: https://github.com/llvm/llvm-project/commit/0ac42fd26d738b2d7b2811fc995bd7cacf994144.diff

LOG: [lldb] Add deref support and tests to shared_ptr synthetic

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

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

Also, add API tests for `std::shared_ptr`, previously there were none.

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

Added: 
    lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/shared_ptr/Makefile
    lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/shared_ptr/TestDataFormatterLibcxxSharedPtr.py
    lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/shared_ptr/main.cpp

Modified: 
    lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp
    lldb/source/Plugins/Language/CPlusPlus/LibCxx.h

Removed: 
    


################################################################################
diff  --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp
index 2b16ebe79daf..925076f10d72 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp
@@ -379,8 +379,7 @@ lldb_private::formatters::LibCxxVectorIteratorSyntheticFrontEndCreator(
 
 lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::
     LibcxxSharedPtrSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
-    : SyntheticChildrenFrontEnd(*valobj_sp), m_cntrl(nullptr), m_count_sp(),
-      m_weak_count_sp(), m_ptr_size(0), m_byte_order(lldb::eByteOrderInvalid) {
+    : SyntheticChildrenFrontEnd(*valobj_sp), m_cntrl(nullptr) {
   if (valobj_sp)
     Update();
 }
@@ -403,42 +402,23 @@ lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::GetChildAtIndex(
   if (idx == 0)
     return valobj_sp->GetChildMemberWithName(ConstString("__ptr_"), true);
 
-  if (idx > 2)
-    return lldb::ValueObjectSP();
-
   if (idx == 1) {
-    if (!m_count_sp) {
-      ValueObjectSP shared_owners_sp(m_cntrl->GetChildMemberWithName(
-          ConstString("__shared_owners_"), true));
-      if (!shared_owners_sp)
-        return lldb::ValueObjectSP();
-      uint64_t count = 1 + shared_owners_sp->GetValueAsUnsigned(0);
-      DataExtractor data(&count, 8, m_byte_order, m_ptr_size);
-      m_count_sp = CreateValueObjectFromData(
-          "count", data, valobj_sp->GetExecutionContextRef(),
-          shared_owners_sp->GetCompilerType());
-    }
-    return m_count_sp;
-  } else /* if (idx == 2) */
-  {
-    if (!m_weak_count_sp) {
-      ValueObjectSP shared_weak_owners_sp(m_cntrl->GetChildMemberWithName(
-          ConstString("__shared_weak_owners_"), true));
-      if (!shared_weak_owners_sp)
-        return lldb::ValueObjectSP();
-      uint64_t count = 1 + shared_weak_owners_sp->GetValueAsUnsigned(0);
-      DataExtractor data(&count, 8, m_byte_order, m_ptr_size);
-      m_weak_count_sp = CreateValueObjectFromData(
-          "count", data, valobj_sp->GetExecutionContextRef(),
-          shared_weak_owners_sp->GetCompilerType());
+    if (auto ptr_sp =
+            valobj_sp->GetChildMemberWithName(ConstString("__ptr_"), true)) {
+      Status status;
+      auto value_sp = ptr_sp->Dereference(status);
+      if (status.Success()) {
+        auto value_type_sp =
+            valobj_sp->GetCompilerType().GetTypeTemplateArgument(0);
+        return value_sp->Cast(value_type_sp);
+      }
     }
-    return m_weak_count_sp;
   }
+
+  return lldb::ValueObjectSP();
 }
 
 bool lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::Update() {
-  m_count_sp.reset();
-  m_weak_count_sp.reset();
   m_cntrl = nullptr;
 
   ValueObjectSP valobj_sp = m_backend.GetSP();
@@ -449,9 +429,6 @@ bool lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::Update() {
   if (!target_sp)
     return false;
 
-  m_byte_order = target_sp->GetArchitecture().GetByteOrder();
-  m_ptr_size = target_sp->GetArchitecture().GetAddressByteSize();
-
   lldb::ValueObjectSP cntrl_sp(
       valobj_sp->GetChildMemberWithName(ConstString("__cntrl_"), true));
 
@@ -469,10 +446,8 @@ size_t lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::
     GetIndexOfChildWithName(ConstString name) {
   if (name == "__ptr_")
     return 0;
-  if (name == "count")
+  if (name == "$$dereference$$")
     return 1;
-  if (name == "weak_count")
-    return 2;
   return UINT32_MAX;
 }
 

diff  --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h
index ea5a7c178178..907025fe8ac8 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h
+++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h
@@ -105,10 +105,6 @@ class LibcxxSharedPtrSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
 
 private:
   ValueObject *m_cntrl;
-  lldb::ValueObjectSP m_count_sp;
-  lldb::ValueObjectSP m_weak_count_sp;
-  uint8_t m_ptr_size;
-  lldb::ByteOrder m_byte_order;
 };
 
 class LibcxxUniquePtrSyntheticFrontEnd : public SyntheticChildrenFrontEnd {

diff  --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/shared_ptr/Makefile b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/shared_ptr/Makefile
new file mode 100644
index 000000000000..7e57f13aea55
--- /dev/null
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/shared_ptr/Makefile
@@ -0,0 +1,6 @@
+CXX_SOURCES := main.cpp
+
+USE_LIBCPP := 1
+
+CXXFLAGS_EXTRAS := -std=c++14
+include Makefile.rules

diff  --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/shared_ptr/TestDataFormatterLibcxxSharedPtr.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/shared_ptr/TestDataFormatterLibcxxSharedPtr.py
new file mode 100644
index 000000000000..8e77d53225a7
--- /dev/null
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/shared_ptr/TestDataFormatterLibcxxSharedPtr.py
@@ -0,0 +1,88 @@
+"""
+Test lldb data formatter for libc++ std::shared_ptr.
+"""
+
+
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class TestCase(TestBase):
+
+    mydir = TestBase.compute_mydir(__file__)
+
+    @add_test_categories(["libc++"])
+    def test_shared_ptr_variables(self):
+        """Test `frame variable` output for `std::shared_ptr` types."""
+        self.build()
+
+        lldbutil.run_to_source_breakpoint(
+            self, "// break here", lldb.SBFileSpec("main.cpp")
+        )
+
+        valobj = self.expect_var_path(
+            "sp_empty",
+            type="std::shared_ptr<int>",
+            summary="nullptr",
+            children=[ValueCheck(name="__ptr_")],
+        )
+        self.assertEqual(
+            valobj.child[0].GetValueAsUnsigned(lldb.LLDB_INVALID_ADDRESS), 0
+        )
+
+        self.expect(
+            "frame variable *sp_empty", substrs=["(int) *sp_empty = <parent is NULL>"]
+        )
+
+        valobj = self.expect_var_path(
+            "sp_int",
+            type="std::shared_ptr<int>",
+            children=[ValueCheck(name="__ptr_")],
+        )
+        self.assertRegex(valobj.summary, r"^10( strong=1)? weak=1$")
+        self.assertNotEqual(valobj.child[0].unsigned, 0)
+
+        valobj = self.expect_var_path(
+            "sp_int_ref",
+            type="std::shared_ptr<int> &",
+            children=[ValueCheck(name="__ptr_")],
+        )
+        self.assertRegex(valobj.summary, r"^10( strong=1)? weak=1$")
+        self.assertNotEqual(valobj.child[0].unsigned, 0)
+
+        valobj = self.expect_var_path(
+            "sp_int_ref_ref",
+            type="std::shared_ptr<int> &&",
+            children=[ValueCheck(name="__ptr_")],
+        )
+        self.assertRegex(valobj.summary, r"^10( strong=1)? weak=1$")
+        self.assertNotEqual(valobj.child[0].unsigned, 0)
+
+        valobj = self.expect_var_path(
+            "sp_str",
+            type="std::shared_ptr<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >",
+            children=[ValueCheck(name="__ptr_", summary='"hello"')],
+        )
+        self.assertRegex(valobj.summary, r'^"hello"( strong=1)? weak=1$')
+
+        valobj = self.expect_var_path("sp_user", type="std::shared_ptr<User>")
+        self.assertRegex(
+            valobj.summary,
+            "^std(::__1)?::shared_ptr<User>::element_type @ 0x0*[1-9a-f][0-9a-f]+( strong=1)? weak=1",
+        )
+        self.assertNotEqual(valobj.child[0].unsigned, 0)
+
+        valobj = self.expect_var_path(
+            "*sp_user",
+            type="User",
+            children=[
+                ValueCheck(name="id", value="30"),
+                ValueCheck(name="name", summary='"steph"'),
+            ],
+        )
+        self.assertEqual(str(valobj), '(User) *__ptr_ = (id = 30, name = "steph")')
+
+        self.expect_var_path("sp_user->id", type="int", value="30")
+        self.expect_var_path("sp_user->name", type="std::string", summary='"steph"')

diff  --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/shared_ptr/main.cpp b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/shared_ptr/main.cpp
new file mode 100644
index 000000000000..026bfe24e72e
--- /dev/null
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/shared_ptr/main.cpp
@@ -0,0 +1,18 @@
+#include <memory>
+#include <string>
+
+struct User {
+  int id = 30;
+  std::string name = "steph";
+};
+
+int main() {
+  std::shared_ptr<int> sp_empty;
+  std::shared_ptr<int> sp_int = std::make_shared<int>(10);
+  std::shared_ptr<std::string> sp_str = std::make_shared<std::string>("hello");
+  std::shared_ptr<int> &sp_int_ref = sp_int;
+  std::shared_ptr<int> &&sp_int_ref_ref = std::make_shared<int>(10);
+  std::shared_ptr<User> sp_user = std::make_shared<User>();
+
+  return 0; // break here
+}


        


More information about the lldb-commits mailing list