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 15 using namespace lldb; 16 using namespace lldb_private; 17 using namespace lldb_private::formatters; 18 19 namespace lldb_private { 20 namespace formatters { 21 class LibcxxInitializerListSyntheticFrontEnd 22 : public SyntheticChildrenFrontEnd { 23 public: 24 LibcxxInitializerListSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp); 25 26 ~LibcxxInitializerListSyntheticFrontEnd() override; 27 28 size_t CalculateNumChildren() override; 29 30 lldb::ValueObjectSP GetChildAtIndex(size_t idx) override; 31 32 bool Update() override; 33 34 bool MightHaveChildren() override; 35 36 size_t GetIndexOfChildWithName(ConstString name) override; 37 38 private: 39 ValueObject *m_start = nullptr; 40 CompilerType m_element_type; 41 uint32_t m_element_size = 0; 42 size_t m_num_elements = 0; 43 }; 44 } // namespace formatters 45 } // namespace lldb_private 46 47 lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd:: 48 LibcxxInitializerListSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp) 49 : SyntheticChildrenFrontEnd(*valobj_sp), m_element_type() { 50 if (valobj_sp) 51 Update(); 52 } 53 54 lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd:: 55 ~LibcxxInitializerListSyntheticFrontEnd() { 56 // this needs to stay around because it's a child object who will follow its 57 // parent's life cycle 58 // delete m_start; 59 } 60 61 size_t lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd:: 62 CalculateNumChildren() { 63 static ConstString g_size_("__size_"); 64 m_num_elements = 0; 65 ValueObjectSP size_sp(m_backend.GetChildMemberWithName(g_size_, true)); 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:: 72 LibcxxInitializerListSyntheticFrontEnd::GetChildAtIndex(size_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 bool lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd:: 86 Update() { 87 static ConstString g_begin_("__begin_"); 88 89 m_start = nullptr; 90 m_num_elements = 0; 91 m_element_type = m_backend.GetCompilerType().GetTypeTemplateArgument(0); 92 if (!m_element_type.IsValid()) 93 return false; 94 95 if (llvm::Optional<uint64_t> size = m_element_type.GetByteSize(nullptr)) { 96 m_element_size = *size; 97 // Store raw pointers or end up with a circular dependency. 98 m_start = m_backend.GetChildMemberWithName(g_begin_, true).get(); 99 } 100 101 return false; 102 } 103 104 bool lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd:: 105 MightHaveChildren() { 106 return true; 107 } 108 109 size_t lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd:: 110 GetIndexOfChildWithName(ConstString name) { 111 if (!m_start) 112 return UINT32_MAX; 113 return ExtractIndexFromString(name.GetCString()); 114 } 115 116 lldb_private::SyntheticChildrenFrontEnd * 117 lldb_private::formatters::LibcxxInitializerListSyntheticFrontEndCreator( 118 CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) { 119 return (valobj_sp ? new LibcxxInitializerListSyntheticFrontEnd(valobj_sp) 120 : nullptr); 121 } 122