Index: lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp =================================================================== --- lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp +++ lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp @@ -73,6 +73,15 @@ 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 @@ 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; } Index: lldb/test/API/functionalities/data-formatter/data-formatter-stl/libstdcpp/smart_ptr/TestDataFormatterStdSmartPtr.py =================================================================== --- lldb/test/API/functionalities/data-formatter/data-formatter-stl/libstdcpp/smart_ptr/TestDataFormatterStdSmartPtr.py +++ lldb/test/API/functionalities/data-formatter/data-formatter-stl/libstdcpp/smart_ptr/TestDataFormatterStdSmartPtr.py @@ -33,6 +33,13 @@ self.expect("frame variable iwp", substrs=['iwp = 123']) self.expect("frame variable swp", substrs=['swp = "foobar"']) + self.expect("frame variable *nsp", substrs=['*nsp = ']) + 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']) Index: lldb/test/API/functionalities/data-formatter/data-formatter-stl/libstdcpp/smart_ptr/main.cpp =================================================================== --- lldb/test/API/functionalities/data-formatter/data-formatter-stl/libstdcpp/smart_ptr/main.cpp +++ lldb/test/API/functionalities/data-formatter/data-formatter-stl/libstdcpp/smart_ptr/main.cpp @@ -1,12 +1,17 @@ #include #include +struct Foo { + int mem = 5; +}; + int main() { std::shared_ptr nsp; std::shared_ptr isp(new int{123}); std::shared_ptr ssp = std::make_shared("foobar"); + std::shared_ptr fsp = std::make_shared(); std::weak_ptr nwp; std::weak_ptr iwp = isp; @@ -15,6 +20,7 @@ nsp.reset(); // Set break point at this line. isp.reset(); ssp.reset(); + fsp.reset(); return 0; // Set break point at this line. }