1 //===-- LibStdcppUniquePointer.cpp ------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "LibStdcpp.h" 11 12 #include "lldb/Core/ValueObject.h" 13 #include "lldb/DataFormatters/FormattersHelpers.h" 14 #include "lldb/DataFormatters/TypeSynthetic.h" 15 #include "lldb/Utility/ConstString.h" 16 17 #include <memory> 18 #include <vector> 19 20 using namespace lldb; 21 using namespace lldb_private; 22 using namespace lldb_private::formatters; 23 24 namespace { 25 26 class LibStdcppUniquePtrSyntheticFrontEnd : public SyntheticChildrenFrontEnd { 27 public: 28 explicit LibStdcppUniquePtrSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp); 29 30 size_t CalculateNumChildren() override; 31 32 lldb::ValueObjectSP GetChildAtIndex(size_t idx) override; 33 34 bool Update() override; 35 36 bool MightHaveChildren() override; 37 38 size_t GetIndexOfChildWithName(const ConstString &name) override; 39 40 bool GetSummary(Stream &stream, const TypeSummaryOptions &options); 41 42 private: 43 ValueObjectSP m_ptr_obj; 44 ValueObjectSP m_obj_obj; 45 ValueObjectSP m_del_obj; 46 47 ValueObjectSP GetTuple(); 48 }; 49 50 } // end of anonymous namespace 51 52 LibStdcppUniquePtrSyntheticFrontEnd::LibStdcppUniquePtrSyntheticFrontEnd( 53 lldb::ValueObjectSP valobj_sp) 54 : SyntheticChildrenFrontEnd(*valobj_sp) { 55 Update(); 56 } 57 58 ValueObjectSP LibStdcppUniquePtrSyntheticFrontEnd::GetTuple() { 59 ValueObjectSP valobj_backend_sp = m_backend.GetSP(); 60 61 if (!valobj_backend_sp) 62 return nullptr; 63 64 ValueObjectSP valobj_sp = valobj_backend_sp->GetNonSyntheticValue(); 65 if (!valobj_sp) 66 return nullptr; 67 68 ValueObjectSP obj_child_sp = 69 valobj_sp->GetChildMemberWithName(ConstString("_M_t"), true); 70 71 ValueObjectSP obj_subchild_sp = 72 obj_child_sp->GetChildMemberWithName(ConstString("_M_t"), true); 73 74 // if there is a _M_t subchild, the tuple is found in 75 // the obj_subchild_sp (for libstdc++ 6.0.23). 76 if (obj_subchild_sp) { 77 return obj_subchild_sp; 78 } 79 80 return obj_child_sp; 81 } 82 83 bool LibStdcppUniquePtrSyntheticFrontEnd::Update() { 84 ValueObjectSP tuple_sp = GetTuple(); 85 86 if (!tuple_sp) 87 return false; 88 89 std::unique_ptr<SyntheticChildrenFrontEnd> tuple_frontend( 90 LibStdcppTupleSyntheticFrontEndCreator(nullptr, tuple_sp)); 91 92 ValueObjectSP ptr_obj = tuple_frontend->GetChildAtIndex(0); 93 if (ptr_obj) 94 m_ptr_obj = ptr_obj->Clone(ConstString("pointer")); 95 96 ValueObjectSP del_obj = tuple_frontend->GetChildAtIndex(1); 97 if (del_obj) 98 m_del_obj = del_obj->Clone(ConstString("deleter")); 99 100 if (m_ptr_obj) { 101 Status error; 102 ValueObjectSP obj_obj = m_ptr_obj->Dereference(error); 103 if (error.Success()) { 104 m_obj_obj = obj_obj->Clone(ConstString("object")); 105 } 106 } 107 108 return false; 109 } 110 111 bool LibStdcppUniquePtrSyntheticFrontEnd::MightHaveChildren() { return true; } 112 113 lldb::ValueObjectSP 114 LibStdcppUniquePtrSyntheticFrontEnd::GetChildAtIndex(size_t idx) { 115 if (idx == 0) 116 return m_ptr_obj; 117 if (idx == 1) 118 return m_del_obj; 119 if (idx == 2) 120 return m_obj_obj; 121 return lldb::ValueObjectSP(); 122 } 123 124 size_t LibStdcppUniquePtrSyntheticFrontEnd::CalculateNumChildren() { 125 if (m_del_obj) 126 return 2; 127 return 1; 128 } 129 130 size_t LibStdcppUniquePtrSyntheticFrontEnd::GetIndexOfChildWithName( 131 const ConstString &name) { 132 if (name == ConstString("ptr") || name == ConstString("pointer")) 133 return 0; 134 if (name == ConstString("del") || name == ConstString("deleter")) 135 return 1; 136 if (name == ConstString("obj") || name == ConstString("object") || 137 name == ConstString("$$dereference$$")) 138 return 2; 139 return UINT32_MAX; 140 } 141 142 bool LibStdcppUniquePtrSyntheticFrontEnd::GetSummary( 143 Stream &stream, const TypeSummaryOptions &options) { 144 if (!m_ptr_obj) 145 return false; 146 147 bool success; 148 uint64_t ptr_value = m_ptr_obj->GetValueAsUnsigned(0, &success); 149 if (!success) 150 return false; 151 if (ptr_value == 0) 152 stream.Printf("nullptr"); 153 else 154 stream.Printf("0x%" PRIx64, ptr_value); 155 return true; 156 } 157 158 SyntheticChildrenFrontEnd * 159 lldb_private::formatters::LibStdcppUniquePtrSyntheticFrontEndCreator( 160 CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) { 161 return (valobj_sp ? new LibStdcppUniquePtrSyntheticFrontEnd(valobj_sp) 162 : nullptr); 163 } 164 165 bool lldb_private::formatters::LibStdcppUniquePointerSummaryProvider( 166 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) { 167 LibStdcppUniquePtrSyntheticFrontEnd formatter(valobj.GetSP()); 168 return formatter.GetSummary(stream, options); 169 } 170