Skip to content

Commit a89e232

Browse files
authored
[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 #146740).
1 parent 25f05c0 commit a89e232

File tree

7 files changed

+72
-61
lines changed

7 files changed

+72
-61
lines changed

lldb/include/lldb/DataFormatters/FormattersHelpers.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,11 @@ void AddFilter(TypeCategoryImpl::SharedPointer category_sp,
5555

5656
std::optional<size_t> ExtractIndexFromString(const char *item_name);
5757

58+
/// Prints the summary for the pointer value of a C++
59+
/// std::unique_ptr/std::shared_ptr/std::weak_ptr.
60+
void DumpCxxSmartPtrPointerSummary(Stream &stream, ValueObject &ptr,
61+
const TypeSummaryOptions &options);
62+
5863
Address GetArrayAddressOrPointerValue(ValueObject &valobj);
5964

6065
time_t GetOSXEpoch();

lldb/source/DataFormatters/FormattersHelpers.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,3 +126,22 @@ lldb_private::formatters::GetArrayAddressOrPointerValue(ValueObject &valobj) {
126126

127127
return data_addr.address;
128128
}
129+
130+
void lldb_private::formatters::DumpCxxSmartPtrPointerSummary(
131+
Stream &stream, ValueObject &ptr, const TypeSummaryOptions &options) {
132+
if (ptr.GetValueAsUnsigned(0) == 0) {
133+
stream.Printf("nullptr");
134+
return;
135+
}
136+
137+
Status error;
138+
ValueObjectSP pointee_sp = ptr.Dereference(error);
139+
if (!pointee_sp || !error.Success())
140+
return;
141+
142+
if (!pointee_sp->DumpPrintableRepresentation(
143+
stream, ValueObject::eValueObjectRepresentationStyleSummary,
144+
lldb::eFormatInvalid,
145+
ValueObject::PrintableRepresentationSpecialCases::eDisable, false))
146+
stream.Printf("ptr = 0x%" PRIx64, ptr.GetValueAsUnsigned(0));
147+
}

lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp

Lines changed: 26 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -157,39 +157,38 @@ bool lldb_private::formatters::LibcxxSmartPointerSummaryProvider(
157157
ValueObjectSP valobj_sp(valobj.GetNonSyntheticValue());
158158
if (!valobj_sp)
159159
return false;
160-
ValueObjectSP ptr_sp(valobj_sp->GetChildMemberWithName("__ptr_"));
161-
ValueObjectSP count_sp(
162-
valobj_sp->GetChildAtNamePath({"__cntrl_", "__shared_owners_"}));
163-
ValueObjectSP weakcount_sp(
164-
valobj_sp->GetChildAtNamePath({"__cntrl_", "__shared_weak_owners_"}));
165160

166-
if (!ptr_sp)
161+
ValueObjectSP ptr_sp(valobj_sp->GetChildMemberWithName("__ptr_"));
162+
ValueObjectSP ctrl_sp(valobj_sp->GetChildMemberWithName("__cntrl_"));
163+
if (!ctrl_sp || !ptr_sp)
167164
return false;
168165

169-
if (ptr_sp->GetValueAsUnsigned(0) == 0) {
170-
stream.Printf("nullptr");
166+
DumpCxxSmartPtrPointerSummary(stream, *ptr_sp, options);
167+
168+
bool success;
169+
uint64_t ctrl_addr = ctrl_sp->GetValueAsUnsigned(0, &success);
170+
// Empty control field. We're done.
171+
if (!success || ctrl_addr == 0)
171172
return true;
172-
} else {
173-
bool print_pointee = false;
174-
Status error;
175-
ValueObjectSP pointee_sp = ptr_sp->Dereference(error);
176-
if (pointee_sp && error.Success()) {
177-
if (pointee_sp->DumpPrintableRepresentation(
178-
stream, ValueObject::eValueObjectRepresentationStyleSummary,
179-
lldb::eFormatInvalid,
180-
ValueObject::PrintableRepresentationSpecialCases::eDisable,
181-
false))
182-
print_pointee = true;
183-
}
184-
if (!print_pointee)
185-
stream.Printf("ptr = 0x%" PRIx64, ptr_sp->GetValueAsUnsigned(0));
173+
174+
if (auto count_sp = ctrl_sp->GetChildMemberWithName("__shared_owners_")) {
175+
bool success;
176+
uint64_t count = count_sp->GetValueAsUnsigned(0, &success);
177+
if (!success)
178+
return false;
179+
180+
stream.Printf(" strong=%" PRIu64, count + 1);
186181
}
187182

188-
if (count_sp)
189-
stream.Printf(" strong=%" PRIu64, 1 + count_sp->GetValueAsUnsigned(0));
183+
if (auto weak_count_sp =
184+
ctrl_sp->GetChildMemberWithName("__shared_weak_owners_")) {
185+
bool success;
186+
uint64_t count = weak_count_sp->GetValueAsUnsigned(0, &success);
187+
if (!success)
188+
return false;
190189

191-
if (weakcount_sp)
192-
stream.Printf(" weak=%" PRIu64, 1 + weakcount_sp->GetValueAsUnsigned(0));
190+
stream.Printf(" weak=%" PRIu64, count + 1);
191+
}
193192

194193
return true;
195194
}
@@ -210,24 +209,7 @@ bool lldb_private::formatters::LibcxxUniquePointerSummaryProvider(
210209
if (!ptr_sp)
211210
return false;
212211

213-
if (ptr_sp->GetValueAsUnsigned(0) == 0) {
214-
stream.Printf("nullptr");
215-
return true;
216-
} else {
217-
bool print_pointee = false;
218-
Status error;
219-
ValueObjectSP pointee_sp = ptr_sp->Dereference(error);
220-
if (pointee_sp && error.Success()) {
221-
if (pointee_sp->DumpPrintableRepresentation(
222-
stream, ValueObject::eValueObjectRepresentationStyleSummary,
223-
lldb::eFormatInvalid,
224-
ValueObject::PrintableRepresentationSpecialCases::eDisable,
225-
false))
226-
print_pointee = true;
227-
}
228-
if (!print_pointee)
229-
stream.Printf("ptr = 0x%" PRIx64, ptr_sp->GetValueAsUnsigned(0));
230-
}
212+
DumpCxxSmartPtrPointerSummary(stream, *ptr_sp, options);
231213

232214
return true;
233215
}

lldb/source/Plugins/Language/CPlusPlus/LibStdcppUniquePointer.cpp

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -156,14 +156,8 @@ bool LibStdcppUniquePtrSyntheticFrontEnd::GetSummary(
156156
if (!m_ptr_obj)
157157
return false;
158158

159-
bool success;
160-
uint64_t ptr_value = m_ptr_obj->GetValueAsUnsigned(0, &success);
161-
if (!success)
162-
return false;
163-
if (ptr_value == 0)
164-
stream.Printf("nullptr");
165-
else
166-
stream.Printf("0x%" PRIx64, ptr_value);
159+
DumpCxxSmartPtrPointerSummary(stream, *m_ptr_obj, options);
160+
167161
return true;
168162
}
169163

lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/shared_ptr/TestDataFormatterLibcxxSharedPtr.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
Test lldb data formatter for libc++ std::shared_ptr.
33
"""
44

5-
65
import lldb
76
from lldbsuite.test.decorators import *
87
from lldbsuite.test.lldbtest import *
@@ -91,6 +90,14 @@ def test_shared_ptr_variables(self):
9190
self.expect_var_path("sp_user->id", type="int", value="30")
9291
self.expect_var_path("sp_user->name", type="std::string", summary='"steph"')
9392

93+
valobj = self.expect_var_path(
94+
"si", type="std::shared_ptr<int>", summary="47 strong=2 weak=1"
95+
)
96+
97+
valobj = self.expect_var_path(
98+
"sie", type="std::shared_ptr<int>", summary="nullptr strong=2 weak=1"
99+
)
100+
94101
self.runCmd("settings set target.experimental.use-DIL true")
95102
self.expect_var_path("ptr_node->value", value="1")
96103
self.expect_var_path("ptr_node->next->value", value="2")

lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/shared_ptr/main.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,9 @@ int main() {
2222
std::shared_ptr<NodeS>(new NodeS{nullptr, 2});
2323
ptr_node = std::shared_ptr<NodeS>(new NodeS{std::move(ptr_node), 1});
2424

25+
// Construct empty shared_ptr with non-null control field.
26+
std::shared_ptr<int> si(new int(47));
27+
std::shared_ptr<int> sie(si, nullptr);
28+
2529
return 0; // break here
2630
}

lldb/test/API/functionalities/data-formatter/data-formatter-stl/libstdcpp/unique_ptr/TestDataFormatterStdUniquePtr.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
Test lldb data formatter subsystem.
33
"""
44

5-
65
import lldb
76
from lldbsuite.test.decorators import *
87
from lldbsuite.test.lldbtest import *
@@ -31,15 +30,16 @@ def test_with_run_command(self):
3130
self.assertTrue(frame.IsValid())
3231

3332
self.expect("frame variable nup", substrs=["nup = nullptr"])
34-
self.expect("frame variable iup", substrs=["iup = 0x"])
35-
self.expect("frame variable sup", substrs=["sup = 0x"])
33+
self.expect("frame variable iup", substrs=["iup = 123"])
34+
self.expect("frame variable sup", substrs=['sup = "foobar"'])
3635

3736
self.expect("frame variable ndp", substrs=["ndp = nullptr"])
3837
self.expect(
39-
"frame variable idp", substrs=["idp = 0x", "deleter = ", "a = 1", "b = 2"]
38+
"frame variable idp", substrs=["idp = 456", "deleter = ", "a = 1", "b = 2"]
4039
)
4140
self.expect(
42-
"frame variable sdp", substrs=["sdp = 0x", "deleter = ", "a = 3", "b = 4"]
41+
"frame variable sdp",
42+
substrs=['sdp = "baz"', "deleter = ", "a = 3", "b = 4"],
4343
)
4444

4545
self.assertEqual(
@@ -106,13 +106,13 @@ def test_recursive_unique_ptr(self):
106106
substrs=["stopped", "stop reason = breakpoint"],
107107
)
108108

109-
self.expect("frame variable f1->fp", substrs=["fp = 0x"])
109+
self.expect("frame variable f1->fp", substrs=["fp = Foo @ 0x"])
110110
self.expect(
111-
"frame variable --ptr-depth=1 f1->fp", substrs=["data = 2", "fp = 0x"]
111+
"frame variable --ptr-depth=1 f1->fp", substrs=["data = 2", "fp = Foo @ 0x"]
112112
)
113113
self.expect(
114114
"frame variable --ptr-depth=2 f1->fp",
115-
substrs=["data = 2", "fp = 0x", "data = 1"],
115+
substrs=["data = 2", "fp = Foo @ 0x", "data = 1"],
116116
)
117117

118118
frame = self.frame()

0 commit comments

Comments
 (0)