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-exception 6 // 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 19 using namespace lldb; 20 using namespace lldb_private; 21 using namespace lldb_private::formatters; 22 23 namespace { 24 25 class LibStdcppTupleSyntheticFrontEnd : public SyntheticChildrenFrontEnd { 26 public: 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 37 private: 38 // The lifetime of a ValueObject and all its derivative ValueObjects 39 // (children, clones, etc.) is managed by a ClusterManager. These 40 // objects are only destroyed when every shared pointer to any of them 41 // is destroyed, so we must not store a shared pointer to any ValueObject 42 // derived from our backend ValueObject (since we're in the same cluster). 43 std::vector<ValueObject*> m_members; 44 }; 45 46 } // end of anonymous namespace 47 LibStdcppTupleSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)48LibStdcppTupleSyntheticFrontEnd::LibStdcppTupleSyntheticFrontEnd( 49 lldb::ValueObjectSP valobj_sp) 50 : SyntheticChildrenFrontEnd(*valobj_sp) { 51 Update(); 52 } 53 Update()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 87 lldb::ValueObjectSP GetChildAtIndex(uint32_t idx)88LibStdcppTupleSyntheticFrontEnd::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 94 llvm::Expected<uint32_t> CalculateNumChildren()95LibStdcppTupleSyntheticFrontEnd::CalculateNumChildren() { 96 return m_members.size(); 97 } 98 99 llvm::Expected<size_t> GetIndexOfChildWithName(ConstString name)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 109 SyntheticChildrenFrontEnd * LibStdcppTupleSyntheticFrontEndCreator(CXXSyntheticChildren *,lldb::ValueObjectSP valobj_sp)110lldb_private::formatters::LibStdcppTupleSyntheticFrontEndCreator( 111 CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) { 112 return (valobj_sp ? new LibStdcppTupleSyntheticFrontEnd(valobj_sp) : nullptr); 113 } 114