1 //===-- ValueObjectSyntheticFilter.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 "lldb/lldb-python.h"
11
12 #include "lldb/Core/ValueObjectSyntheticFilter.h"
13
14 // C Includes
15 // C++ Includes
16 // Other libraries and framework includes
17 // Project includes
18 #include "lldb/Core/ValueObject.h"
19 #include "lldb/DataFormatters/FormatClasses.h"
20
21 using namespace lldb_private;
22
23 class DummySyntheticFrontEnd : public SyntheticChildrenFrontEnd
24 {
25 public:
DummySyntheticFrontEnd(ValueObject & backend)26 DummySyntheticFrontEnd(ValueObject &backend) :
27 SyntheticChildrenFrontEnd(backend)
28 {}
29
30 size_t
CalculateNumChildren()31 CalculateNumChildren()
32 {
33 return 0;
34 }
35
36 lldb::ValueObjectSP
GetChildAtIndex(size_t idx)37 GetChildAtIndex (size_t idx)
38 {
39 return lldb::ValueObjectSP();
40 }
41
42 size_t
GetIndexOfChildWithName(const ConstString & name)43 GetIndexOfChildWithName (const ConstString &name)
44 {
45 return UINT32_MAX;
46 }
47
48 bool
MightHaveChildren()49 MightHaveChildren ()
50 {
51 return true;
52 }
53
54 bool
Update()55 Update()
56 {
57 return false;
58 }
59
60 };
61
ValueObjectSynthetic(ValueObject & parent,lldb::SyntheticChildrenSP filter)62 ValueObjectSynthetic::ValueObjectSynthetic (ValueObject &parent, lldb::SyntheticChildrenSP filter) :
63 ValueObject(parent),
64 m_synth_sp(filter),
65 m_children_byindex(),
66 m_name_toindex(),
67 m_synthetic_children_count(UINT32_MAX),
68 m_parent_type_name(parent.GetTypeName()),
69 m_might_have_children(eLazyBoolCalculate)
70 {
71 #ifdef LLDB_CONFIGURATION_DEBUG
72 std::string new_name(parent.GetName().AsCString());
73 new_name += "$$__synth__";
74 SetName (ConstString(new_name.c_str()));
75 #else
76 SetName(parent.GetName());
77 #endif
78 CopyParentData();
79 CreateSynthFilter();
80 }
81
~ValueObjectSynthetic()82 ValueObjectSynthetic::~ValueObjectSynthetic()
83 {
84 }
85
86 ClangASTType
GetClangTypeImpl()87 ValueObjectSynthetic::GetClangTypeImpl ()
88 {
89 return m_parent->GetClangType();
90 }
91
92 ConstString
GetTypeName()93 ValueObjectSynthetic::GetTypeName()
94 {
95 return m_parent->GetTypeName();
96 }
97
98 ConstString
GetQualifiedTypeName()99 ValueObjectSynthetic::GetQualifiedTypeName()
100 {
101 return m_parent->GetQualifiedTypeName();
102 }
103
104 size_t
CalculateNumChildren()105 ValueObjectSynthetic::CalculateNumChildren()
106 {
107 UpdateValueIfNeeded();
108 if (m_synthetic_children_count < UINT32_MAX)
109 return m_synthetic_children_count;
110 return (m_synthetic_children_count = m_synth_filter_ap->CalculateNumChildren());
111 }
112
113 lldb::ValueObjectSP
GetDynamicValue(lldb::DynamicValueType valueType)114 ValueObjectSynthetic::GetDynamicValue (lldb::DynamicValueType valueType)
115 {
116 if (!m_parent)
117 return lldb::ValueObjectSP();
118 if (IsDynamic() && GetDynamicValueType() == valueType)
119 return GetSP();
120 return m_parent->GetDynamicValue(valueType);
121 }
122
123 bool
MightHaveChildren()124 ValueObjectSynthetic::MightHaveChildren()
125 {
126 if (m_might_have_children == eLazyBoolCalculate)
127 m_might_have_children = (m_synth_filter_ap->MightHaveChildren() ? eLazyBoolYes : eLazyBoolNo);
128 return (m_might_have_children == eLazyBoolNo ? false : true);
129 }
130
131 uint64_t
GetByteSize()132 ValueObjectSynthetic::GetByteSize()
133 {
134 return m_parent->GetByteSize();
135 }
136
137 lldb::ValueType
GetValueType() const138 ValueObjectSynthetic::GetValueType() const
139 {
140 return m_parent->GetValueType();
141 }
142
143 void
CreateSynthFilter()144 ValueObjectSynthetic::CreateSynthFilter ()
145 {
146 m_synth_filter_ap = (m_synth_sp->GetFrontEnd(*m_parent));
147 if (!m_synth_filter_ap.get())
148 m_synth_filter_ap.reset(new DummySyntheticFrontEnd(*m_parent));
149 }
150
151 bool
UpdateValue()152 ValueObjectSynthetic::UpdateValue ()
153 {
154 SetValueIsValid (false);
155 m_error.Clear();
156
157 if (!m_parent->UpdateValueIfNeeded(false))
158 {
159 // our parent could not update.. as we are meaningless without a parent, just stop
160 if (m_parent->GetError().Fail())
161 m_error = m_parent->GetError();
162 return false;
163 }
164
165 // regenerate the synthetic filter if our typename changes
166 // <rdar://problem/12424824>
167 ConstString new_parent_type_name = m_parent->GetTypeName();
168 if (new_parent_type_name != m_parent_type_name)
169 {
170 m_parent_type_name = new_parent_type_name;
171 CreateSynthFilter();
172 }
173
174 // let our backend do its update
175 if (m_synth_filter_ap->Update() == false)
176 {
177 // filter said that cached values are stale
178 m_children_byindex.clear();
179 m_name_toindex.clear();
180 // usually, an object's value can change but this does not alter its children count
181 // for a synthetic VO that might indeed happen, so we need to tell the upper echelons
182 // that they need to come back to us asking for children
183 m_children_count_valid = false;
184 m_synthetic_children_count = UINT32_MAX;
185 m_might_have_children = eLazyBoolCalculate;
186 }
187
188 CopyParentData();
189
190 SetValueIsValid(true);
191 return true;
192 }
193
194 lldb::ValueObjectSP
GetChildAtIndex(size_t idx,bool can_create)195 ValueObjectSynthetic::GetChildAtIndex (size_t idx, bool can_create)
196 {
197 UpdateValueIfNeeded();
198
199 ByIndexIterator iter = m_children_byindex.find(idx);
200
201 if (iter == m_children_byindex.end())
202 {
203 if (can_create && m_synth_filter_ap.get() != NULL)
204 {
205 lldb::ValueObjectSP synth_guy = m_synth_filter_ap->GetChildAtIndex (idx);
206 if (!synth_guy)
207 return synth_guy;
208 m_children_byindex[idx]= synth_guy.get();
209 return synth_guy;
210 }
211 else
212 return lldb::ValueObjectSP();
213 }
214 else
215 return iter->second->GetSP();
216 }
217
218 lldb::ValueObjectSP
GetChildMemberWithName(const ConstString & name,bool can_create)219 ValueObjectSynthetic::GetChildMemberWithName (const ConstString &name, bool can_create)
220 {
221 UpdateValueIfNeeded();
222
223 uint32_t index = GetIndexOfChildWithName(name);
224
225 if (index == UINT32_MAX)
226 return lldb::ValueObjectSP();
227
228 return GetChildAtIndex(index, can_create);
229 }
230
231 size_t
GetIndexOfChildWithName(const ConstString & name)232 ValueObjectSynthetic::GetIndexOfChildWithName (const ConstString &name)
233 {
234 UpdateValueIfNeeded();
235
236 NameToIndexIterator iter = m_name_toindex.find(name.GetCString());
237
238 if (iter == m_name_toindex.end() && m_synth_filter_ap.get() != NULL)
239 {
240 uint32_t index = m_synth_filter_ap->GetIndexOfChildWithName (name);
241 if (index == UINT32_MAX)
242 return index;
243 m_name_toindex[name.GetCString()] = index;
244 return index;
245 }
246 else if (iter == m_name_toindex.end() && m_synth_filter_ap.get() == NULL)
247 return UINT32_MAX;
248 else /*if (iter != m_name_toindex.end())*/
249 return iter->second;
250 }
251
252 bool
IsInScope()253 ValueObjectSynthetic::IsInScope ()
254 {
255 return m_parent->IsInScope();
256 }
257
258 lldb::ValueObjectSP
GetNonSyntheticValue()259 ValueObjectSynthetic::GetNonSyntheticValue ()
260 {
261 return m_parent->GetSP();
262 }
263
264 void
CopyParentData()265 ValueObjectSynthetic::CopyParentData ()
266 {
267 m_value = m_parent->GetValue();
268 ExecutionContext exe_ctx (GetExecutionContextRef());
269 m_error = m_value.GetValueAsData (&exe_ctx, m_data, 0, GetModule().get());
270 }
271