114 lines · cpp
1//===-- LibStdcppTuple.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 LibStdcppTupleSyntheticFrontEnd : public SyntheticChildrenFrontEnd {26public:27 explicit LibStdcppTupleSyntheticFrontEnd(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 37private:38 // The lifetime of a ValueObject and all its derivative ValueObjects39 // (children, clones, etc.) is managed by a ClusterManager. These40 // objects are only destroyed when every shared pointer to any of them41 // is destroyed, so we must not store a shared pointer to any ValueObject42 // derived from our backend ValueObject (since we're in the same cluster).43 std::vector<ValueObject*> m_members;44};45 46} // end of anonymous namespace47 48LibStdcppTupleSyntheticFrontEnd::LibStdcppTupleSyntheticFrontEnd(49 lldb::ValueObjectSP valobj_sp)50 : SyntheticChildrenFrontEnd(*valobj_sp) {51 Update();52}53 54lldb::ChildCacheState LibStdcppTupleSyntheticFrontEnd::Update() {55 m_members.clear();56 57 ValueObjectSP valobj_backend_sp = m_backend.GetSP();58 if (!valobj_backend_sp)59 return lldb::ChildCacheState::eRefetch;60 61 ValueObjectSP next_child_sp = valobj_backend_sp->GetNonSyntheticValue();62 while (next_child_sp != nullptr) {63 ValueObjectSP current_child = next_child_sp;64 next_child_sp = nullptr;65 66 size_t child_count = current_child->GetNumChildrenIgnoringErrors();67 for (size_t i = 0; i < child_count; ++i) {68 ValueObjectSP child_sp = current_child->GetChildAtIndex(i);69 llvm::StringRef name_str = child_sp->GetName().GetStringRef();70 if (name_str.starts_with("std::_Tuple_impl<")) {71 next_child_sp = child_sp;72 } else if (name_str.starts_with("std::_Head_base<")) {73 ValueObjectSP value_sp =74 child_sp->GetChildMemberWithName("_M_head_impl");75 if (value_sp) {76 StreamString name;77 name.Printf("[%zd]", m_members.size());78 m_members.push_back(value_sp->Clone(ConstString(name.GetString())).get());79 }80 }81 }82 }83 84 return lldb::ChildCacheState::eRefetch;85}86 87lldb::ValueObjectSP88LibStdcppTupleSyntheticFrontEnd::GetChildAtIndex(uint32_t idx) {89 if (idx < m_members.size() && m_members[idx])90 return m_members[idx]->GetSP();91 return lldb::ValueObjectSP();92}93 94llvm::Expected<uint32_t>95LibStdcppTupleSyntheticFrontEnd::CalculateNumChildren() {96 return m_members.size();97}98 99llvm::Expected<size_t>100LibStdcppTupleSyntheticFrontEnd::GetIndexOfChildWithName(ConstString name) {101 auto optional_idx = formatters::ExtractIndexFromString(name.GetCString());102 if (!optional_idx) {103 return llvm::createStringError("Type has no child named '%s'",104 name.AsCString());105 }106 return *optional_idx;107}108 109SyntheticChildrenFrontEnd *110lldb_private::formatters::LibStdcppTupleSyntheticFrontEndCreator(111 CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {112 return (valobj_sp ? new LibStdcppTupleSyntheticFrontEnd(valobj_sp) : nullptr);113}114