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         };
54     } // namespace formatters
55 } // namespace lldb_private
56 
57 lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd::LibcxxInitializerListSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
58     SyntheticChildrenFrontEnd(*valobj_sp),
59     m_start(nullptr),
60     m_element_type(),
61     m_element_size(0),
62     m_num_elements(0)
63 {
64     if (valobj_sp)
65         Update();
66 }
67 
68 lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd::~LibcxxInitializerListSyntheticFrontEnd()
69 {
70     // this needs to stay around because it's a child object who will follow its parent's life cycle
71     // delete m_start;
72 }
73 
74 size_t
75 lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd::CalculateNumChildren ()
76 {
77     static ConstString g___size_("__size_");
78     m_num_elements = 0;
79     ValueObjectSP size_sp(m_backend.GetChildMemberWithName(g___size_, true));
80     if (size_sp)
81         m_num_elements = size_sp->GetValueAsUnsigned(0);
82     return m_num_elements;
83 }
84 
85 lldb::ValueObjectSP
86 lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd::GetChildAtIndex (size_t idx)
87 {
88     if (!m_start)
89         return lldb::ValueObjectSP();
90 
91     uint64_t offset = idx * m_element_size;
92     offset = offset + m_start->GetValueAsUnsigned(0);
93     StreamString name;
94     name.Printf("[%" PRIu64 "]", (uint64_t)idx);
95     return CreateValueObjectFromAddress(name.GetData(), offset, m_backend.GetExecutionContextRef(), m_element_type);
96 }
97 
98 bool
99 lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd::Update()
100 {
101     static ConstString g___begin_("__begin_");
102 
103     m_start = nullptr;
104     m_num_elements = 0;
105     lldb::TemplateArgumentKind kind;
106     m_element_type = m_backend.GetCompilerType().GetTemplateArgument(0, kind);
107     if (kind != lldb::eTemplateArgumentKindType || !m_element_type.IsValid())
108         return false;
109 
110     m_element_size = m_element_type.GetByteSize(nullptr);
111 
112     if (m_element_size > 0)
113         m_start = m_backend.GetChildMemberWithName(g___begin_,true).get(); // store raw pointers or end up with a circular dependency
114 
115     return false;
116 }
117 
118 bool
119 lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd::MightHaveChildren ()
120 {
121     return true;
122 }
123 
124 size_t
125 lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
126 {
127     if (!m_start)
128         return UINT32_MAX;
129     return ExtractIndexFromString(name.GetCString());
130 }
131 
132 lldb_private::SyntheticChildrenFrontEnd*
133 lldb_private::formatters::LibcxxInitializerListSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
134 {
135     return (valobj_sp ? new LibcxxInitializerListSyntheticFrontEnd(valobj_sp) : nullptr);
136 }
137