1 //===-- LibCxxInitializerList.cpp ----------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "LibCxx.h" 11 12 #include "lldb/Core/ConstString.h" 13 #include "lldb/Core/ValueObject.h" 14 #include "lldb/DataFormatters/FormattersHelpers.h" 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 : public SyntheticChildrenFrontEnd 23 { 24 public: 25 LibcxxInitializerListSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); 26 27 virtual size_t 28 CalculateNumChildren (); 29 30 virtual lldb::ValueObjectSP 31 GetChildAtIndex (size_t idx); 32 33 virtual bool 34 Update(); 35 36 virtual bool 37 MightHaveChildren (); 38 39 virtual size_t 40 GetIndexOfChildWithName (const ConstString &name); 41 42 virtual 43 ~LibcxxInitializerListSyntheticFrontEnd (); 44 private: 45 ValueObject* m_start; 46 CompilerType m_element_type; 47 uint32_t m_element_size; 48 size_t m_num_elements; 49 std::map<size_t,lldb::ValueObjectSP> m_children; 50 }; 51 } 52 } 53 54 lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd::LibcxxInitializerListSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : 55 SyntheticChildrenFrontEnd(*valobj_sp.get()), 56 m_start(NULL), 57 m_element_type(), 58 m_element_size(0), 59 m_num_elements(0), 60 m_children() 61 { 62 if (valobj_sp) 63 Update(); 64 } 65 66 size_t 67 lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd::CalculateNumChildren () 68 { 69 static ConstString g___size_("__size_"); 70 m_num_elements = 0; 71 ValueObjectSP size_sp(m_backend.GetChildMemberWithName(g___size_, true)); 72 if (size_sp) 73 m_num_elements = size_sp->GetValueAsUnsigned(0); 74 return m_num_elements; 75 } 76 77 lldb::ValueObjectSP 78 lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd::GetChildAtIndex (size_t idx) 79 { 80 if (!m_start) 81 return lldb::ValueObjectSP(); 82 83 auto cached = m_children.find(idx); 84 if (cached != m_children.end()) 85 return cached->second; 86 87 uint64_t offset = idx * m_element_size; 88 offset = offset + m_start->GetValueAsUnsigned(0); 89 StreamString name; 90 name.Printf("[%" PRIu64 "]", (uint64_t)idx); 91 ValueObjectSP child_sp = CreateValueObjectFromAddress(name.GetData(), offset, m_backend.GetExecutionContextRef(), m_element_type); 92 m_children[idx] = child_sp; 93 return child_sp; 94 } 95 96 bool 97 lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd::Update() 98 { 99 static ConstString g___begin_("__begin_"); 100 101 m_start = nullptr; 102 m_num_elements = 0; 103 m_children.clear(); 104 lldb::TemplateArgumentKind kind; 105 m_element_type = m_backend.GetCompilerType().GetTemplateArgument(0, kind); 106 if (kind != lldb::eTemplateArgumentKindType || false == m_element_type.IsValid()) 107 return false; 108 109 m_element_size = m_element_type.GetByteSize(nullptr); 110 111 if (m_element_size > 0) 112 m_start = m_backend.GetChildMemberWithName(g___begin_,true).get(); // store raw pointers or end up with a circular dependency 113 114 return false; 115 } 116 117 bool 118 lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd::MightHaveChildren () 119 { 120 return true; 121 } 122 123 size_t 124 lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) 125 { 126 if (!m_start) 127 return UINT32_MAX; 128 return ExtractIndexFromString(name.GetCString()); 129 } 130 131 lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd::~LibcxxInitializerListSyntheticFrontEnd () 132 { 133 // this needs to stay around because it's a child object who will follow its parent's life cycle 134 // delete m_start; 135 } 136 137 lldb_private::SyntheticChildrenFrontEnd* 138 lldb_private::formatters::LibcxxInitializerListSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp) 139 { 140 if (!valobj_sp) 141 return NULL; 142 return (new LibcxxInitializerListSyntheticFrontEnd(valobj_sp)); 143 } 144 145