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 size_t CalculateNumChildren() override; 30 31 lldb::ValueObjectSP GetChildAtIndex(size_t idx) override; 32 33 bool 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:: 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:: 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 size_t lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd:: 63 CalculateNumChildren() { 64 static ConstString g_size_("__size_"); 65 m_num_elements = 0; 66 ValueObjectSP size_sp(m_backend.GetChildMemberWithName(g_size_, true)); 67 if (size_sp) 68 m_num_elements = size_sp->GetValueAsUnsigned(0); 69 return m_num_elements; 70 } 71 72 lldb::ValueObjectSP lldb_private::formatters:: 73 LibcxxInitializerListSyntheticFrontEnd::GetChildAtIndex(size_t idx) { 74 if (!m_start) 75 return lldb::ValueObjectSP(); 76 77 uint64_t offset = idx * m_element_size; 78 offset = offset + m_start->GetValueAsUnsigned(0); 79 StreamString name; 80 name.Printf("[%" PRIu64 "]", (uint64_t)idx); 81 return CreateValueObjectFromAddress(name.GetString(), offset, 82 m_backend.GetExecutionContextRef(), 83 m_element_type); 84 } 85 86 bool lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd:: 87 Update() { 88 static ConstString g_begin_("__begin_"); 89 90 m_start = nullptr; 91 m_num_elements = 0; 92 m_element_type = m_backend.GetCompilerType().GetTypeTemplateArgument(0); 93 if (!m_element_type.IsValid()) 94 return false; 95 96 if (std::optional<uint64_t> size = m_element_type.GetByteSize(nullptr)) { 97 m_element_size = *size; 98 // Store raw pointers or end up with a circular dependency. 99 m_start = m_backend.GetChildMemberWithName(g_begin_, true).get(); 100 } 101 102 return false; 103 } 104 105 bool lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd:: 106 MightHaveChildren() { 107 return true; 108 } 109 110 size_t lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd:: 111 GetIndexOfChildWithName(ConstString name) { 112 if (!m_start) 113 return UINT32_MAX; 114 return ExtractIndexFromString(name.GetCString()); 115 } 116 117 lldb_private::SyntheticChildrenFrontEnd * 118 lldb_private::formatters::LibcxxInitializerListSyntheticFrontEndCreator( 119 CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) { 120 return (valobj_sp ? new LibcxxInitializerListSyntheticFrontEnd(valobj_sp) 121 : nullptr); 122 } 123