Path: blob/main/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibStdcppUniquePointer.cpp
39642 views
//===-- LibStdcppUniquePointer.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 "LibStdcpp.h"910#include "lldb/Core/ValueObject.h"11#include "lldb/DataFormatters/FormattersHelpers.h"12#include "lldb/DataFormatters/TypeSynthetic.h"13#include "lldb/Utility/ConstString.h"1415#include <memory>16#include <vector>1718using namespace lldb;19using namespace lldb_private;20using namespace lldb_private::formatters;2122namespace {2324class LibStdcppUniquePtrSyntheticFrontEnd : public SyntheticChildrenFrontEnd {25public:26explicit LibStdcppUniquePtrSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);2728llvm::Expected<uint32_t> CalculateNumChildren() override;2930lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override;3132lldb::ChildCacheState Update() override;3334bool MightHaveChildren() override;3536size_t GetIndexOfChildWithName(ConstString name) override;3738bool GetSummary(Stream &stream, const TypeSummaryOptions &options);3940private:41// The lifetime of a ValueObject and all its derivative ValueObjects42// (children, clones, etc.) is managed by a ClusterManager. These43// objects are only destroyed when every shared pointer to any of them44// is destroyed, so we must not store a shared pointer to any ValueObject45// derived from our backend ValueObject (since we're in the same cluster).46ValueObject* m_ptr_obj = nullptr;47ValueObject* m_obj_obj = nullptr;48ValueObject* m_del_obj = nullptr;4950ValueObjectSP GetTuple();51};5253} // end of anonymous namespace5455LibStdcppUniquePtrSyntheticFrontEnd::LibStdcppUniquePtrSyntheticFrontEnd(56lldb::ValueObjectSP valobj_sp)57: SyntheticChildrenFrontEnd(*valobj_sp) {58Update();59}6061ValueObjectSP LibStdcppUniquePtrSyntheticFrontEnd::GetTuple() {62ValueObjectSP valobj_backend_sp = m_backend.GetSP();6364if (!valobj_backend_sp)65return nullptr;6667ValueObjectSP valobj_sp = valobj_backend_sp->GetNonSyntheticValue();68if (!valobj_sp)69return nullptr;7071ValueObjectSP obj_child_sp = valobj_sp->GetChildMemberWithName("_M_t");72if (!obj_child_sp)73return nullptr;7475ValueObjectSP obj_subchild_sp = obj_child_sp->GetChildMemberWithName("_M_t");7677// if there is a _M_t subchild, the tuple is found in the obj_subchild_sp78// (for libstdc++ 6.0.23).79if (obj_subchild_sp) {80return obj_subchild_sp;81}8283return obj_child_sp;84}8586lldb::ChildCacheState LibStdcppUniquePtrSyntheticFrontEnd::Update() {87ValueObjectSP tuple_sp = GetTuple();8889if (!tuple_sp)90return lldb::ChildCacheState::eRefetch;9192std::unique_ptr<SyntheticChildrenFrontEnd> tuple_frontend(93LibStdcppTupleSyntheticFrontEndCreator(nullptr, tuple_sp));9495ValueObjectSP ptr_obj = tuple_frontend->GetChildAtIndex(0);96if (ptr_obj)97m_ptr_obj = ptr_obj->Clone(ConstString("pointer")).get();9899// Add a 'deleter' child if there was a non-empty deleter type specified.100//101// The object might have size=1 in the TypeSystem but occupies no dedicated102// storage due to no_unique_address, so infer the actual size from the total103// size of the unique_ptr class. If sizeof(unique_ptr) == sizeof(void*) then104// the deleter is empty and should be hidden.105if (tuple_sp->GetByteSize() > ptr_obj->GetByteSize()) {106ValueObjectSP del_obj = tuple_frontend->GetChildAtIndex(1);107if (del_obj)108m_del_obj = del_obj->Clone(ConstString("deleter")).get();109}110m_obj_obj = nullptr;111112return lldb::ChildCacheState::eRefetch;113}114115bool LibStdcppUniquePtrSyntheticFrontEnd::MightHaveChildren() { return true; }116117lldb::ValueObjectSP118LibStdcppUniquePtrSyntheticFrontEnd::GetChildAtIndex(uint32_t idx) {119if (idx == 0 && m_ptr_obj)120return m_ptr_obj->GetSP();121if (idx == 1 && m_del_obj)122return m_del_obj->GetSP();123if (idx == 2) {124if (m_ptr_obj && !m_obj_obj) {125Status error;126ValueObjectSP obj_obj = m_ptr_obj->Dereference(error);127if (error.Success()) {128m_obj_obj = obj_obj->Clone(ConstString("object")).get();129}130}131if (m_obj_obj)132return m_obj_obj->GetSP();133}134return lldb::ValueObjectSP();135}136137llvm::Expected<uint32_t>138LibStdcppUniquePtrSyntheticFrontEnd::CalculateNumChildren() {139if (m_del_obj)140return 2;141return 1;142}143144size_t LibStdcppUniquePtrSyntheticFrontEnd::GetIndexOfChildWithName(145ConstString name) {146if (name == "ptr" || name == "pointer")147return 0;148if (name == "del" || name == "deleter")149return 1;150if (name == "obj" || name == "object" || name == "$$dereference$$")151return 2;152return UINT32_MAX;153}154155bool LibStdcppUniquePtrSyntheticFrontEnd::GetSummary(156Stream &stream, const TypeSummaryOptions &options) {157if (!m_ptr_obj)158return false;159160bool success;161uint64_t ptr_value = m_ptr_obj->GetValueAsUnsigned(0, &success);162if (!success)163return false;164if (ptr_value == 0)165stream.Printf("nullptr");166else167stream.Printf("0x%" PRIx64, ptr_value);168return true;169}170171SyntheticChildrenFrontEnd *172lldb_private::formatters::LibStdcppUniquePtrSyntheticFrontEndCreator(173CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {174return (valobj_sp ? new LibStdcppUniquePtrSyntheticFrontEnd(valobj_sp)175: nullptr);176}177178bool lldb_private::formatters::LibStdcppUniquePointerSummaryProvider(179ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {180LibStdcppUniquePtrSyntheticFrontEnd formatter(valobj.GetSP());181return formatter.GetSummary(stream, options);182}183184185