Skip to content

Commit d54d47c

Browse files
committed
[lldb][Formatters] Make libc++ and libstdc++ std::shared_ptr formatters consistent with each other (llvm#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 llvm#147141 (cherry picked from commit 6fec6a9)
1 parent cafdcab commit d54d47c

File tree

4 files changed

+46
-33
lines changed

4 files changed

+46
-33
lines changed

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

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,8 @@ lldb_private::formatters::LibCxxVectorIteratorSyntheticFrontEndCreator(
237237

238238
lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::
239239
LibcxxSharedPtrSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
240-
: SyntheticChildrenFrontEnd(*valobj_sp), m_cntrl(nullptr) {
240+
: SyntheticChildrenFrontEnd(*valobj_sp), m_cntrl(nullptr),
241+
m_ptr_obj(nullptr) {
241242
if (valobj_sp)
242243
Update();
243244
}
@@ -250,28 +251,25 @@ llvm::Expected<uint32_t> lldb_private::formatters::
250251
lldb::ValueObjectSP
251252
lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::GetChildAtIndex(
252253
uint32_t idx) {
253-
if (!m_cntrl)
254+
if (!m_cntrl || !m_ptr_obj)
254255
return lldb::ValueObjectSP();
255256

256257
ValueObjectSP valobj_sp = m_backend.GetSP();
257258
if (!valobj_sp)
258259
return lldb::ValueObjectSP();
259260

260261
if (idx == 0)
261-
return valobj_sp->GetChildMemberWithName("__ptr_");
262+
return m_ptr_obj->GetSP();
262263

263264
if (idx == 1) {
264-
if (auto ptr_sp = valobj_sp->GetChildMemberWithName("__ptr_")) {
265-
Status status;
266-
auto value_type_sp =
267-
valobj_sp->GetCompilerType()
268-
.GetTypeTemplateArgument(0).GetPointerType();
269-
ValueObjectSP cast_ptr_sp = ptr_sp->Cast(value_type_sp);
270-
ValueObjectSP value_sp = cast_ptr_sp->Dereference(status);
271-
if (status.Success()) {
272-
return value_sp;
273-
}
274-
}
265+
Status status;
266+
auto value_type_sp = valobj_sp->GetCompilerType()
267+
.GetTypeTemplateArgument(0)
268+
.GetPointerType();
269+
ValueObjectSP cast_ptr_sp = m_ptr_obj->Cast(value_type_sp);
270+
ValueObjectSP value_sp = cast_ptr_sp->Dereference(status);
271+
if (status.Success())
272+
return value_sp;
275273
}
276274

277275
return lldb::ValueObjectSP();
@@ -280,6 +278,7 @@ lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::GetChildAtIndex(
280278
lldb::ChildCacheState
281279
lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::Update() {
282280
m_cntrl = nullptr;
281+
m_ptr_obj = nullptr;
283282

284283
ValueObjectSP valobj_sp = m_backend.GetSP();
285284
if (!valobj_sp)
@@ -289,6 +288,12 @@ lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::Update() {
289288
if (!target_sp)
290289
return lldb::ChildCacheState::eRefetch;
291290

291+
auto ptr_obj_sp = valobj_sp->GetChildMemberWithName("__ptr_");
292+
if (!ptr_obj_sp)
293+
return lldb::ChildCacheState::eRefetch;
294+
295+
m_ptr_obj = ptr_obj_sp->Clone(ConstString("pointer")).get();
296+
292297
lldb::ValueObjectSP cntrl_sp(valobj_sp->GetChildMemberWithName("__cntrl_"));
293298

294299
m_cntrl = cntrl_sp.get(); // need to store the raw pointer to avoid a circular
@@ -303,10 +308,12 @@ bool lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::
303308

304309
size_t lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::
305310
GetIndexOfChildWithName(ConstString name) {
306-
if (name == "__ptr_")
311+
if (name == "__ptr_" || name == "pointer")
307312
return 0;
308-
if (name == "$$dereference$$")
313+
314+
if (name == "object" || name == "$$dereference$$")
309315
return 1;
316+
310317
return UINT32_MAX;
311318
}
312319

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ class LibcxxSharedPtrSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
110110

111111
private:
112112
ValueObject *m_cntrl;
113+
ValueObject *m_ptr_obj;
113114
};
114115

115116
class LibcxxUniquePtrSyntheticFrontEnd : public SyntheticChildrenFrontEnd {

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

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,7 @@ class LibStdcppSharedPtrSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
8080
// objects are only destroyed when every shared pointer to any of them
8181
// is destroyed, so we must not store a shared pointer to any ValueObject
8282
// derived from our backend ValueObject (since we're in the same cluster).
83-
ValueObject* m_ptr_obj = nullptr; // Underlying pointer (held, not owned)
84-
ValueObject* m_obj_obj = nullptr; // Underlying object (held, not owned)
83+
ValueObject *m_ptr_obj = nullptr; // Underlying pointer (held, not owned)
8584
};
8685

8786
} // end of anonymous namespace
@@ -385,15 +384,20 @@ lldb::ValueObjectSP
385384
LibStdcppSharedPtrSyntheticFrontEnd::GetChildAtIndex(uint32_t idx) {
386385
if (idx == 0)
387386
return m_ptr_obj->GetSP();
387+
388388
if (idx == 1) {
389-
if (m_ptr_obj && !m_obj_obj) {
390-
Status error;
391-
ValueObjectSP obj_obj = m_ptr_obj->Dereference(error);
392-
if (error.Success())
393-
m_obj_obj = obj_obj->Clone(ConstString("object")).get();
394-
}
395-
if (m_obj_obj)
396-
return m_obj_obj->GetSP();
389+
ValueObjectSP valobj_sp = m_backend.GetSP();
390+
if (!valobj_sp)
391+
return nullptr;
392+
393+
Status status;
394+
auto value_type_sp = valobj_sp->GetCompilerType()
395+
.GetTypeTemplateArgument(0)
396+
.GetPointerType();
397+
ValueObjectSP cast_ptr_sp = m_ptr_obj->Cast(value_type_sp);
398+
ValueObjectSP value_sp = cast_ptr_sp->Dereference(status);
399+
if (status.Success())
400+
return value_sp;
397401
}
398402
return lldb::ValueObjectSP();
399403
}
@@ -412,7 +416,6 @@ lldb::ChildCacheState LibStdcppSharedPtrSyntheticFrontEnd::Update() {
412416
return lldb::ChildCacheState::eRefetch;
413417

414418
m_ptr_obj = ptr_obj_sp->Clone(ConstString("pointer")).get();
415-
m_obj_obj = nullptr;
416419

417420
return lldb::ChildCacheState::eRefetch;
418421
}
@@ -423,8 +426,10 @@ size_t LibStdcppSharedPtrSyntheticFrontEnd::GetIndexOfChildWithName(
423426
ConstString name) {
424427
if (name == "pointer")
425428
return 0;
429+
426430
if (name == "object" || name == "$$dereference$$")
427431
return 1;
432+
428433
return UINT32_MAX;
429434
}
430435

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

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ def test_shared_ptr_variables(self):
2222
"sp_empty",
2323
type="std::shared_ptr<int>",
2424
summary="nullptr",
25-
children=[ValueCheck(name="__ptr_")],
25+
children=[ValueCheck(name="pointer")],
2626
)
2727
self.assertEqual(
2828
valobj.child[0].GetValueAsUnsigned(lldb.LLDB_INVALID_ADDRESS), 0
@@ -35,23 +35,23 @@ def test_shared_ptr_variables(self):
3535
valobj = self.expect_var_path(
3636
"sp_int",
3737
type="std::shared_ptr<int>",
38-
children=[ValueCheck(name="__ptr_")],
38+
children=[ValueCheck(name="pointer")],
3939
)
4040
self.assertRegex(valobj.summary, r"^10( strong=1)? weak=0$")
4141
self.assertNotEqual(valobj.child[0].unsigned, 0)
4242

4343
valobj = self.expect_var_path(
4444
"sp_int_ref",
4545
type="std::shared_ptr<int> &",
46-
children=[ValueCheck(name="__ptr_")],
46+
children=[ValueCheck(name="pointer")],
4747
)
4848
self.assertRegex(valobj.summary, r"^10( strong=1)? weak=0$")
4949
self.assertNotEqual(valobj.child[0].unsigned, 0)
5050

5151
valobj = self.expect_var_path(
5252
"sp_int_ref_ref",
5353
type="std::shared_ptr<int> &&",
54-
children=[ValueCheck(name="__ptr_")],
54+
children=[ValueCheck(name="pointer")],
5555
)
5656
self.assertRegex(valobj.summary, r"^10( strong=1)? weak=0$")
5757
self.assertNotEqual(valobj.child[0].unsigned, 0)
@@ -66,7 +66,7 @@ def test_shared_ptr_variables(self):
6666
valobj = self.expect_var_path(
6767
"sp_str",
6868
type="std::shared_ptr<" + string_type + ">",
69-
children=[ValueCheck(name="__ptr_", summary='"hello"')],
69+
children=[ValueCheck(name="pointer", summary='"hello"')],
7070
)
7171
self.assertRegex(valobj.summary, r'^"hello"( strong=1)? weak=0$')
7272

@@ -85,7 +85,7 @@ def test_shared_ptr_variables(self):
8585
ValueCheck(name="name", summary='"steph"'),
8686
],
8787
)
88-
self.assertEqual(str(valobj), '(User) *__ptr_ = (id = 30, name = "steph")')
88+
self.assertEqual(str(valobj), '(User) *pointer = (id = 30, name = "steph")')
8989

9090
self.expect_var_path("sp_user->id", type="int", value="30")
9191
self.expect_var_path("sp_user->name", type="std::string", summary='"steph"')

0 commit comments

Comments
 (0)