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