Add data formatter for libstdc++ shared_ptr and weak_ptr

Differential revision: http://reviews.llvm.org/D21984

llvm-svn: 274617
diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp b/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp
index b4848b1..6d6f915 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp
+++ b/lldb/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::pair<const int, std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >) 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::pair<const int, std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >) 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;
+}