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