brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.3 KiB · 4daba2e Raw
172 lines · cpp
1//===-- LibStdcppUniquePointer.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 "LibStdcpp.h"10 11#include "lldb/DataFormatters/FormattersHelpers.h"12#include "lldb/DataFormatters/TypeSynthetic.h"13#include "lldb/Utility/ConstString.h"14#include "lldb/ValueObject/ValueObject.h"15 16#include <memory>17#include <vector>18 19using namespace lldb;20using namespace lldb_private;21using namespace lldb_private::formatters;22 23namespace {24 25class LibStdcppUniquePtrSyntheticFrontEnd : public SyntheticChildrenFrontEnd {26public:27  explicit LibStdcppUniquePtrSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);28 29  llvm::Expected<uint32_t> CalculateNumChildren() override;30 31  lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override;32 33  lldb::ChildCacheState Update() override;34 35  llvm::Expected<size_t> GetIndexOfChildWithName(ConstString name) override;36 37  bool GetSummary(Stream &stream, const TypeSummaryOptions &options);38 39private:40  // The lifetime of a ValueObject and all its derivative ValueObjects41  // (children, clones, etc.) is managed by a ClusterManager. These42  // objects are only destroyed when every shared pointer to any of them43  // is destroyed, so we must not store a shared pointer to any ValueObject44  // derived from our backend ValueObject (since we're in the same cluster).45  ValueObject *m_ptr_obj = nullptr;46  ValueObject* m_del_obj = nullptr;47 48  ValueObjectSP GetTuple();49};50 51} // end of anonymous namespace52 53LibStdcppUniquePtrSyntheticFrontEnd::LibStdcppUniquePtrSyntheticFrontEnd(54    lldb::ValueObjectSP valobj_sp)55    : SyntheticChildrenFrontEnd(*valobj_sp) {56  Update();57}58 59ValueObjectSP LibStdcppUniquePtrSyntheticFrontEnd::GetTuple() {60  ValueObjectSP valobj_backend_sp = m_backend.GetSP();61 62  if (!valobj_backend_sp)63    return nullptr;64 65  ValueObjectSP valobj_sp = valobj_backend_sp->GetNonSyntheticValue();66  if (!valobj_sp)67    return nullptr;68 69  ValueObjectSP obj_child_sp = valobj_sp->GetChildMemberWithName("_M_t");70  if (!obj_child_sp)71      return nullptr;72 73  ValueObjectSP obj_subchild_sp = obj_child_sp->GetChildMemberWithName("_M_t");74 75  // if there is a _M_t subchild, the tuple is found in the obj_subchild_sp76  // (for libstdc++ 6.0.23).77  if (obj_subchild_sp) {78    return obj_subchild_sp;79  }80 81  return obj_child_sp;82}83 84lldb::ChildCacheState LibStdcppUniquePtrSyntheticFrontEnd::Update() {85  ValueObjectSP tuple_sp = GetTuple();86 87  if (!tuple_sp)88    return lldb::ChildCacheState::eRefetch;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")).get();96 97  // Add a 'deleter' child if there was a non-empty deleter type specified.98  //99  // The object might have size=1 in the TypeSystem but occupies no dedicated100  // storage due to no_unique_address, so infer the actual size from the total101  // size of the unique_ptr class. If sizeof(unique_ptr) == sizeof(void*) then102  // the deleter is empty and should be hidden.103  if (llvm::expectedToOptional(tuple_sp->GetByteSize()).value_or(0) >104      llvm::expectedToOptional(ptr_obj->GetByteSize()).value_or(0)) {105    ValueObjectSP del_obj = tuple_frontend->GetChildAtIndex(1);106    if (del_obj)107      m_del_obj = del_obj->Clone(ConstString("deleter")).get();108  }109 110  return lldb::ChildCacheState::eRefetch;111}112 113lldb::ValueObjectSP114LibStdcppUniquePtrSyntheticFrontEnd::GetChildAtIndex(uint32_t idx) {115  if (idx == 0 && m_ptr_obj)116    return m_ptr_obj->GetSP();117  if (idx == 1 && m_del_obj)118    return m_del_obj->GetSP();119  if (idx == 2) {120    if (m_ptr_obj) {121      Status status;122      auto value_sp = m_ptr_obj->Dereference(status);123      if (status.Success()) {124        return value_sp;125      }126    }127  }128  return lldb::ValueObjectSP();129}130 131llvm::Expected<uint32_t>132LibStdcppUniquePtrSyntheticFrontEnd::CalculateNumChildren() {133  if (m_del_obj)134    return 2;135  return 1;136}137 138llvm::Expected<size_t>139LibStdcppUniquePtrSyntheticFrontEnd::GetIndexOfChildWithName(ConstString name) {140  if (name == "ptr" || name == "pointer")141    return 0;142  if (name == "del" || name == "deleter")143    return 1;144  if (name == "obj" || name == "object" || name == "$$dereference$$")145    return 2;146  return llvm::createStringError("Type has no child named '%s'",147                                 name.AsCString());148}149 150bool LibStdcppUniquePtrSyntheticFrontEnd::GetSummary(151    Stream &stream, const TypeSummaryOptions &options) {152  if (!m_ptr_obj)153    return false;154 155  DumpCxxSmartPtrPointerSummary(stream, *m_ptr_obj, options);156 157  return true;158}159 160SyntheticChildrenFrontEnd *161lldb_private::formatters::LibStdcppUniquePtrSyntheticFrontEndCreator(162    CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {163  return (valobj_sp ? new LibStdcppUniquePtrSyntheticFrontEnd(valobj_sp)164                    : nullptr);165}166 167bool 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