1*dda28197Spatrick //===-- LibStdcppTuple.cpp ------------------------------------------------===// 2061da546Spatrick // 3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information. 5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6061da546Spatrick // 7061da546Spatrick //===----------------------------------------------------------------------===// 8061da546Spatrick 9061da546Spatrick #include "LibStdcpp.h" 10061da546Spatrick 11061da546Spatrick #include "lldb/Core/ValueObject.h" 12061da546Spatrick #include "lldb/DataFormatters/FormattersHelpers.h" 13061da546Spatrick #include "lldb/DataFormatters/TypeSynthetic.h" 14061da546Spatrick #include "lldb/Utility/ConstString.h" 15061da546Spatrick 16061da546Spatrick #include <memory> 17061da546Spatrick #include <vector> 18061da546Spatrick 19061da546Spatrick using namespace lldb; 20061da546Spatrick using namespace lldb_private; 21061da546Spatrick using namespace lldb_private::formatters; 22061da546Spatrick 23061da546Spatrick namespace { 24061da546Spatrick 25061da546Spatrick class LibStdcppTupleSyntheticFrontEnd : public SyntheticChildrenFrontEnd { 26061da546Spatrick public: 27061da546Spatrick explicit LibStdcppTupleSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp); 28061da546Spatrick 29061da546Spatrick size_t CalculateNumChildren() override; 30061da546Spatrick 31061da546Spatrick lldb::ValueObjectSP GetChildAtIndex(size_t idx) override; 32061da546Spatrick 33061da546Spatrick bool Update() override; 34061da546Spatrick 35061da546Spatrick bool MightHaveChildren() override; 36061da546Spatrick 37061da546Spatrick size_t GetIndexOfChildWithName(ConstString name) override; 38061da546Spatrick 39061da546Spatrick private: 40061da546Spatrick // The lifetime of a ValueObject and all its derivative ValueObjects 41061da546Spatrick // (children, clones, etc.) is managed by a ClusterManager. These 42061da546Spatrick // objects are only destroyed when every shared pointer to any of them 43061da546Spatrick // is destroyed, so we must not store a shared pointer to any ValueObject 44061da546Spatrick // derived from our backend ValueObject (since we're in the same cluster). 45061da546Spatrick std::vector<ValueObject*> m_members; 46061da546Spatrick }; 47061da546Spatrick 48061da546Spatrick } // end of anonymous namespace 49061da546Spatrick LibStdcppTupleSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)50061da546SpatrickLibStdcppTupleSyntheticFrontEnd::LibStdcppTupleSyntheticFrontEnd( 51061da546Spatrick lldb::ValueObjectSP valobj_sp) 52061da546Spatrick : SyntheticChildrenFrontEnd(*valobj_sp) { 53061da546Spatrick Update(); 54061da546Spatrick } 55061da546Spatrick Update()56061da546Spatrickbool LibStdcppTupleSyntheticFrontEnd::Update() { 57061da546Spatrick m_members.clear(); 58061da546Spatrick 59061da546Spatrick ValueObjectSP valobj_backend_sp = m_backend.GetSP(); 60061da546Spatrick if (!valobj_backend_sp) 61061da546Spatrick return false; 62061da546Spatrick 63061da546Spatrick ValueObjectSP next_child_sp = valobj_backend_sp->GetNonSyntheticValue(); 64061da546Spatrick while (next_child_sp != nullptr) { 65061da546Spatrick ValueObjectSP current_child = next_child_sp; 66061da546Spatrick next_child_sp = nullptr; 67061da546Spatrick 68061da546Spatrick size_t child_count = current_child->GetNumChildren(); 69061da546Spatrick for (size_t i = 0; i < child_count; ++i) { 70061da546Spatrick ValueObjectSP child_sp = current_child->GetChildAtIndex(i, true); 71061da546Spatrick llvm::StringRef name_str = child_sp->GetName().GetStringRef(); 72061da546Spatrick if (name_str.startswith("std::_Tuple_impl<")) { 73061da546Spatrick next_child_sp = child_sp; 74061da546Spatrick } else if (name_str.startswith("std::_Head_base<")) { 75061da546Spatrick ValueObjectSP value_sp = 76061da546Spatrick child_sp->GetChildMemberWithName(ConstString("_M_head_impl"), true); 77061da546Spatrick if (value_sp) { 78061da546Spatrick StreamString name; 79061da546Spatrick name.Printf("[%zd]", m_members.size()); 80061da546Spatrick m_members.push_back(value_sp->Clone(ConstString(name.GetString())).get()); 81061da546Spatrick } 82061da546Spatrick } 83061da546Spatrick } 84061da546Spatrick } 85061da546Spatrick 86061da546Spatrick return false; 87061da546Spatrick } 88061da546Spatrick MightHaveChildren()89061da546Spatrickbool LibStdcppTupleSyntheticFrontEnd::MightHaveChildren() { return true; } 90061da546Spatrick 91061da546Spatrick lldb::ValueObjectSP GetChildAtIndex(size_t idx)92061da546SpatrickLibStdcppTupleSyntheticFrontEnd::GetChildAtIndex(size_t idx) { 93061da546Spatrick if (idx < m_members.size() && m_members[idx]) 94061da546Spatrick return m_members[idx]->GetSP(); 95061da546Spatrick return lldb::ValueObjectSP(); 96061da546Spatrick } 97061da546Spatrick CalculateNumChildren()98061da546Spatricksize_t LibStdcppTupleSyntheticFrontEnd::CalculateNumChildren() { 99061da546Spatrick return m_members.size(); 100061da546Spatrick } 101061da546Spatrick GetIndexOfChildWithName(ConstString name)102061da546Spatricksize_t LibStdcppTupleSyntheticFrontEnd::GetIndexOfChildWithName( 103061da546Spatrick ConstString name) { 104061da546Spatrick return ExtractIndexFromString(name.GetCString()); 105061da546Spatrick } 106061da546Spatrick 107061da546Spatrick SyntheticChildrenFrontEnd * LibStdcppTupleSyntheticFrontEndCreator(CXXSyntheticChildren *,lldb::ValueObjectSP valobj_sp)108061da546Spatricklldb_private::formatters::LibStdcppTupleSyntheticFrontEndCreator( 109061da546Spatrick CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) { 110061da546Spatrick return (valobj_sp ? new LibStdcppTupleSyntheticFrontEnd(valobj_sp) : nullptr); 111061da546Spatrick } 112