[Lldb-commits] [lldb] a89e232 - [lldb][DataFormatter] Format libstdc++ unique_ptr like we do libc++ (#146909)
via lldb-commits
lldb-commits at lists.llvm.org
Fri Jul 4 01:18:27 PDT 2025
Author: Michael Buch
Date: 2025-07-04T09:18:24+01:00
New Revision: a89e232058a29260eb9bfe77b862715ce875f962
URL: https://github.com/llvm/llvm-project/commit/a89e232058a29260eb9bfe77b862715ce875f962
DIFF: https://github.com/llvm/llvm-project/commit/a89e232058a29260eb9bfe77b862715ce875f962.diff
LOG: [lldb][DataFormatter] Format libstdc++ unique_ptr like we do libc++ (#146909)
The only difference is that with libc++ the summary string contains the
derefernced pointer value. With libstdc++ we currently display the
pointer itself, which seems redundant. E.g.,
```
(std::unique_ptr<int>) iup = 0x55555556d2b0 {
pointer = 0x000055555556d2b0
}
(std::unique_ptr<std::basic_string<char> >) sup = 0x55555556d2d0 {
pointer = "foobar"
}
```
This patch moves the logic into a common helper that's shared between
the libc++ and libstdc++ formatters.
After this patch we can combine the libc++ and libstdc++ API tests (see
https://github.com/llvm/llvm-project/pull/146740).
Added:
Modified:
lldb/include/lldb/DataFormatters/FormattersHelpers.h
lldb/source/DataFormatters/FormattersHelpers.cpp
lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp
lldb/source/Plugins/Language/CPlusPlus/LibStdcppUniquePointer.cpp
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
lldb/test/API/functionalities/data-formatter/data-formatter-stl/libstdcpp/unique_ptr/TestDataFormatterStdUniquePtr.py
Removed:
################################################################################
diff --git a/lldb/include/lldb/DataFormatters/FormattersHelpers.h b/lldb/include/lldb/DataFormatters/FormattersHelpers.h
index 42699d0a0b1b1..97d367afc65d7 100644
--- a/lldb/include/lldb/DataFormatters/FormattersHelpers.h
+++ b/lldb/include/lldb/DataFormatters/FormattersHelpers.h
@@ -55,6 +55,11 @@ void AddFilter(TypeCategoryImpl::SharedPointer category_sp,
std::optional<size_t> ExtractIndexFromString(const char *item_name);
+/// Prints the summary for the pointer value of a C++
+/// std::unique_ptr/std::shared_ptr/std::weak_ptr.
+void DumpCxxSmartPtrPointerSummary(Stream &stream, ValueObject &ptr,
+ const TypeSummaryOptions &options);
+
Address GetArrayAddressOrPointerValue(ValueObject &valobj);
time_t GetOSXEpoch();
diff --git a/lldb/source/DataFormatters/FormattersHelpers.cpp b/lldb/source/DataFormatters/FormattersHelpers.cpp
index d7b058d91c4a3..81c76b06fc47a 100644
--- a/lldb/source/DataFormatters/FormattersHelpers.cpp
+++ b/lldb/source/DataFormatters/FormattersHelpers.cpp
@@ -126,3 +126,22 @@ lldb_private::formatters::GetArrayAddressOrPointerValue(ValueObject &valobj) {
return data_addr.address;
}
+
+void lldb_private::formatters::DumpCxxSmartPtrPointerSummary(
+ Stream &stream, ValueObject &ptr, const TypeSummaryOptions &options) {
+ if (ptr.GetValueAsUnsigned(0) == 0) {
+ stream.Printf("nullptr");
+ return;
+ }
+
+ Status error;
+ ValueObjectSP pointee_sp = ptr.Dereference(error);
+ if (!pointee_sp || !error.Success())
+ return;
+
+ if (!pointee_sp->DumpPrintableRepresentation(
+ stream, ValueObject::eValueObjectRepresentationStyleSummary,
+ lldb::eFormatInvalid,
+ ValueObject::PrintableRepresentationSpecialCases::eDisable, false))
+ stream.Printf("ptr = 0x%" PRIx64, ptr.GetValueAsUnsigned(0));
+}
diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp
index 7143089209dd3..009586f525282 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp
@@ -157,39 +157,38 @@ bool lldb_private::formatters::LibcxxSmartPointerSummaryProvider(
ValueObjectSP valobj_sp(valobj.GetNonSyntheticValue());
if (!valobj_sp)
return false;
- ValueObjectSP ptr_sp(valobj_sp->GetChildMemberWithName("__ptr_"));
- ValueObjectSP count_sp(
- valobj_sp->GetChildAtNamePath({"__cntrl_", "__shared_owners_"}));
- ValueObjectSP weakcount_sp(
- valobj_sp->GetChildAtNamePath({"__cntrl_", "__shared_weak_owners_"}));
- if (!ptr_sp)
+ ValueObjectSP ptr_sp(valobj_sp->GetChildMemberWithName("__ptr_"));
+ ValueObjectSP ctrl_sp(valobj_sp->GetChildMemberWithName("__cntrl_"));
+ if (!ctrl_sp || !ptr_sp)
return false;
- if (ptr_sp->GetValueAsUnsigned(0) == 0) {
- stream.Printf("nullptr");
+ DumpCxxSmartPtrPointerSummary(stream, *ptr_sp, options);
+
+ bool success;
+ uint64_t ctrl_addr = ctrl_sp->GetValueAsUnsigned(0, &success);
+ // Empty control field. We're done.
+ if (!success || ctrl_addr == 0)
return true;
- } else {
- bool print_pointee = false;
- Status error;
- ValueObjectSP pointee_sp = ptr_sp->Dereference(error);
- if (pointee_sp && error.Success()) {
- if (pointee_sp->DumpPrintableRepresentation(
- stream, ValueObject::eValueObjectRepresentationStyleSummary,
- lldb::eFormatInvalid,
- ValueObject::PrintableRepresentationSpecialCases::eDisable,
- false))
- print_pointee = true;
- }
- if (!print_pointee)
- stream.Printf("ptr = 0x%" PRIx64, ptr_sp->GetValueAsUnsigned(0));
+
+ if (auto count_sp = ctrl_sp->GetChildMemberWithName("__shared_owners_")) {
+ bool success;
+ uint64_t count = count_sp->GetValueAsUnsigned(0, &success);
+ if (!success)
+ return false;
+
+ stream.Printf(" strong=%" PRIu64, count + 1);
}
- if (count_sp)
- stream.Printf(" strong=%" PRIu64, 1 + count_sp->GetValueAsUnsigned(0));
+ if (auto weak_count_sp =
+ ctrl_sp->GetChildMemberWithName("__shared_weak_owners_")) {
+ bool success;
+ uint64_t count = weak_count_sp->GetValueAsUnsigned(0, &success);
+ if (!success)
+ return false;
- if (weakcount_sp)
- stream.Printf(" weak=%" PRIu64, 1 + weakcount_sp->GetValueAsUnsigned(0));
+ stream.Printf(" weak=%" PRIu64, count + 1);
+ }
return true;
}
@@ -210,24 +209,7 @@ bool lldb_private::formatters::LibcxxUniquePointerSummaryProvider(
if (!ptr_sp)
return false;
- if (ptr_sp->GetValueAsUnsigned(0) == 0) {
- stream.Printf("nullptr");
- return true;
- } else {
- bool print_pointee = false;
- Status error;
- ValueObjectSP pointee_sp = ptr_sp->Dereference(error);
- if (pointee_sp && error.Success()) {
- if (pointee_sp->DumpPrintableRepresentation(
- stream, ValueObject::eValueObjectRepresentationStyleSummary,
- lldb::eFormatInvalid,
- ValueObject::PrintableRepresentationSpecialCases::eDisable,
- false))
- print_pointee = true;
- }
- if (!print_pointee)
- stream.Printf("ptr = 0x%" PRIx64, ptr_sp->GetValueAsUnsigned(0));
- }
+ DumpCxxSmartPtrPointerSummary(stream, *ptr_sp, options);
return true;
}
diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibStdcppUniquePointer.cpp b/lldb/source/Plugins/Language/CPlusPlus/LibStdcppUniquePointer.cpp
index b47ff579b6a5e..e570a4bb1a886 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/LibStdcppUniquePointer.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/LibStdcppUniquePointer.cpp
@@ -156,14 +156,8 @@ bool LibStdcppUniquePtrSyntheticFrontEnd::GetSummary(
if (!m_ptr_obj)
return false;
- bool success;
- uint64_t ptr_value = m_ptr_obj->GetValueAsUnsigned(0, &success);
- if (!success)
- return false;
- if (ptr_value == 0)
- stream.Printf("nullptr");
- else
- stream.Printf("0x%" PRIx64, ptr_value);
+ DumpCxxSmartPtrPointerSummary(stream, *m_ptr_obj, options);
+
return true;
}
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 61c050b3bfa01..6ecf5ca88e90e 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
@@ -2,7 +2,6 @@
Test lldb data formatter for libc++ std::shared_ptr.
"""
-
import lldb
from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
@@ -91,6 +90,14 @@ def test_shared_ptr_variables(self):
self.expect_var_path("sp_user->id", type="int", value="30")
self.expect_var_path("sp_user->name", type="std::string", summary='"steph"')
+ valobj = self.expect_var_path(
+ "si", type="std::shared_ptr<int>", summary="47 strong=2 weak=1"
+ )
+
+ valobj = self.expect_var_path(
+ "sie", type="std::shared_ptr<int>", summary="nullptr strong=2 weak=1"
+ )
+
self.runCmd("settings set target.experimental.use-DIL true")
self.expect_var_path("ptr_node->value", value="1")
self.expect_var_path("ptr_node->next->value", value="2")
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
index 84a02ec13df1c..3ac86a3ee9843 100644
--- 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
@@ -22,5 +22,9 @@ int main() {
std::shared_ptr<NodeS>(new NodeS{nullptr, 2});
ptr_node = std::shared_ptr<NodeS>(new NodeS{std::move(ptr_node), 1});
+ // Construct empty shared_ptr with non-null control field.
+ std::shared_ptr<int> si(new int(47));
+ std::shared_ptr<int> sie(si, nullptr);
+
return 0; // break here
}
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libstdcpp/unique_ptr/TestDataFormatterStdUniquePtr.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libstdcpp/unique_ptr/TestDataFormatterStdUniquePtr.py
index 2301e5edfbd90..8f57dc88f3187 100644
--- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libstdcpp/unique_ptr/TestDataFormatterStdUniquePtr.py
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libstdcpp/unique_ptr/TestDataFormatterStdUniquePtr.py
@@ -2,7 +2,6 @@
Test lldb data formatter subsystem.
"""
-
import lldb
from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
@@ -31,15 +30,16 @@ def test_with_run_command(self):
self.assertTrue(frame.IsValid())
self.expect("frame variable nup", substrs=["nup = nullptr"])
- self.expect("frame variable iup", substrs=["iup = 0x"])
- self.expect("frame variable sup", substrs=["sup = 0x"])
+ self.expect("frame variable iup", substrs=["iup = 123"])
+ self.expect("frame variable sup", substrs=['sup = "foobar"'])
self.expect("frame variable ndp", substrs=["ndp = nullptr"])
self.expect(
- "frame variable idp", substrs=["idp = 0x", "deleter = ", "a = 1", "b = 2"]
+ "frame variable idp", substrs=["idp = 456", "deleter = ", "a = 1", "b = 2"]
)
self.expect(
- "frame variable sdp", substrs=["sdp = 0x", "deleter = ", "a = 3", "b = 4"]
+ "frame variable sdp",
+ substrs=['sdp = "baz"', "deleter = ", "a = 3", "b = 4"],
)
self.assertEqual(
@@ -106,13 +106,13 @@ def test_recursive_unique_ptr(self):
substrs=["stopped", "stop reason = breakpoint"],
)
- self.expect("frame variable f1->fp", substrs=["fp = 0x"])
+ self.expect("frame variable f1->fp", substrs=["fp = Foo @ 0x"])
self.expect(
- "frame variable --ptr-depth=1 f1->fp", substrs=["data = 2", "fp = 0x"]
+ "frame variable --ptr-depth=1 f1->fp", substrs=["data = 2", "fp = Foo @ 0x"]
)
self.expect(
"frame variable --ptr-depth=2 f1->fp",
- substrs=["data = 2", "fp = 0x", "data = 1"],
+ substrs=["data = 2", "fp = Foo @ 0x", "data = 1"],
)
frame = self.frame()
More information about the lldb-commits
mailing list