Path: blob/main/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/MsvcStlSmartPointer.cpp
213845 views
//===-- MsvcStlSmartPointer.cpp -------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "Generic.h"9#include "MsvcStl.h"1011#include "lldb/DataFormatters/FormattersHelpers.h"12#include "lldb/DataFormatters/TypeSynthetic.h"1314using namespace lldb;1516bool lldb_private::formatters::IsMsvcStlSmartPointer(ValueObject &valobj) {17if (auto valobj_sp = valobj.GetNonSyntheticValue())18return valobj_sp->GetChildMemberWithName("_Ptr") != nullptr;1920return false;21}2223bool lldb_private::formatters::MsvcStlSmartPointerSummaryProvider(24ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {25ValueObjectSP valobj_sp(valobj.GetNonSyntheticValue());26if (!valobj_sp)27return false;2829ValueObjectSP ptr_sp(valobj_sp->GetChildMemberWithName("_Ptr"));30ValueObjectSP ctrl_sp(valobj_sp->GetChildMemberWithName("_Rep"));31if (!ctrl_sp || !ptr_sp)32return false;3334DumpCxxSmartPtrPointerSummary(stream, *ptr_sp, options);3536bool success;37uint64_t ctrl_addr = ctrl_sp->GetValueAsUnsigned(0, &success);38// Empty control field (expired)39if (!success || ctrl_addr == 0)40return true;4142uint64_t uses = 0;43if (auto uses_sp = ctrl_sp->GetChildMemberWithName("_Uses")) {44bool success;45uses = uses_sp->GetValueAsUnsigned(0, &success);46if (!success)47return false;4849stream.Printf(" strong=%" PRIu64, uses);50}5152// _Weaks is the number of weak references - (_Uses != 0).53if (auto weak_count_sp = ctrl_sp->GetChildMemberWithName("_Weaks")) {54bool success;55uint64_t count = weak_count_sp->GetValueAsUnsigned(0, &success);56if (!success)57return false;5859stream.Printf(" weak=%" PRIu64, count - (uses != 0));60}6162return true;63}6465namespace lldb_private {66namespace formatters {6768class MsvcStlSmartPointerSyntheticFrontEnd : public SyntheticChildrenFrontEnd {69public:70MsvcStlSmartPointerSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);7172llvm::Expected<uint32_t> CalculateNumChildren() override;7374lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override;7576lldb::ChildCacheState Update() override;7778llvm::Expected<size_t> GetIndexOfChildWithName(ConstString name) override;7980~MsvcStlSmartPointerSyntheticFrontEnd() override;8182private:83ValueObject *m_ptr_obj = nullptr;84};8586class MsvcStlUniquePtrSyntheticFrontEnd : public SyntheticChildrenFrontEnd {87public:88MsvcStlUniquePtrSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);8990llvm::Expected<uint32_t> CalculateNumChildren() override;9192lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override;9394lldb::ChildCacheState Update() override;9596llvm::Expected<size_t> GetIndexOfChildWithName(ConstString name) override;9798private:99lldb::ValueObjectSP m_value_ptr_sp;100lldb::ValueObjectSP m_deleter_sp;101};102103} // namespace formatters104} // namespace lldb_private105106lldb_private::formatters::MsvcStlSmartPointerSyntheticFrontEnd::107MsvcStlSmartPointerSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)108: SyntheticChildrenFrontEnd(*valobj_sp) {109if (valobj_sp)110Update();111}112113llvm::Expected<uint32_t> lldb_private::formatters::114MsvcStlSmartPointerSyntheticFrontEnd::CalculateNumChildren() {115return (m_ptr_obj ? 1 : 0);116}117118lldb::ValueObjectSP119lldb_private::formatters::MsvcStlSmartPointerSyntheticFrontEnd::GetChildAtIndex(120uint32_t idx) {121if (!m_ptr_obj)122return lldb::ValueObjectSP();123124ValueObjectSP valobj_sp = m_backend.GetSP();125if (!valobj_sp)126return lldb::ValueObjectSP();127128if (idx == 0)129return m_ptr_obj->GetSP();130131if (idx == 1) {132Status status;133ValueObjectSP value_sp = m_ptr_obj->Dereference(status);134if (status.Success())135return value_sp;136}137138return lldb::ValueObjectSP();139}140141lldb::ChildCacheState142lldb_private::formatters::MsvcStlSmartPointerSyntheticFrontEnd::Update() {143m_ptr_obj = nullptr;144145ValueObjectSP valobj_sp = m_backend.GetSP();146if (!valobj_sp)147return lldb::ChildCacheState::eRefetch;148149auto ptr_obj_sp = valobj_sp->GetChildMemberWithName("_Ptr");150if (!ptr_obj_sp)151return lldb::ChildCacheState::eRefetch;152153auto cast_ptr_sp = GetDesugaredSmartPointerValue(*ptr_obj_sp, *valobj_sp);154if (!cast_ptr_sp)155return lldb::ChildCacheState::eRefetch;156157m_ptr_obj = cast_ptr_sp->Clone(ConstString("pointer")).get();158return lldb::ChildCacheState::eRefetch;159}160161llvm::Expected<size_t>162lldb_private::formatters::MsvcStlSmartPointerSyntheticFrontEnd::163GetIndexOfChildWithName(ConstString name) {164if (name == "pointer")165return 0;166167if (name == "object" || name == "$$dereference$$")168return 1;169170return llvm::createStringError("Type has no child named '%s'",171name.AsCString());172}173174lldb_private::formatters::MsvcStlSmartPointerSyntheticFrontEnd::175~MsvcStlSmartPointerSyntheticFrontEnd() = default;176177lldb_private::SyntheticChildrenFrontEnd *178lldb_private::formatters::MsvcStlSmartPointerSyntheticFrontEndCreator(179lldb::ValueObjectSP valobj_sp) {180return new MsvcStlSmartPointerSyntheticFrontEnd(valobj_sp);181}182183bool lldb_private::formatters::IsMsvcStlUniquePtr(ValueObject &valobj) {184if (auto valobj_sp = valobj.GetNonSyntheticValue())185return valobj_sp->GetChildMemberWithName("_Mypair") != nullptr;186187return false;188}189190bool lldb_private::formatters::MsvcStlUniquePtrSummaryProvider(191ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {192ValueObjectSP valobj_sp(valobj.GetNonSyntheticValue());193if (!valobj_sp)194return false;195196ValueObjectSP ptr_sp(valobj_sp->GetChildAtNamePath({"_Mypair", "_Myval2"}));197if (!ptr_sp)198return false;199200DumpCxxSmartPtrPointerSummary(stream, *ptr_sp, options);201202return true;203}204205lldb_private::formatters::MsvcStlUniquePtrSyntheticFrontEnd::206MsvcStlUniquePtrSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)207: SyntheticChildrenFrontEnd(*valobj_sp) {208if (valobj_sp)209Update();210}211212llvm::Expected<uint32_t> lldb_private::formatters::213MsvcStlUniquePtrSyntheticFrontEnd::CalculateNumChildren() {214if (m_value_ptr_sp)215return m_deleter_sp ? 2 : 1;216return 0;217}218219lldb::ValueObjectSP220lldb_private::formatters::MsvcStlUniquePtrSyntheticFrontEnd::GetChildAtIndex(221uint32_t idx) {222if (!m_value_ptr_sp)223return lldb::ValueObjectSP();224225if (idx == 0)226return m_value_ptr_sp;227228if (idx == 1)229return m_deleter_sp;230231if (idx == 2) {232Status status;233auto value_sp = m_value_ptr_sp->Dereference(status);234if (status.Success()) {235return value_sp;236}237}238239return lldb::ValueObjectSP();240}241242lldb::ChildCacheState243lldb_private::formatters::MsvcStlUniquePtrSyntheticFrontEnd::Update() {244ValueObjectSP valobj_sp = m_backend.GetSP();245if (!valobj_sp)246return lldb::ChildCacheState::eRefetch;247248ValueObjectSP pair_sp = valobj_sp->GetChildMemberWithName("_Mypair");249if (!pair_sp)250return lldb::ChildCacheState::eRefetch;251252if (auto value_ptr_sp = pair_sp->GetChildMemberWithName("_Myval2"))253m_value_ptr_sp = value_ptr_sp->Clone(ConstString("pointer"));254255// Only present if the deleter is non-empty256if (auto deleter_sp = pair_sp->GetChildMemberWithName("_Myval1"))257m_deleter_sp = deleter_sp->Clone(ConstString("deleter"));258259return lldb::ChildCacheState::eRefetch;260}261262llvm::Expected<size_t>263lldb_private::formatters::MsvcStlUniquePtrSyntheticFrontEnd::264GetIndexOfChildWithName(ConstString name) {265if (name == "pointer")266return 0;267if (name == "deleter")268return 1;269if (name == "obj" || name == "object" || name == "$$dereference$$")270return 2;271return llvm::createStringError("Type has no child named '%s'",272name.AsCString());273}274275lldb_private::SyntheticChildrenFrontEnd *276lldb_private::formatters::MsvcStlUniquePtrSyntheticFrontEndCreator(277lldb::ValueObjectSP valobj_sp) {278return new MsvcStlUniquePtrSyntheticFrontEnd(valobj_sp);279}280281282