1 //===-- ValueObjectSyntheticFilter.cpp --------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
12 // Other libraries and framework includes
14 #include "lldb/Core/ValueObjectSyntheticFilter.h"
16 #include "lldb/Core/Log.h"
17 #include "lldb/Core/ValueObject.h"
18 #include "lldb/DataFormatters/TypeSynthetic.h"
20 using namespace lldb_private;
22 class DummySyntheticFrontEnd : public SyntheticChildrenFrontEnd
25 DummySyntheticFrontEnd(ValueObject &backend) :
26 SyntheticChildrenFrontEnd(backend)
30 CalculateNumChildren() override
32 return m_backend.GetNumChildren();
36 GetChildAtIndex(size_t idx) override
38 return m_backend.GetChildAtIndex(idx, true);
42 GetIndexOfChildWithName(const ConstString &name) override
44 return m_backend.GetIndexOfChildWithName(name);
48 MightHaveChildren() override
60 ValueObjectSynthetic::ValueObjectSynthetic (ValueObject &parent, lldb::SyntheticChildrenSP filter) :
65 m_synthetic_children_count(UINT32_MAX),
66 m_synthetic_children_cache(),
67 m_parent_type_name(parent.GetTypeName()),
68 m_might_have_children(eLazyBoolCalculate),
69 m_provides_value(eLazyBoolCalculate)
71 SetName(parent.GetName());
72 CopyValueData(m_parent);
76 ValueObjectSynthetic::~ValueObjectSynthetic() = default;
79 ValueObjectSynthetic::GetCompilerTypeImpl ()
81 return m_parent->GetCompilerType();
85 ValueObjectSynthetic::GetTypeName()
87 return m_parent->GetTypeName();
91 ValueObjectSynthetic::GetQualifiedTypeName()
93 return m_parent->GetQualifiedTypeName();
97 ValueObjectSynthetic::GetDisplayTypeName()
99 if (ConstString synth_name = m_synth_filter_ap->GetSyntheticTypeName())
102 return m_parent->GetDisplayTypeName();
106 ValueObjectSynthetic::CalculateNumChildren(uint32_t max)
108 Log* log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS);
110 UpdateValueIfNeeded();
111 if (m_synthetic_children_count < UINT32_MAX)
112 return m_synthetic_children_count <= max ? m_synthetic_children_count : max;
114 if (max < UINT32_MAX)
116 size_t num_children = m_synth_filter_ap->CalculateNumChildren(max);
118 log->Printf("[ValueObjectSynthetic::CalculateNumChildren] for VO of name %s and type %s, the filter returned %zu child values",
119 GetName().AsCString(),
120 GetTypeName().AsCString(),
126 size_t num_children = (m_synthetic_children_count = m_synth_filter_ap->CalculateNumChildren(max));
128 log->Printf("[ValueObjectSynthetic::CalculateNumChildren] for VO of name %s and type %s, the filter returned %zu child values",
129 GetName().AsCString(),
130 GetTypeName().AsCString(),
137 ValueObjectSynthetic::GetDynamicValue (lldb::DynamicValueType valueType)
140 return lldb::ValueObjectSP();
141 if (IsDynamic() && GetDynamicValueType() == valueType)
143 return m_parent->GetDynamicValue(valueType);
147 ValueObjectSynthetic::MightHaveChildren()
149 if (m_might_have_children == eLazyBoolCalculate)
150 m_might_have_children = (m_synth_filter_ap->MightHaveChildren() ? eLazyBoolYes : eLazyBoolNo);
151 return (m_might_have_children == eLazyBoolNo ? false : true);
155 ValueObjectSynthetic::GetByteSize()
157 return m_parent->GetByteSize();
161 ValueObjectSynthetic::GetValueType() const
163 return m_parent->GetValueType();
167 ValueObjectSynthetic::CreateSynthFilter ()
169 m_synth_filter_ap = (m_synth_sp->GetFrontEnd(*m_parent));
170 if (!m_synth_filter_ap.get())
171 m_synth_filter_ap.reset(new DummySyntheticFrontEnd(*m_parent));
175 ValueObjectSynthetic::UpdateValue ()
177 Log* log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS);
179 SetValueIsValid (false);
182 if (!m_parent->UpdateValueIfNeeded(false))
184 // our parent could not update.. as we are meaningless without a parent, just stop
185 if (m_parent->GetError().Fail())
186 m_error = m_parent->GetError();
190 // regenerate the synthetic filter if our typename changes
191 // <rdar://problem/12424824>
192 ConstString new_parent_type_name = m_parent->GetTypeName();
193 if (new_parent_type_name != m_parent_type_name)
196 log->Printf("[ValueObjectSynthetic::UpdateValue] name=%s, type changed from %s to %s, recomputing synthetic filter",
197 GetName().AsCString(),
198 m_parent_type_name.AsCString(),
199 new_parent_type_name.AsCString());
200 m_parent_type_name = new_parent_type_name;
204 // let our backend do its update
205 if (m_synth_filter_ap->Update() == false)
208 log->Printf("[ValueObjectSynthetic::UpdateValue] name=%s, synthetic filter said caches are stale - clearing", GetName().AsCString());
209 // filter said that cached values are stale
210 m_children_byindex.Clear();
211 m_name_toindex.Clear();
212 // usually, an object's value can change but this does not alter its children count
213 // for a synthetic VO that might indeed happen, so we need to tell the upper echelons
214 // that they need to come back to us asking for children
215 m_children_count_valid = false;
216 m_synthetic_children_cache.Clear();
217 m_synthetic_children_count = UINT32_MAX;
218 m_might_have_children = eLazyBoolCalculate;
223 log->Printf("[ValueObjectSynthetic::UpdateValue] name=%s, synthetic filter said caches are still valid", GetName().AsCString());
226 m_provides_value = eLazyBoolCalculate;
228 lldb::ValueObjectSP synth_val(m_synth_filter_ap->GetSyntheticValue());
230 if (synth_val && synth_val->CanProvideValue())
233 log->Printf("[ValueObjectSynthetic::UpdateValue] name=%s, synthetic filter said it can provide a value", GetName().AsCString());
235 m_provides_value = eLazyBoolYes;
236 CopyValueData(synth_val.get());
241 log->Printf("[ValueObjectSynthetic::UpdateValue] name=%s, synthetic filter said it will not provide a value", GetName().AsCString());
243 m_provides_value = eLazyBoolNo;
244 CopyValueData(m_parent);
247 SetValueIsValid(true);
252 ValueObjectSynthetic::GetChildAtIndex (size_t idx, bool can_create)
254 Log* log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS);
257 log->Printf("[ValueObjectSynthetic::GetChildAtIndex] name=%s, retrieving child at index %zu",
258 GetName().AsCString(),
261 UpdateValueIfNeeded();
264 if (m_children_byindex.GetValueForKey(idx, valobj) == false)
266 if (can_create && m_synth_filter_ap.get() != nullptr)
269 log->Printf("[ValueObjectSynthetic::GetChildAtIndex] name=%s, child at index %zu not cached and will be created",
270 GetName().AsCString(),
273 lldb::ValueObjectSP synth_guy = m_synth_filter_ap->GetChildAtIndex (idx);
276 log->Printf("[ValueObjectSynthetic::GetChildAtIndex] name=%s, child at index %zu created as %p (is synthetic: %s)",
277 GetName().AsCString(),
280 synth_guy.get() ? (synth_guy->IsSyntheticChildrenGenerated() ? "yes" : "no") : "no");
285 if (synth_guy->IsSyntheticChildrenGenerated())
286 m_synthetic_children_cache.AppendObject(synth_guy);
287 m_children_byindex.SetValueForKey(idx, synth_guy.get());
288 synth_guy->SetPreferredDisplayLanguageIfNeeded(GetPreferredDisplayLanguage());
294 log->Printf("[ValueObjectSynthetic::GetChildAtIndex] name=%s, child at index %zu not cached and cannot be created (can_create = %s, synth_filter = %p)",
295 GetName().AsCString(),
297 can_create ? "yes" : "no",
298 m_synth_filter_ap.get());
300 return lldb::ValueObjectSP();
306 log->Printf("[ValueObjectSynthetic::GetChildAtIndex] name=%s, child at index %zu cached as %p",
307 GetName().AsCString(),
311 return valobj->GetSP();
316 ValueObjectSynthetic::GetChildMemberWithName (const ConstString &name, bool can_create)
318 UpdateValueIfNeeded();
320 uint32_t index = GetIndexOfChildWithName(name);
322 if (index == UINT32_MAX)
323 return lldb::ValueObjectSP();
325 return GetChildAtIndex(index, can_create);
329 ValueObjectSynthetic::GetIndexOfChildWithName (const ConstString &name)
331 UpdateValueIfNeeded();
333 uint32_t found_index = UINT32_MAX;
334 bool did_find = m_name_toindex.GetValueForKey(name.GetCString(), found_index);
336 if (!did_find && m_synth_filter_ap.get() != nullptr)
338 uint32_t index = m_synth_filter_ap->GetIndexOfChildWithName (name);
339 if (index == UINT32_MAX)
341 m_name_toindex.SetValueForKey(name.GetCString(), index);
344 else if (!did_find && m_synth_filter_ap.get() == nullptr)
346 else /*if (iter != m_name_toindex.end())*/
351 ValueObjectSynthetic::IsInScope ()
353 return m_parent->IsInScope();
357 ValueObjectSynthetic::GetNonSyntheticValue ()
359 return m_parent->GetSP();
363 ValueObjectSynthetic::CopyValueData (ValueObject *source)
365 m_value = (source->UpdateValueIfNeeded(), source->GetValue());
366 ExecutionContext exe_ctx (GetExecutionContextRef());
367 m_error = m_value.GetValueAsData (&exe_ctx, m_data, 0, GetModule().get());
371 ValueObjectSynthetic::CanProvideValue ()
373 if (!UpdateValueIfNeeded())
375 if (m_provides_value == eLazyBoolYes)
377 return m_parent->CanProvideValue();
381 ValueObjectSynthetic::SetValueFromCString (const char *value_str, Error& error)
383 return m_parent->SetValueFromCString(value_str, error);
387 ValueObjectSynthetic::SetFormat (lldb::Format format)
391 m_parent->ClearUserVisibleData(eClearUserVisibleDataItemsAll);
392 m_parent->SetFormat(format);
394 this->ValueObject::SetFormat(format);
395 this->ClearUserVisibleData(eClearUserVisibleDataItemsAll);
399 ValueObjectSynthetic::SetPreferredDisplayLanguage (lldb::LanguageType lang)
401 this->ValueObject::SetPreferredDisplayLanguage(lang);
403 m_parent->SetPreferredDisplayLanguage(lang);
407 ValueObjectSynthetic::GetPreferredDisplayLanguage ()
409 if (m_preferred_display_language == lldb::eLanguageTypeUnknown)
412 return m_parent->GetPreferredDisplayLanguage();
413 return lldb::eLanguageTypeUnknown;
416 return m_preferred_display_language;
420 ValueObjectSynthetic::IsSyntheticChildrenGenerated ()
423 return m_parent->IsSyntheticChildrenGenerated();
428 ValueObjectSynthetic::SetSyntheticChildrenGenerated (bool b)
431 m_parent->SetSyntheticChildrenGenerated(b);
432 this->ValueObject::SetSyntheticChildrenGenerated(b);
436 ValueObjectSynthetic::GetDeclaration (Declaration &decl)
439 return m_parent->GetDeclaration(decl);
441 return ValueObject::GetDeclaration(decl);
445 ValueObjectSynthetic::GetLanguageFlags ()
448 return m_parent->GetLanguageFlags();
449 return this->ValueObject::GetLanguageFlags();
453 ValueObjectSynthetic::SetLanguageFlags (uint64_t flags)
456 m_parent->SetLanguageFlags(flags);
458 this->ValueObject::SetLanguageFlags(flags);