diff options
author | Michael Buch <michaelbuch12@gmail.com> | 2023-05-24 00:01:47 +0100 |
---|---|---|
committer | Michael Buch <michaelbuch12@gmail.com> | 2023-05-24 13:01:11 +0100 |
commit | 44bb442fd5be3860e7819cb216621b5ea59970c3 (patch) | |
tree | 096a6d3d7aa5504cc73c5683c023b8a3626db25f /lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp | |
parent | a2ac3678cd337865ad6a8852acf94c8c5f0b03ea (diff) | |
download | llvm-44bb442fd5be3860e7819cb216621b5ea59970c3.zip llvm-44bb442fd5be3860e7819cb216621b5ea59970c3.tar.gz llvm-44bb442fd5be3860e7819cb216621b5ea59970c3.tar.bz2 |
[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.
Diffstat (limited to 'lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp')
-rw-r--r-- | lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp | 51 |
1 files changed, 42 insertions, 9 deletions
diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp b/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp index c7f1c79..bd129d2 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp +++ b/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp @@ -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 lldb::ValueObjectSP(); + 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; } |