1 //===-- LibCxxInitializerList.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 11 #include "lldb/Core/ValueObject.h" 12 #include "lldb/DataFormatters/FormattersHelpers.h" 13 #include "lldb/Utility/ConstString.h" 14 #include <optional> 15 16 using namespace lldb; 17 using namespace lldb_private; 18 using namespace lldb_private::formatters; 19 20 namespace lldb_private { 21 namespace formatters { 22 class LibcxxInitializerListSyntheticFrontEnd 23 : public SyntheticChildrenFrontEnd { 24 public: 25 LibcxxInitializerListSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp); 26 27 ~LibcxxInitializerListSyntheticFrontEnd() override; 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 bool MightHaveChildren() override; 36 37 size_t GetIndexOfChildWithName(ConstString name) override; 38 39 private: 40 ValueObject *m_start = nullptr; 41 CompilerType m_element_type; 42 uint32_t m_element_size = 0; 43 size_t m_num_elements = 0; 44 }; 45 } // namespace formatters 46 } // namespace lldb_private 47 48 lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd:: LibcxxInitializerListSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)49 LibcxxInitializerListSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp) 50 : SyntheticChildrenFrontEnd(*valobj_sp), m_element_type() { 51 if (valobj_sp) 52 Update(); 53 } 54 55 lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd:: ~LibcxxInitializerListSyntheticFrontEnd()56 ~LibcxxInitializerListSyntheticFrontEnd() { 57 // this needs to stay around because it's a child object who will follow its 58 // parent's life cycle 59 // delete m_start; 60 } 61 62 llvm::Expected<uint32_t> lldb_private::formatters:: CalculateNumChildren()63 LibcxxInitializerListSyntheticFrontEnd::CalculateNumChildren() { 64 m_num_elements = 0; 65 ValueObjectSP size_sp(m_backend.GetChildMemberWithName("__size_")); 66 if (size_sp) 67 m_num_elements = size_sp->GetValueAsUnsigned(0); 68 return m_num_elements; 69 } 70 71 lldb::ValueObjectSP lldb_private::formatters:: GetChildAtIndex(uint32_t idx)72 LibcxxInitializerListSyntheticFrontEnd::GetChildAtIndex(uint32_t idx) { 73 if (!m_start) 74 return lldb::ValueObjectSP(); 75 76 uint64_t offset = idx * m_element_size; 77 offset = offset + m_start->GetValueAsUnsigned(0); 78 StreamString name; 79 name.Printf("[%" PRIu64 "]", (uint64_t)idx); 80 return CreateValueObjectFromAddress(name.GetString(), offset, 81 m_backend.GetExecutionContextRef(), 82 m_element_type); 83 } 84 85 lldb::ChildCacheState Update()86lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd::Update() { 87 m_start = nullptr; 88 m_num_elements = 0; 89 m_element_type = m_backend.GetCompilerType().GetTypeTemplateArgument(0); 90 if (!m_element_type.IsValid()) 91 return lldb::ChildCacheState::eRefetch; 92 93 if (std::optional<uint64_t> size = m_element_type.GetByteSize(nullptr)) { 94 m_element_size = *size; 95 // Store raw pointers or end up with a circular dependency. 96 m_start = m_backend.GetChildMemberWithName("__begin_").get(); 97 } 98 99 return lldb::ChildCacheState::eRefetch; 100 } 101 102 bool lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd:: MightHaveChildren()103 MightHaveChildren() { 104 return true; 105 } 106 107 size_t lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd:: GetIndexOfChildWithName(ConstString name)108 GetIndexOfChildWithName(ConstString name) { 109 if (!m_start) 110 return UINT32_MAX; 111 return ExtractIndexFromString(name.GetCString()); 112 } 113 114 lldb_private::SyntheticChildrenFrontEnd * LibcxxInitializerListSyntheticFrontEndCreator(CXXSyntheticChildren *,lldb::ValueObjectSP valobj_sp)115lldb_private::formatters::LibcxxInitializerListSyntheticFrontEndCreator( 116 CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) { 117 return (valobj_sp ? new LibcxxInitializerListSyntheticFrontEnd(valobj_sp) 118 : nullptr); 119 } 120