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 if (!obj_child_sp) 71 return nullptr; 72 73 ValueObjectSP obj_subchild_sp = 74 obj_child_sp->GetChildMemberWithName(ConstString("_M_t"), true); 75 76 // if there is a _M_t subchild, the tuple is found in the obj_subchild_sp 77 // (for libstdc++ 6.0.23). 78 if (obj_subchild_sp) { 79 return obj_subchild_sp; 80 } 81 82 return obj_child_sp; 83 } 84 85 bool LibStdcppUniquePtrSyntheticFrontEnd::Update() { 86 ValueObjectSP tuple_sp = GetTuple(); 87 88 if (!tuple_sp) 89 return false; 90 91 std::unique_ptr<SyntheticChildrenFrontEnd> tuple_frontend( 92 LibStdcppTupleSyntheticFrontEndCreator(nullptr, tuple_sp)); 93 94 ValueObjectSP ptr_obj = tuple_frontend->GetChildAtIndex(0); 95 if (ptr_obj) 96 m_ptr_obj = ptr_obj->Clone(ConstString("pointer")); 97 98 ValueObjectSP del_obj = tuple_frontend->GetChildAtIndex(1); 99 if (del_obj) 100 m_del_obj = del_obj->Clone(ConstString("deleter")); 101 102 if (m_ptr_obj) { 103 Status error; 104 ValueObjectSP obj_obj = m_ptr_obj->Dereference(error); 105 if (error.Success()) { 106 m_obj_obj = obj_obj->Clone(ConstString("object")); 107 } 108 } 109 110 return false; 111 } 112 113 bool LibStdcppUniquePtrSyntheticFrontEnd::MightHaveChildren() { return true; } 114 115 lldb::ValueObjectSP 116 LibStdcppUniquePtrSyntheticFrontEnd::GetChildAtIndex(size_t idx) { 117 if (idx == 0) 118 return m_ptr_obj; 119 if (idx == 1) 120 return m_del_obj; 121 if (idx == 2) 122 return m_obj_obj; 123 return lldb::ValueObjectSP(); 124 } 125 126 size_t LibStdcppUniquePtrSyntheticFrontEnd::CalculateNumChildren() { 127 if (m_del_obj) 128 return 2; 129 return 1; 130 } 131 132 size_t LibStdcppUniquePtrSyntheticFrontEnd::GetIndexOfChildWithName( 133 const ConstString &name) { 134 if (name == ConstString("ptr") || name == ConstString("pointer")) 135 return 0; 136 if (name == ConstString("del") || name == ConstString("deleter")) 137 return 1; 138 if (name == ConstString("obj") || name == ConstString("object") || 139 name == ConstString("$$dereference$$")) 140 return 2; 141 return UINT32_MAX; 142 } 143 144 bool LibStdcppUniquePtrSyntheticFrontEnd::GetSummary( 145 Stream &stream, const TypeSummaryOptions &options) { 146 if (!m_ptr_obj) 147 return false; 148 149 bool success; 150 uint64_t ptr_value = m_ptr_obj->GetValueAsUnsigned(0, &success); 151 if (!success) 152 return false; 153 if (ptr_value == 0) 154 stream.Printf("nullptr"); 155 else 156 stream.Printf("0x%" PRIx64, ptr_value); 157 return true; 158 } 159 160 SyntheticChildrenFrontEnd * 161 lldb_private::formatters::LibStdcppUniquePtrSyntheticFrontEndCreator( 162 CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) { 163 return (valobj_sp ? new LibStdcppUniquePtrSyntheticFrontEnd(valobj_sp) 164 : nullptr); 165 } 166 167 bool lldb_private::formatters::LibStdcppUniquePointerSummaryProvider( 168 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) { 169 LibStdcppUniquePtrSyntheticFrontEnd formatter(valobj.GetSP()); 170 return formatter.GetSummary(stream, options); 171 } 172