15ffd83dbSDimitry Andric //===-- LibCxxTuple.cpp ---------------------------------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #include "LibCxx.h" 100b57cec5SDimitry Andric #include "lldb/DataFormatters/FormattersHelpers.h" 110b57cec5SDimitry Andric 120b57cec5SDimitry Andric using namespace lldb; 130b57cec5SDimitry Andric using namespace lldb_private; 140b57cec5SDimitry Andric 150b57cec5SDimitry Andric namespace { 160b57cec5SDimitry Andric 170b57cec5SDimitry Andric class TupleFrontEnd: public SyntheticChildrenFrontEnd { 180b57cec5SDimitry Andric public: 190b57cec5SDimitry Andric TupleFrontEnd(ValueObject &valobj) : SyntheticChildrenFrontEnd(valobj) { 200b57cec5SDimitry Andric Update(); 210b57cec5SDimitry Andric } 220b57cec5SDimitry Andric 230b57cec5SDimitry Andric size_t GetIndexOfChildWithName(ConstString name) override { 240b57cec5SDimitry Andric return formatters::ExtractIndexFromString(name.GetCString()); 250b57cec5SDimitry Andric } 260b57cec5SDimitry Andric 270b57cec5SDimitry Andric bool MightHaveChildren() override { return true; } 28*0fca6ea1SDimitry Andric lldb::ChildCacheState Update() override; 29*0fca6ea1SDimitry Andric llvm::Expected<uint32_t> CalculateNumChildren() override { 30*0fca6ea1SDimitry Andric return m_elements.size(); 31*0fca6ea1SDimitry Andric } 32*0fca6ea1SDimitry Andric ValueObjectSP GetChildAtIndex(uint32_t idx) override; 330b57cec5SDimitry Andric 340b57cec5SDimitry Andric private: 359dba64beSDimitry Andric // The lifetime of a ValueObject and all its derivative ValueObjects 369dba64beSDimitry Andric // (children, clones, etc.) is managed by a ClusterManager. These 379dba64beSDimitry Andric // objects are only destroyed when every shared pointer to any of them 389dba64beSDimitry Andric // is destroyed, so we must not store a shared pointer to any ValueObject 399dba64beSDimitry Andric // derived from our backend ValueObject (since we're in the same cluster). 409dba64beSDimitry Andric std::vector<ValueObject*> m_elements; 419dba64beSDimitry Andric ValueObject* m_base = nullptr; 420b57cec5SDimitry Andric }; 430b57cec5SDimitry Andric } 440b57cec5SDimitry Andric 45*0fca6ea1SDimitry Andric lldb::ChildCacheState TupleFrontEnd::Update() { 460b57cec5SDimitry Andric m_elements.clear(); 479dba64beSDimitry Andric m_base = nullptr; 489dba64beSDimitry Andric 499dba64beSDimitry Andric ValueObjectSP base_sp; 5006c3fb27SDimitry Andric base_sp = m_backend.GetChildMemberWithName("__base_"); 519dba64beSDimitry Andric if (!base_sp) { 520b57cec5SDimitry Andric // Pre r304382 name of the base element. 5306c3fb27SDimitry Andric base_sp = m_backend.GetChildMemberWithName("base_"); 540b57cec5SDimitry Andric } 559dba64beSDimitry Andric if (!base_sp) 56*0fca6ea1SDimitry Andric return lldb::ChildCacheState::eRefetch; 579dba64beSDimitry Andric m_base = base_sp.get(); 589dba64beSDimitry Andric m_elements.assign(base_sp->GetCompilerType().GetNumDirectBaseClasses(), 599dba64beSDimitry Andric nullptr); 60*0fca6ea1SDimitry Andric return lldb::ChildCacheState::eRefetch; 610b57cec5SDimitry Andric } 620b57cec5SDimitry Andric 63*0fca6ea1SDimitry Andric ValueObjectSP TupleFrontEnd::GetChildAtIndex(uint32_t idx) { 640b57cec5SDimitry Andric if (idx >= m_elements.size()) 650b57cec5SDimitry Andric return ValueObjectSP(); 669dba64beSDimitry Andric if (!m_base) 670b57cec5SDimitry Andric return ValueObjectSP(); 680b57cec5SDimitry Andric if (m_elements[idx]) 699dba64beSDimitry Andric return m_elements[idx]->GetSP(); 700b57cec5SDimitry Andric 710b57cec5SDimitry Andric CompilerType holder_type = 729dba64beSDimitry Andric m_base->GetCompilerType().GetDirectBaseClassAtIndex(idx, nullptr); 730b57cec5SDimitry Andric if (!holder_type) 740b57cec5SDimitry Andric return ValueObjectSP(); 7506c3fb27SDimitry Andric ValueObjectSP holder_sp = m_base->GetChildAtIndex(idx); 760b57cec5SDimitry Andric if (!holder_sp) 770b57cec5SDimitry Andric return ValueObjectSP(); 780b57cec5SDimitry Andric 7906c3fb27SDimitry Andric ValueObjectSP elem_sp = holder_sp->GetChildAtIndex(0); 800b57cec5SDimitry Andric if (elem_sp) 810b57cec5SDimitry Andric m_elements[idx] = 829dba64beSDimitry Andric elem_sp->Clone(ConstString(llvm::formatv("[{0}]", idx).str())).get(); 830b57cec5SDimitry Andric 849dba64beSDimitry Andric if (m_elements[idx]) 859dba64beSDimitry Andric return m_elements[idx]->GetSP(); 869dba64beSDimitry Andric return ValueObjectSP(); 870b57cec5SDimitry Andric } 880b57cec5SDimitry Andric 890b57cec5SDimitry Andric SyntheticChildrenFrontEnd * 900b57cec5SDimitry Andric formatters::LibcxxTupleFrontEndCreator(CXXSyntheticChildren *, 910b57cec5SDimitry Andric lldb::ValueObjectSP valobj_sp) { 920b57cec5SDimitry Andric if (valobj_sp) 930b57cec5SDimitry Andric return new TupleFrontEnd(*valobj_sp); 940b57cec5SDimitry Andric return nullptr; 950b57cec5SDimitry Andric } 96