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