Skip to content

Commit 21e1d0e

Browse files
committed
[lldb][DataFormatter] Format libstdc++ unique_ptr like we do libc++ (llvm#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 llvm#146740). (cherry picked from commit a89e232)
1 parent 996bc6b commit 21e1d0e

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
@@ -64,6 +64,11 @@ void AddFilter(TypeCategoryImpl::SharedPointer category_sp,
6464

6565
size_t ExtractIndexFromString(const char *item_name);
6666

67+
/// Prints the summary for the pointer value of a C++
68+
/// std::unique_ptr/std::shared_ptr/std::weak_ptr.
69+
void DumpCxxSmartPtrPointerSummary(Stream &stream, ValueObject &ptr,
70+
const TypeSummaryOptions &options);
71+
6772
Address GetArrayAddressOrPointerValue(ValueObject &valobj);
6873

6974
time_t GetOSXEpoch();

lldb/source/DataFormatters/FormattersHelpers.cpp

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

431431
return data_addr;
432432
}
433+
434+
void lldb_private::formatters::DumpCxxSmartPtrPointerSummary(
435+
Stream &stream, ValueObject &ptr, const TypeSummaryOptions &options) {
436+
if (ptr.GetValueAsUnsigned(0) == 0) {
437+
stream.Printf("nullptr");
438+
return;
439+
}
440+
441+
Status error;
442+
ValueObjectSP pointee_sp = ptr.Dereference(error);
443+
if (!pointee_sp || !error.Success())
444+
return;
445+
446+
if (!pointee_sp->DumpPrintableRepresentation(
447+
stream, ValueObject::eValueObjectRepresentationStyleSummary,
448+
lldb::eFormatInvalid,
449+
ValueObject::PrintableRepresentationSpecialCases::eDisable, false))
450+
stream.Printf("ptr = 0x%" PRIx64, ptr.GetValueAsUnsigned(0));
451+
}

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

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

165-
if (!ptr_sp)
160+
ValueObjectSP ptr_sp(valobj_sp->GetChildMemberWithName("__ptr_"));
161+
ValueObjectSP ctrl_sp(valobj_sp->GetChildMemberWithName("__cntrl_"));
162+
if (!ctrl_sp || !ptr_sp)
166163
return false;
167164

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

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

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

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

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

231213
return true;
232214
}

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

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -159,14 +159,8 @@ bool LibStdcppUniquePtrSyntheticFrontEnd::GetSummary(
159159
if (!m_ptr_obj)
160160
return false;
161161

162-
bool success;
163-
uint64_t ptr_value = m_ptr_obj->GetValueAsUnsigned(0, &success);
164-
if (!success)
165-
return false;
166-
if (ptr_value == 0)
167-
stream.Printf("nullptr");
168-
else
169-
stream.Printf("0x%" PRIx64, ptr_value);
162+
DumpCxxSmartPtrPointerSummary(stream, *m_ptr_obj, options);
163+
170164
return true;
171165
}
172166

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 *
@@ -90,3 +89,11 @@ def test_shared_ptr_variables(self):
9089

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"')
92+
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+
)

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
@@ -14,5 +14,9 @@ int main() {
1414
std::shared_ptr<int> &&sp_int_ref_ref = std::make_shared<int>(10);
1515
std::shared_ptr<User> sp_user = std::make_shared<User>();
1616

17+
// Construct empty shared_ptr with non-null control field.
18+
std::shared_ptr<int> si(new int(47));
19+
std::shared_ptr<int> sie(si, nullptr);
20+
1721
return 0; // break here
1822
}

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)