281 lines · cpp
1//===-- MsvcStlSmartPointer.cpp -------------------------------------------===//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-exception6//7//===----------------------------------------------------------------------===//8 9#include "Generic.h"10#include "MsvcStl.h"11 12#include "lldb/DataFormatters/FormattersHelpers.h"13#include "lldb/DataFormatters/TypeSynthetic.h"14 15using namespace lldb;16 17bool lldb_private::formatters::IsMsvcStlSmartPointer(ValueObject &valobj) {18 if (auto valobj_sp = valobj.GetNonSyntheticValue())19 return valobj_sp->GetChildMemberWithName("_Ptr") != nullptr;20 21 return false;22}23 24bool lldb_private::formatters::MsvcStlSmartPointerSummaryProvider(25 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {26 ValueObjectSP valobj_sp(valobj.GetNonSyntheticValue());27 if (!valobj_sp)28 return false;29 30 ValueObjectSP ptr_sp(valobj_sp->GetChildMemberWithName("_Ptr"));31 ValueObjectSP ctrl_sp(valobj_sp->GetChildMemberWithName("_Rep"));32 if (!ctrl_sp || !ptr_sp)33 return false;34 35 DumpCxxSmartPtrPointerSummary(stream, *ptr_sp, options);36 37 bool success;38 uint64_t ctrl_addr = ctrl_sp->GetValueAsUnsigned(0, &success);39 // Empty control field (expired)40 if (!success || ctrl_addr == 0)41 return true;42 43 uint64_t uses = 0;44 if (auto uses_sp = ctrl_sp->GetChildMemberWithName("_Uses")) {45 bool success;46 uses = uses_sp->GetValueAsUnsigned(0, &success);47 if (!success)48 return false;49 50 stream.Printf(" strong=%" PRIu64, uses);51 }52 53 // _Weaks is the number of weak references - (_Uses != 0).54 if (auto weak_count_sp = ctrl_sp->GetChildMemberWithName("_Weaks")) {55 bool success;56 uint64_t count = weak_count_sp->GetValueAsUnsigned(0, &success);57 if (!success)58 return false;59 60 stream.Printf(" weak=%" PRIu64, count - (uses != 0));61 }62 63 return true;64}65 66namespace lldb_private {67namespace formatters {68 69class MsvcStlSmartPointerSyntheticFrontEnd : public SyntheticChildrenFrontEnd {70public:71 MsvcStlSmartPointerSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);72 73 llvm::Expected<uint32_t> CalculateNumChildren() override;74 75 lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override;76 77 lldb::ChildCacheState Update() override;78 79 llvm::Expected<size_t> GetIndexOfChildWithName(ConstString name) override;80 81 ~MsvcStlSmartPointerSyntheticFrontEnd() override;82 83private:84 ValueObject *m_ptr_obj = nullptr;85};86 87class MsvcStlUniquePtrSyntheticFrontEnd : public SyntheticChildrenFrontEnd {88public:89 MsvcStlUniquePtrSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);90 91 llvm::Expected<uint32_t> CalculateNumChildren() override;92 93 lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override;94 95 lldb::ChildCacheState Update() override;96 97 llvm::Expected<size_t> GetIndexOfChildWithName(ConstString name) override;98 99private:100 lldb::ValueObjectSP m_value_ptr_sp;101 lldb::ValueObjectSP m_deleter_sp;102};103 104} // namespace formatters105} // namespace lldb_private106 107lldb_private::formatters::MsvcStlSmartPointerSyntheticFrontEnd::108 MsvcStlSmartPointerSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)109 : SyntheticChildrenFrontEnd(*valobj_sp) {110 if (valobj_sp)111 Update();112}113 114llvm::Expected<uint32_t> lldb_private::formatters::115 MsvcStlSmartPointerSyntheticFrontEnd::CalculateNumChildren() {116 return (m_ptr_obj ? 1 : 0);117}118 119lldb::ValueObjectSP120lldb_private::formatters::MsvcStlSmartPointerSyntheticFrontEnd::GetChildAtIndex(121 uint32_t idx) {122 if (!m_ptr_obj)123 return lldb::ValueObjectSP();124 125 ValueObjectSP valobj_sp = m_backend.GetSP();126 if (!valobj_sp)127 return lldb::ValueObjectSP();128 129 if (idx == 0)130 return m_ptr_obj->GetSP();131 132 if (idx == 1) {133 Status status;134 ValueObjectSP value_sp = m_ptr_obj->Dereference(status);135 if (status.Success())136 return value_sp;137 }138 139 return lldb::ValueObjectSP();140}141 142lldb::ChildCacheState143lldb_private::formatters::MsvcStlSmartPointerSyntheticFrontEnd::Update() {144 m_ptr_obj = nullptr;145 146 ValueObjectSP valobj_sp = m_backend.GetSP();147 if (!valobj_sp)148 return lldb::ChildCacheState::eRefetch;149 150 auto ptr_obj_sp = valobj_sp->GetChildMemberWithName("_Ptr");151 if (!ptr_obj_sp)152 return lldb::ChildCacheState::eRefetch;153 154 auto cast_ptr_sp = GetDesugaredSmartPointerValue(*ptr_obj_sp, *valobj_sp);155 if (!cast_ptr_sp)156 return lldb::ChildCacheState::eRefetch;157 158 m_ptr_obj = cast_ptr_sp->Clone(ConstString("pointer")).get();159 return lldb::ChildCacheState::eRefetch;160}161 162llvm::Expected<size_t>163lldb_private::formatters::MsvcStlSmartPointerSyntheticFrontEnd::164 GetIndexOfChildWithName(ConstString name) {165 if (name == "pointer")166 return 0;167 168 if (name == "object" || name == "$$dereference$$")169 return 1;170 171 return llvm::createStringError("Type has no child named '%s'",172 name.AsCString());173}174 175lldb_private::formatters::MsvcStlSmartPointerSyntheticFrontEnd::176 ~MsvcStlSmartPointerSyntheticFrontEnd() = default;177 178lldb_private::SyntheticChildrenFrontEnd *179lldb_private::formatters::MsvcStlSmartPointerSyntheticFrontEndCreator(180 lldb::ValueObjectSP valobj_sp) {181 return new MsvcStlSmartPointerSyntheticFrontEnd(valobj_sp);182}183 184bool lldb_private::formatters::IsMsvcStlUniquePtr(ValueObject &valobj) {185 if (auto valobj_sp = valobj.GetNonSyntheticValue())186 return valobj_sp->GetChildMemberWithName("_Mypair") != nullptr;187 188 return false;189}190 191bool lldb_private::formatters::MsvcStlUniquePtrSummaryProvider(192 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {193 ValueObjectSP valobj_sp(valobj.GetNonSyntheticValue());194 if (!valobj_sp)195 return false;196 197 ValueObjectSP ptr_sp(valobj_sp->GetChildAtNamePath({"_Mypair", "_Myval2"}));198 if (!ptr_sp)199 return false;200 201 DumpCxxSmartPtrPointerSummary(stream, *ptr_sp, options);202 203 return true;204}205 206lldb_private::formatters::MsvcStlUniquePtrSyntheticFrontEnd::207 MsvcStlUniquePtrSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)208 : SyntheticChildrenFrontEnd(*valobj_sp) {209 if (valobj_sp)210 Update();211}212 213llvm::Expected<uint32_t> lldb_private::formatters::214 MsvcStlUniquePtrSyntheticFrontEnd::CalculateNumChildren() {215 if (m_value_ptr_sp)216 return m_deleter_sp ? 2 : 1;217 return 0;218}219 220lldb::ValueObjectSP221lldb_private::formatters::MsvcStlUniquePtrSyntheticFrontEnd::GetChildAtIndex(222 uint32_t idx) {223 if (!m_value_ptr_sp)224 return lldb::ValueObjectSP();225 226 if (idx == 0)227 return m_value_ptr_sp;228 229 if (idx == 1)230 return m_deleter_sp;231 232 if (idx == 2) {233 Status status;234 auto value_sp = m_value_ptr_sp->Dereference(status);235 if (status.Success()) {236 return value_sp;237 }238 }239 240 return lldb::ValueObjectSP();241}242 243lldb::ChildCacheState244lldb_private::formatters::MsvcStlUniquePtrSyntheticFrontEnd::Update() {245 ValueObjectSP valobj_sp = m_backend.GetSP();246 if (!valobj_sp)247 return lldb::ChildCacheState::eRefetch;248 249 ValueObjectSP pair_sp = valobj_sp->GetChildMemberWithName("_Mypair");250 if (!pair_sp)251 return lldb::ChildCacheState::eRefetch;252 253 if (auto value_ptr_sp = pair_sp->GetChildMemberWithName("_Myval2"))254 m_value_ptr_sp = value_ptr_sp->Clone(ConstString("pointer"));255 256 // Only present if the deleter is non-empty257 if (auto deleter_sp = pair_sp->GetChildMemberWithName("_Myval1"))258 m_deleter_sp = deleter_sp->Clone(ConstString("deleter"));259 260 return lldb::ChildCacheState::eRefetch;261}262 263llvm::Expected<size_t>264lldb_private::formatters::MsvcStlUniquePtrSyntheticFrontEnd::265 GetIndexOfChildWithName(ConstString name) {266 if (name == "pointer")267 return 0;268 if (name == "deleter")269 return 1;270 if (name == "obj" || name == "object" || name == "$$dereference$$")271 return 2;272 return llvm::createStringError("Type has no child named '%s'",273 name.AsCString());274}275 276lldb_private::SyntheticChildrenFrontEnd *277lldb_private::formatters::MsvcStlUniquePtrSyntheticFrontEndCreator(278 lldb::ValueObjectSP valobj_sp) {279 return new MsvcStlUniquePtrSyntheticFrontEnd(valobj_sp);280}281