1 //===-- LibCxxTuple.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 "LibCxx.h" 10 #include "lldb/DataFormatters/FormattersHelpers.h" 11 12 using namespace lldb; 13 using namespace lldb_private; 14 15 namespace { 16 17 class TupleFrontEnd: public SyntheticChildrenFrontEnd { 18 public: TupleFrontEnd(ValueObject & valobj)19 TupleFrontEnd(ValueObject &valobj) : SyntheticChildrenFrontEnd(valobj) { 20 Update(); 21 } 22 GetIndexOfChildWithName(ConstString name)23 size_t GetIndexOfChildWithName(ConstString name) override { 24 return formatters::ExtractIndexFromString(name.GetCString()); 25 } 26 MightHaveChildren()27 bool MightHaveChildren() override { return true; } 28 lldb::ChildCacheState Update() override; CalculateNumChildren()29 llvm::Expected<uint32_t> CalculateNumChildren() override { 30 return m_elements.size(); 31 } 32 ValueObjectSP GetChildAtIndex(uint32_t idx) override; 33 34 private: 35 // The lifetime of a ValueObject and all its derivative ValueObjects 36 // (children, clones, etc.) is managed by a ClusterManager. These 37 // objects are only destroyed when every shared pointer to any of them 38 // is destroyed, so we must not store a shared pointer to any ValueObject 39 // derived from our backend ValueObject (since we're in the same cluster). 40 std::vector<ValueObject*> m_elements; 41 ValueObject* m_base = nullptr; 42 }; 43 } 44 Update()45lldb::ChildCacheState TupleFrontEnd::Update() { 46 m_elements.clear(); 47 m_base = nullptr; 48 49 ValueObjectSP base_sp; 50 base_sp = m_backend.GetChildMemberWithName("__base_"); 51 if (!base_sp) { 52 // Pre r304382 name of the base element. 53 base_sp = m_backend.GetChildMemberWithName("base_"); 54 } 55 if (!base_sp) 56 return lldb::ChildCacheState::eRefetch; 57 m_base = base_sp.get(); 58 m_elements.assign(base_sp->GetCompilerType().GetNumDirectBaseClasses(), 59 nullptr); 60 return lldb::ChildCacheState::eRefetch; 61 } 62 GetChildAtIndex(uint32_t idx)63ValueObjectSP TupleFrontEnd::GetChildAtIndex(uint32_t idx) { 64 if (idx >= m_elements.size()) 65 return ValueObjectSP(); 66 if (!m_base) 67 return ValueObjectSP(); 68 if (m_elements[idx]) 69 return m_elements[idx]->GetSP(); 70 71 CompilerType holder_type = 72 m_base->GetCompilerType().GetDirectBaseClassAtIndex(idx, nullptr); 73 if (!holder_type) 74 return ValueObjectSP(); 75 ValueObjectSP holder_sp = m_base->GetChildAtIndex(idx); 76 if (!holder_sp) 77 return ValueObjectSP(); 78 79 ValueObjectSP elem_sp = holder_sp->GetChildAtIndex(0); 80 if (elem_sp) 81 m_elements[idx] = 82 elem_sp->Clone(ConstString(llvm::formatv("[{0}]", idx).str())).get(); 83 84 if (m_elements[idx]) 85 return m_elements[idx]->GetSP(); 86 return ValueObjectSP(); 87 } 88 89 SyntheticChildrenFrontEnd * LibcxxTupleFrontEndCreator(CXXSyntheticChildren *,lldb::ValueObjectSP valobj_sp)90formatters::LibcxxTupleFrontEndCreator(CXXSyntheticChildren *, 91 lldb::ValueObjectSP valobj_sp) { 92 if (valobj_sp) 93 return new TupleFrontEnd(*valobj_sp); 94 return nullptr; 95 } 96