mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-11-23 22:00:10 +00:00
[lldb][DataFormatter] Add dereference support to libstdcpp std::shared_ptr formatter
This mimicks the implementation of the libstdcpp std::unique_ptr formatter. This has been attempted several years ago in `0789722d85cf1f1fdbe2ffb2245ea0ba034a9f94` but was reverted in `e7dd3972094c2f2fb42dc9d4d5344e54a431e2ce`. The difference to the original patch is that we now maintain a `$$dereference$$` member and we only store weak pointers to the other children inside the synthetic frontend. This is what the libc++ formatters do to prevent the recursion mentioned in the revert commit.
This commit is contained in:
parent
a2ac3678cd
commit
44bb442fd5
@ -73,6 +73,15 @@ public:
|
||||
bool MightHaveChildren() override;
|
||||
|
||||
size_t GetIndexOfChildWithName(ConstString name) override;
|
||||
private:
|
||||
|
||||
// The lifetime of a ValueObject and all its derivative ValueObjects
|
||||
// (children, clones, etc.) is managed by a ClusterManager. These
|
||||
// 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)
|
||||
};
|
||||
|
||||
} // end of anonymous namespace
|
||||
@ -367,24 +376,48 @@ size_t LibStdcppSharedPtrSyntheticFrontEnd::CalculateNumChildren() { return 1; }
|
||||
|
||||
lldb::ValueObjectSP
|
||||
LibStdcppSharedPtrSyntheticFrontEnd::GetChildAtIndex(size_t idx) {
|
||||
ValueObjectSP valobj_sp = m_backend.GetSP();
|
||||
if (!valobj_sp)
|
||||
return lldb::ValueObjectSP();
|
||||
|
||||
if (idx == 0)
|
||||
return valobj_sp->GetChildMemberWithName(ConstString("_M_ptr"), true);
|
||||
else
|
||||
return m_ptr_obj->GetSP();
|
||||
if (idx == 1)
|
||||
return m_obj_obj->GetSP();
|
||||
|
||||
return lldb::ValueObjectSP();
|
||||
}
|
||||
|
||||
bool LibStdcppSharedPtrSyntheticFrontEnd::Update() { return false; }
|
||||
bool LibStdcppSharedPtrSyntheticFrontEnd::Update() {
|
||||
auto backend = m_backend.GetSP();
|
||||
if (!backend)
|
||||
return false;
|
||||
|
||||
auto valobj_sp = backend->GetNonSyntheticValue();
|
||||
if (!valobj_sp)
|
||||
return false;
|
||||
|
||||
auto ptr_obj_sp = valobj_sp->GetChildMemberWithName(ConstString("_M_ptr"), true);
|
||||
if (!ptr_obj_sp)
|
||||
return false;
|
||||
|
||||
m_ptr_obj = ptr_obj_sp->Clone(ConstString("pointer")).get();
|
||||
|
||||
if (m_ptr_obj) {
|
||||
Status error;
|
||||
ValueObjectSP obj_obj = m_ptr_obj->Dereference(error);
|
||||
if (error.Success()) {
|
||||
m_obj_obj = obj_obj->Clone(ConstString("object")).get();
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool LibStdcppSharedPtrSyntheticFrontEnd::MightHaveChildren() { return true; }
|
||||
|
||||
size_t LibStdcppSharedPtrSyntheticFrontEnd::GetIndexOfChildWithName(
|
||||
ConstString name) {
|
||||
if (name == "_M_ptr")
|
||||
if (name == "pointer")
|
||||
return 0;
|
||||
if (name == "object" || name == "$$dereference$$")
|
||||
return 1;
|
||||
return UINT32_MAX;
|
||||
}
|
||||
|
||||
|
@ -33,6 +33,13 @@ class StdSmartPtrDataFormatterTestCase(TestBase):
|
||||
self.expect("frame variable iwp", substrs=['iwp = 123'])
|
||||
self.expect("frame variable swp", substrs=['swp = "foobar"'])
|
||||
|
||||
self.expect("frame variable *nsp", substrs=['*nsp = <parent is NULL>'])
|
||||
self.expect("frame variable *isp", substrs=['*isp = 123'])
|
||||
self.expect("frame variable *ssp", substrs=['*ssp = "foobar"'])
|
||||
self.expect("frame variable *fsp", substrs=['*fsp = (mem = 5)'])
|
||||
|
||||
self.expect("frame variable fsp->mem", substrs=['(int) fsp->mem = 5'])
|
||||
|
||||
self.runCmd("continue")
|
||||
|
||||
self.expect("frame variable nsp", substrs=['nsp = nullptr'])
|
||||
|
@ -1,12 +1,17 @@
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
struct Foo {
|
||||
int mem = 5;
|
||||
};
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
std::shared_ptr<char> nsp;
|
||||
std::shared_ptr<int> isp(new int{123});
|
||||
std::shared_ptr<std::string> ssp = std::make_shared<std::string>("foobar");
|
||||
std::shared_ptr<Foo> fsp = std::make_shared<Foo>();
|
||||
|
||||
std::weak_ptr<char> nwp;
|
||||
std::weak_ptr<int> iwp = isp;
|
||||
@ -15,6 +20,7 @@ main()
|
||||
nsp.reset(); // Set break point at this line.
|
||||
isp.reset();
|
||||
ssp.reset();
|
||||
fsp.reset();
|
||||
|
||||
return 0; // Set break point at this line.
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user