[Lldb-commits] [lldb] 6fec6a9 - [lldb][Formatters] Make libc++ and libstdc++ std::shared_ptr formatters consistent with each other (#147165)
via lldb-commits
lldb-commits at lists.llvm.org
Mon Jul 7 01:13:56 PDT 2025
Author: Michael Buch
Date: 2025-07-07T09:13:52+01:00
New Revision: 6fec6a98c01523a5478ce2aa9617e884dc772f6f
URL: https://github.com/llvm/llvm-project/commit/6fec6a98c01523a5478ce2aa9617e884dc772f6f
DIFF: https://github.com/llvm/llvm-project/commit/6fec6a98c01523a5478ce2aa9617e884dc772f6f.diff
LOG: [lldb][Formatters] Make libc++ and libstdc++ std::shared_ptr formatters consistent with each other (#147165)
This patch adjusts the libcxx and libstdcxx std::shared_ptr formatters
to look the same.
Changes to libcxx:
* Now creates a synthetic child called `pointer` (like we already do for
`std::unique_ptr`)
Changes to libstdcxx:
* When asked to dereference the pointer, cast the type of the result
ValueObject to the element type (which we get from the template argument
to std::shared_ptr).
Before:
```
(std::__shared_ptr<int, __gnu_cxx::_S_atomic>::element_type) *foo = 123
```
After:
```
(int) *foo = 123
```
Tested in https://github.com/llvm/llvm-project/pull/147141
Added:
Modified:
lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp
lldb/source/Plugins/Language/CPlusPlus/LibCxx.h
lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp
lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/shared_ptr/TestDataFormatterLibcxxSharedPtr.py
Removed:
################################################################################
diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp
index 9ee4e2ab0490e..7ecb484e35474 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp
@@ -238,7 +238,8 @@ lldb_private::formatters::LibCxxVectorIteratorSyntheticFrontEndCreator(
lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::
LibcxxSharedPtrSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
- : SyntheticChildrenFrontEnd(*valobj_sp), m_cntrl(nullptr) {
+ : SyntheticChildrenFrontEnd(*valobj_sp), m_cntrl(nullptr),
+ m_ptr_obj(nullptr) {
if (valobj_sp)
Update();
}
@@ -251,7 +252,7 @@ llvm::Expected<uint32_t> lldb_private::formatters::
lldb::ValueObjectSP
lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::GetChildAtIndex(
uint32_t idx) {
- if (!m_cntrl)
+ if (!m_cntrl || !m_ptr_obj)
return lldb::ValueObjectSP();
ValueObjectSP valobj_sp = m_backend.GetSP();
@@ -259,20 +260,17 @@ lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::GetChildAtIndex(
return lldb::ValueObjectSP();
if (idx == 0)
- return valobj_sp->GetChildMemberWithName("__ptr_");
+ return m_ptr_obj->GetSP();
if (idx == 1) {
- if (auto ptr_sp = valobj_sp->GetChildMemberWithName("__ptr_")) {
- Status status;
- auto value_type_sp =
- valobj_sp->GetCompilerType()
- .GetTypeTemplateArgument(0).GetPointerType();
- ValueObjectSP cast_ptr_sp = ptr_sp->Cast(value_type_sp);
- ValueObjectSP value_sp = cast_ptr_sp->Dereference(status);
- if (status.Success()) {
- return value_sp;
- }
- }
+ Status status;
+ auto value_type_sp = valobj_sp->GetCompilerType()
+ .GetTypeTemplateArgument(0)
+ .GetPointerType();
+ ValueObjectSP cast_ptr_sp = m_ptr_obj->Cast(value_type_sp);
+ ValueObjectSP value_sp = cast_ptr_sp->Dereference(status);
+ if (status.Success())
+ return value_sp;
}
return lldb::ValueObjectSP();
@@ -281,6 +279,7 @@ lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::GetChildAtIndex(
lldb::ChildCacheState
lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::Update() {
m_cntrl = nullptr;
+ m_ptr_obj = nullptr;
ValueObjectSP valobj_sp = m_backend.GetSP();
if (!valobj_sp)
@@ -290,6 +289,12 @@ lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::Update() {
if (!target_sp)
return lldb::ChildCacheState::eRefetch;
+ auto ptr_obj_sp = valobj_sp->GetChildMemberWithName("__ptr_");
+ if (!ptr_obj_sp)
+ return lldb::ChildCacheState::eRefetch;
+
+ m_ptr_obj = ptr_obj_sp->Clone(ConstString("pointer")).get();
+
lldb::ValueObjectSP cntrl_sp(valobj_sp->GetChildMemberWithName("__cntrl_"));
m_cntrl = cntrl_sp.get(); // need to store the raw pointer to avoid a circular
@@ -300,10 +305,12 @@ lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::Update() {
llvm::Expected<size_t>
lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::
GetIndexOfChildWithName(ConstString name) {
- if (name == "__ptr_")
+ if (name == "__ptr_" || name == "pointer")
return 0;
- if (name == "$$dereference$$")
+
+ if (name == "object" || name == "$$dereference$$")
return 1;
+
return llvm::createStringError("Type has no child named '%s'",
name.AsCString());
}
diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h
index 0c1f120ea708a..d88a6ecb1fa89 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h
+++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h
@@ -105,6 +105,7 @@ class LibcxxSharedPtrSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
private:
ValueObject *m_cntrl;
+ ValueObject *m_ptr_obj;
};
class LibcxxUniquePtrSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp b/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp
index 28b7c01ab1b5b..7668a87ce447e 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp
@@ -77,8 +77,7 @@ class LibStdcppSharedPtrSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
// objects are only destroyed when every shared pointer to any of them
// is destroyed, so we must not store a shared pointer to any ValueObject
// derived from our backend ValueObject (since we're in the same cluster).
- ValueObject* m_ptr_obj = nullptr; // Underlying pointer (held, not owned)
- ValueObject* m_obj_obj = nullptr; // Underlying object (held, not owned)
+ ValueObject *m_ptr_obj = nullptr; // Underlying pointer (held, not owned)
};
} // end of anonymous namespace
@@ -266,15 +265,20 @@ LibStdcppSharedPtrSyntheticFrontEnd::GetChildAtIndex(uint32_t idx) {
if (idx == 0)
return m_ptr_obj->GetSP();
+
if (idx == 1) {
- if (m_ptr_obj && !m_obj_obj) {
- Status error;
- ValueObjectSP obj_obj = m_ptr_obj->Dereference(error);
- if (error.Success())
- m_obj_obj = obj_obj->Clone(ConstString("object")).get();
- }
- if (m_obj_obj)
- return m_obj_obj->GetSP();
+ ValueObjectSP valobj_sp = m_backend.GetSP();
+ if (!valobj_sp)
+ return nullptr;
+
+ Status status;
+ auto value_type_sp = valobj_sp->GetCompilerType()
+ .GetTypeTemplateArgument(0)
+ .GetPointerType();
+ ValueObjectSP cast_ptr_sp = m_ptr_obj->Cast(value_type_sp);
+ ValueObjectSP value_sp = cast_ptr_sp->Dereference(status);
+ if (status.Success())
+ return value_sp;
}
return lldb::ValueObjectSP();
}
@@ -293,7 +297,6 @@ lldb::ChildCacheState LibStdcppSharedPtrSyntheticFrontEnd::Update() {
return lldb::ChildCacheState::eRefetch;
m_ptr_obj = ptr_obj_sp->Clone(ConstString("pointer")).get();
- m_obj_obj = nullptr;
return lldb::ChildCacheState::eRefetch;
}
@@ -302,8 +305,10 @@ llvm::Expected<size_t>
LibStdcppSharedPtrSyntheticFrontEnd::GetIndexOfChildWithName(ConstString name) {
if (name == "pointer")
return 0;
+
if (name == "object" || name == "$$dereference$$")
return 1;
+
return llvm::createStringError("Type has no child named '%s'",
name.AsCString());
}
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
index 25f616ff61046..a10ab8e863002 100644
--- 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
@@ -22,7 +22,7 @@ def test_shared_ptr_variables(self):
"sp_empty",
type="std::shared_ptr<int>",
summary="nullptr",
- children=[ValueCheck(name="__ptr_")],
+ children=[ValueCheck(name="pointer")],
)
self.assertEqual(
valobj.child[0].GetValueAsUnsigned(lldb.LLDB_INVALID_ADDRESS), 0
@@ -35,7 +35,7 @@ def test_shared_ptr_variables(self):
valobj = self.expect_var_path(
"sp_int",
type="std::shared_ptr<int>",
- children=[ValueCheck(name="__ptr_")],
+ children=[ValueCheck(name="pointer")],
)
self.assertRegex(valobj.summary, r"^10( strong=1)? weak=0$")
self.assertNotEqual(valobj.child[0].unsigned, 0)
@@ -43,7 +43,7 @@ def test_shared_ptr_variables(self):
valobj = self.expect_var_path(
"sp_int_ref",
type="std::shared_ptr<int> &",
- children=[ValueCheck(name="__ptr_")],
+ children=[ValueCheck(name="pointer")],
)
self.assertRegex(valobj.summary, r"^10( strong=1)? weak=0$")
self.assertNotEqual(valobj.child[0].unsigned, 0)
@@ -51,7 +51,7 @@ def test_shared_ptr_variables(self):
valobj = self.expect_var_path(
"sp_int_ref_ref",
type="std::shared_ptr<int> &&",
- children=[ValueCheck(name="__ptr_")],
+ children=[ValueCheck(name="pointer")],
)
self.assertRegex(valobj.summary, r"^10( strong=1)? weak=0$")
self.assertNotEqual(valobj.child[0].unsigned, 0)
@@ -66,7 +66,7 @@ def test_shared_ptr_variables(self):
valobj = self.expect_var_path(
"sp_str",
type="std::shared_ptr<" + string_type + ">",
- children=[ValueCheck(name="__ptr_", summary='"hello"')],
+ children=[ValueCheck(name="pointer", summary='"hello"')],
)
self.assertRegex(valobj.summary, r'^"hello"( strong=1)? weak=0$')
@@ -85,7 +85,7 @@ def test_shared_ptr_variables(self):
ValueCheck(name="name", summary='"steph"'),
],
)
- self.assertEqual(str(valobj), '(User) *__ptr_ = (id = 30, name = "steph")')
+ self.assertEqual(str(valobj), '(User) *pointer = (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"')
More information about the lldb-commits
mailing list