Index: lldb/trunk/include/lldb/DataFormatters/VectorIterator.h =================================================================== --- lldb/trunk/include/lldb/DataFormatters/VectorIterator.h +++ lldb/trunk/include/lldb/DataFormatters/VectorIterator.h @@ -38,9 +38,7 @@ size_t GetIndexOfChildWithName(const ConstString &name) override; - - ~VectorIteratorSyntheticFrontEnd() override; - + private: ExecutionContextRef m_exe_ctx_ref; ConstString m_item_name; Index: lldb/trunk/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/smart_ptr/Makefile =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/smart_ptr/Makefile +++ lldb/trunk/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/smart_ptr/Makefile @@ -0,0 +1,15 @@ +LEVEL = ../../../../../make + +CXX_SOURCES := main.cpp + +CXXFLAGS := -O0 +USE_LIBSTDCPP := 1 + +# clang-3.5+ outputs FullDebugInfo by default for Darwin/FreeBSD +# targets. Other targets do not, which causes this test to fail. +# This flag enables FullDebugInfo for all targets. +ifneq (,$(findstring clang,$(CC))) + CFLAGS_EXTRAS += -fno-limit-debug-info +endif + +include $(LEVEL)/Makefile.rules Index: lldb/trunk/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/smart_ptr/TestDataFormatterStdSmartPtr.py =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/smart_ptr/TestDataFormatterStdSmartPtr.py +++ lldb/trunk/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/smart_ptr/TestDataFormatterStdSmartPtr.py @@ -0,0 +1,45 @@ +""" +Test lldb data formatter subsystem. +""" + +from __future__ import print_function + +import os, time +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +class StdSmartPtrDataFormatterTestCase(TestBase): + mydir = TestBase.compute_mydir(__file__) + + @skipIfFreeBSD + @skipIfWindows # libstdcpp not ported to Windows + def test_with_run_command(self): + self.build() + self.runCmd("file a.out", CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_source_regexp (self, "Set break point at this line.") + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs = ['stopped', 'stop reason = breakpoint']) + + self.expect("frame variable nsp", substrs = ['nsp = nullptr']) + self.expect("frame variable isp", substrs = ['isp = 123']) + self.expect("frame variable ssp", substrs = ['ssp = "foobar"']) + + self.expect("frame variable nwp", substrs = ['nwp = nullptr']) + self.expect("frame variable iwp", substrs = ['iwp = 123']) + self.expect("frame variable swp", substrs = ['swp = "foobar"']) + + self.runCmd("continue") + + self.expect("frame variable nsp", substrs = ['nsp = nullptr']) + self.expect("frame variable isp", substrs = ['isp = nullptr']) + self.expect("frame variable ssp", substrs = ['ssp = nullptr']) + + self.expect("frame variable nwp", substrs = ['nwp = nullptr']) + self.expect("frame variable iwp", substrs = ['iwp = nullptr']) + self.expect("frame variable swp", substrs = ['swp = nullptr']) Index: lldb/trunk/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/smart_ptr/main.cpp =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/smart_ptr/main.cpp +++ lldb/trunk/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/smart_ptr/main.cpp @@ -0,0 +1,20 @@ +#include +#include + +int +main() +{ + std::shared_ptr nsp; + std::shared_ptr isp(new int{123}); + std::shared_ptr ssp = std::make_shared("foobar"); + + std::weak_ptr nwp; + std::weak_ptr iwp = isp; + std::weak_ptr swp = ssp; + + nsp.reset(); // Set break point at this line. + isp.reset(); + ssp.reset(); + + return 0; // Set break point at this line. +} Index: lldb/trunk/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp =================================================================== --- lldb/trunk/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp +++ lldb/trunk/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp @@ -652,8 +652,22 @@ "size=${svar%#}"))); AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibStdcppVectorIteratorSyntheticFrontEndCreator, "std::vector iterator synthetic children", ConstString("^__gnu_cxx::__normal_iterator<.+>$"), stl_synth_flags, true); - + AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibstdcppMapIteratorSyntheticFrontEndCreator, "std::map iterator synthetic children", ConstString("^std::_Rb_tree_iterator<.+>$"), stl_synth_flags, true); + + AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibStdcppSharedPtrSyntheticFrontEndCreator, + "std::shared_ptr synthetic children", ConstString("^std::shared_ptr<.+>(( )?&)?$"), stl_synth_flags, + true); + AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibStdcppSharedPtrSyntheticFrontEndCreator, + "std::weak_ptr synthetic children", ConstString("^std::weak_ptr<.+>(( )?&)?$"), stl_synth_flags, + true); + + AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibStdcppSmartPointerSummaryProvider, + "libstdc++ std::shared_ptr summary provider", ConstString("^std::shared_ptr<.+>(( )?&)?$"), + stl_summary_flags, true); + AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibStdcppSmartPointerSummaryProvider, + "libstdc++ std::weak_ptr summary provider", ConstString("^std::weak_ptr<.+>(( )?&)?$"), + stl_summary_flags, true); #endif } Index: lldb/trunk/source/Plugins/Language/CPlusPlus/LibStdcpp.h =================================================================== --- lldb/trunk/source/Plugins/Language/CPlusPlus/LibStdcpp.h +++ lldb/trunk/source/Plugins/Language/CPlusPlus/LibStdcpp.h @@ -24,9 +24,14 @@ bool LibStdcppWStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); // libcstdc++ c++11 std::wstring + bool + LibStdcppSmartPointerSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); // libstdc++ std::shared_ptr<> and std::weak_ptr<> + SyntheticChildrenFrontEnd* LibstdcppMapIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP); - + SyntheticChildrenFrontEnd* LibStdcppVectorIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP); + + SyntheticChildrenFrontEnd* LibStdcppSharedPtrSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP); } // namespace formatters } // namespace lldb_private Index: lldb/trunk/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp =================================================================== --- lldb/trunk/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp +++ lldb/trunk/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp @@ -28,12 +28,24 @@ using namespace lldb_private; using namespace lldb_private::formatters; +namespace +{ + class LibstdcppMapIteratorSyntheticFrontEnd : public SyntheticChildrenFrontEnd { -public: - LibstdcppMapIteratorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); + /* + (std::_Rb_tree_iterator, std::allocator > > >) ibeg = { + (_Base_ptr) _M_node = 0x0000000100103910 { + (std::_Rb_tree_color) _M_color = _S_black + (std::_Rb_tree_node_base::_Base_ptr) _M_parent = 0x00000001001038c0 + (std::_Rb_tree_node_base::_Base_ptr) _M_left = 0x0000000000000000 + (std::_Rb_tree_node_base::_Base_ptr) _M_right = 0x0000000000000000 + } + } + */ - ~LibstdcppMapIteratorSyntheticFrontEnd() override = default; +public: + explicit LibstdcppMapIteratorSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp); size_t CalculateNumChildren() override; @@ -57,16 +69,28 @@ lldb::ValueObjectSP m_pair_sp; }; -/* - (std::_Rb_tree_iterator, std::allocator > > >) ibeg = { - (_Base_ptr) _M_node = 0x0000000100103910 { - (std::_Rb_tree_color) _M_color = _S_black - (std::_Rb_tree_node_base::_Base_ptr) _M_parent = 0x00000001001038c0 - (std::_Rb_tree_node_base::_Base_ptr) _M_left = 0x0000000000000000 - (std::_Rb_tree_node_base::_Base_ptr) _M_right = 0x0000000000000000 - } - } - */ +class LibStdcppSharedPtrSyntheticFrontEnd : public SyntheticChildrenFrontEnd +{ +public: + explicit LibStdcppSharedPtrSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp); + + size_t + CalculateNumChildren() override; + + lldb::ValueObjectSP + GetChildAtIndex(size_t idx) override; + + bool + Update() override; + + bool + MightHaveChildren() override; + + size_t + GetIndexOfChildWithName(const ConstString &name) override; +}; + +} // end of anonymous namespace LibstdcppMapIteratorSyntheticFrontEnd::LibstdcppMapIteratorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : SyntheticChildrenFrontEnd(*valobj_sp), @@ -193,7 +217,7 @@ } bool -lldb_private::formatters::VectorIteratorSyntheticFrontEnd::Update() +VectorIteratorSyntheticFrontEnd::Update() { m_item_sp.reset(); @@ -218,13 +242,13 @@ } size_t -lldb_private::formatters::VectorIteratorSyntheticFrontEnd::CalculateNumChildren () +VectorIteratorSyntheticFrontEnd::CalculateNumChildren() { return 1; } lldb::ValueObjectSP -lldb_private::formatters::VectorIteratorSyntheticFrontEnd::GetChildAtIndex (size_t idx) +VectorIteratorSyntheticFrontEnd::GetChildAtIndex(size_t idx) { if (idx == 0) return m_item_sp; @@ -232,21 +256,19 @@ } bool -lldb_private::formatters::VectorIteratorSyntheticFrontEnd::MightHaveChildren () +VectorIteratorSyntheticFrontEnd::MightHaveChildren() { return true; } size_t -lldb_private::formatters::VectorIteratorSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) +VectorIteratorSyntheticFrontEnd::GetIndexOfChildWithName(const ConstString &name) { if (name == ConstString("item")) return 0; return UINT32_MAX; } -lldb_private::formatters::VectorIteratorSyntheticFrontEnd::~VectorIteratorSyntheticFrontEnd() = default; - bool lldb_private::formatters::LibStdcppStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) { @@ -360,3 +382,95 @@ } return false; } + +LibStdcppSharedPtrSyntheticFrontEnd::LibStdcppSharedPtrSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp) + : SyntheticChildrenFrontEnd(*valobj_sp) +{ + if (valobj_sp) + Update(); +} + +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(); +} + +bool +LibStdcppSharedPtrSyntheticFrontEnd::Update() +{ + return false; +} + +bool +LibStdcppSharedPtrSyntheticFrontEnd::MightHaveChildren() +{ + return true; +} + +size_t +LibStdcppSharedPtrSyntheticFrontEnd::GetIndexOfChildWithName(const ConstString &name) +{ + if (name == ConstString("_M_ptr")) + return 0; + return UINT32_MAX; +} + +SyntheticChildrenFrontEnd * +lldb_private::formatters::LibStdcppSharedPtrSyntheticFrontEndCreator(CXXSyntheticChildren *, + lldb::ValueObjectSP valobj_sp) +{ + return (valobj_sp ? new LibStdcppSharedPtrSyntheticFrontEnd(valobj_sp) : nullptr); +} + +bool +lldb_private::formatters::LibStdcppSmartPointerSummaryProvider(ValueObject &valobj, Stream &stream, + const TypeSummaryOptions &options) +{ + ValueObjectSP valobj_sp(valobj.GetNonSyntheticValue()); + if (!valobj_sp) + return false; + + ValueObjectSP ptr_sp(valobj_sp->GetChildMemberWithName(ConstString("_M_ptr"), true)); + if (!ptr_sp) + return false; + + ValueObjectSP usecount_sp( + valobj_sp->GetChildAtNamePath({ConstString("_M_refcount"), ConstString("_M_pi"), ConstString("_M_use_count")})); + if (!usecount_sp) + return false; + + if (ptr_sp->GetValueAsUnsigned(0) == 0 || usecount_sp->GetValueAsUnsigned(0) == 0) + { + stream.Printf("nullptr"); + return true; + } + + Error error; + ValueObjectSP pointee_sp = ptr_sp->Dereference(error); + if (pointee_sp && error.Success()) + { + if (pointee_sp->DumpPrintableRepresentation(stream, ValueObject::eValueObjectRepresentationStyleSummary, + lldb::eFormatInvalid, + ValueObject::ePrintableRepresentationSpecialCasesDisable, false)) + { + return true; + } + } + + stream.Printf("ptr = 0x%" PRIx64, ptr_sp->GetValueAsUnsigned(0)); + return true; +}