1 //===-- LibStdcppUniquePointer.cpp ------------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "LibStdcpp.h" 10 11 #include "lldb/Core/ValueObject.h" 12 #include "lldb/DataFormatters/FormattersHelpers.h" 13 #include "lldb/DataFormatters/TypeSynthetic.h" 14 #include "lldb/Utility/ConstString.h" 15 16 #include <memory> 17 #include <vector> 18 19 using namespace lldb; 20 using namespace lldb_private; 21 using namespace lldb_private::formatters; 22 23 namespace { 24 25 class LibStdcppUniquePtrSyntheticFrontEnd : public SyntheticChildrenFrontEnd { 26 public: 27 explicit LibStdcppUniquePtrSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp); 28 29 size_t CalculateNumChildren() override; 30 31 lldb::ValueObjectSP GetChildAtIndex(size_t idx) override; 32 33 bool Update() override; 34 35 bool MightHaveChildren() override; 36 37 size_t GetIndexOfChildWithName(ConstString name) override; 38 39 bool GetSummary(Stream &stream, const TypeSummaryOptions &options); 40 41 private: 42 ValueObjectSP m_ptr_obj; 43 ValueObjectSP m_obj_obj; 44 ValueObjectSP m_del_obj; 45 46 ValueObjectSP GetTuple(); 47 }; 48 49 } // end of anonymous namespace 50 51 LibStdcppUniquePtrSyntheticFrontEnd::LibStdcppUniquePtrSyntheticFrontEnd( 52 lldb::ValueObjectSP valobj_sp) 53 : SyntheticChildrenFrontEnd(*valobj_sp) { 54 Update(); 55 } 56 57 ValueObjectSP LibStdcppUniquePtrSyntheticFrontEnd::GetTuple() { 58 ValueObjectSP valobj_backend_sp = m_backend.GetSP(); 59 60 if (!valobj_backend_sp) 61 return nullptr; 62 63 ValueObjectSP valobj_sp = valobj_backend_sp->GetNonSyntheticValue(); 64 if (!valobj_sp) 65 return nullptr; 66 67 ValueObjectSP obj_child_sp = 68 valobj_sp->GetChildMemberWithName(ConstString("_M_t"), true); 69 if (!obj_child_sp) 70 return nullptr; 71 72 ValueObjectSP obj_subchild_sp = 73 obj_child_sp->GetChildMemberWithName(ConstString("_M_t"), true); 74 75 // if there is a _M_t subchild, the tuple is found in the obj_subchild_sp 76 // (for libstdc++ 6.0.23). 77 if (obj_subchild_sp) { 78 return obj_subchild_sp; 79 } 80 81 return obj_child_sp; 82 } 83 84 bool LibStdcppUniquePtrSyntheticFrontEnd::Update() { 85 ValueObjectSP tuple_sp = GetTuple(); 86 87 if (!tuple_sp) 88 return false; 89 90 std::unique_ptr<SyntheticChildrenFrontEnd> tuple_frontend( 91 LibStdcppTupleSyntheticFrontEndCreator(nullptr, tuple_sp)); 92 93 ValueObjectSP ptr_obj = tuple_frontend->GetChildAtIndex(0); 94 if (ptr_obj) 95 m_ptr_obj = ptr_obj->Clone(ConstString("pointer")); 96 97 ValueObjectSP del_obj = tuple_frontend->GetChildAtIndex(1); 98 if (del_obj) 99 m_del_obj = del_obj->Clone(ConstString("deleter")); 100 101 if (m_ptr_obj) { 102 Status error; 103 ValueObjectSP obj_obj = m_ptr_obj->Dereference(error); 104 if (error.Success()) { 105 m_obj_obj = obj_obj->Clone(ConstString("object")); 106 } 107 } 108 109 return false; 110 } 111 112 bool LibStdcppUniquePtrSyntheticFrontEnd::MightHaveChildren() { return true; } 113 114 lldb::ValueObjectSP 115 LibStdcppUniquePtrSyntheticFrontEnd::GetChildAtIndex(size_t idx) { 116 if (idx == 0) 117 return m_ptr_obj; 118 if (idx == 1) 119 return m_del_obj; 120 if (idx == 2) 121 return m_obj_obj; 122 return lldb::ValueObjectSP(); 123 } 124 125 size_t LibStdcppUniquePtrSyntheticFrontEnd::CalculateNumChildren() { 126 if (m_del_obj) 127 return 2; 128 return 1; 129 } 130 131 size_t LibStdcppUniquePtrSyntheticFrontEnd::GetIndexOfChildWithName( 132 ConstString name) { 133 if (name == "ptr" || name == "pointer") 134 return 0; 135 if (name == "del" || name == "deleter") 136 return 1; 137 if (name == "obj" || name == "object" || name == "$$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