//===-- ValueObjectSyntheticFilter.cpp -----------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "lldb/lldb-python.h" #include "lldb/Core/ValueObjectSyntheticFilter.h" // C Includes // C++ Includes // Other libraries and framework includes // Project includes #include "lldb/Core/ValueObject.h" #include "lldb/DataFormatters/TypeSynthetic.h" using namespace lldb_private; class DummySyntheticFrontEnd : public SyntheticChildrenFrontEnd { public: DummySyntheticFrontEnd(ValueObject &backend) : SyntheticChildrenFrontEnd(backend) {} size_t CalculateNumChildren() { return m_backend.GetNumChildren(); } lldb::ValueObjectSP GetChildAtIndex (size_t idx) { return m_backend.GetChildAtIndex(idx, true); } size_t GetIndexOfChildWithName (const ConstString &name) { return m_backend.GetIndexOfChildWithName(name); } bool MightHaveChildren () { return true; } bool Update() { return false; } }; ValueObjectSynthetic::ValueObjectSynthetic (ValueObject &parent, lldb::SyntheticChildrenSP filter) : ValueObject(parent), m_synth_sp(filter), m_children_byindex(), m_name_toindex(), m_synthetic_children_count(UINT32_MAX), m_parent_type_name(parent.GetTypeName()), m_might_have_children(eLazyBoolCalculate) { #ifdef LLDB_CONFIGURATION_DEBUG std::string new_name(parent.GetName().AsCString()); new_name += "$$__synth__"; SetName (ConstString(new_name.c_str())); #else SetName(parent.GetName()); #endif CopyParentData(); CreateSynthFilter(); } ValueObjectSynthetic::~ValueObjectSynthetic() { } ClangASTType ValueObjectSynthetic::GetClangTypeImpl () { return m_parent->GetClangType(); } ConstString ValueObjectSynthetic::GetTypeName() { return m_parent->GetTypeName(); } ConstString ValueObjectSynthetic::GetQualifiedTypeName() { return m_parent->GetQualifiedTypeName(); } size_t ValueObjectSynthetic::CalculateNumChildren() { UpdateValueIfNeeded(); if (m_synthetic_children_count < UINT32_MAX) return m_synthetic_children_count; return (m_synthetic_children_count = m_synth_filter_ap->CalculateNumChildren()); } lldb::ValueObjectSP ValueObjectSynthetic::GetDynamicValue (lldb::DynamicValueType valueType) { if (!m_parent) return lldb::ValueObjectSP(); if (IsDynamic() && GetDynamicValueType() == valueType) return GetSP(); return m_parent->GetDynamicValue(valueType); } bool ValueObjectSynthetic::MightHaveChildren() { if (m_might_have_children == eLazyBoolCalculate) m_might_have_children = (m_synth_filter_ap->MightHaveChildren() ? eLazyBoolYes : eLazyBoolNo); return (m_might_have_children == eLazyBoolNo ? false : true); } uint64_t ValueObjectSynthetic::GetByteSize() { return m_parent->GetByteSize(); } lldb::ValueType ValueObjectSynthetic::GetValueType() const { return m_parent->GetValueType(); } void ValueObjectSynthetic::CreateSynthFilter () { m_synth_filter_ap = (m_synth_sp->GetFrontEnd(*m_parent)); if (!m_synth_filter_ap.get()) m_synth_filter_ap.reset(new DummySyntheticFrontEnd(*m_parent)); } bool ValueObjectSynthetic::UpdateValue () { SetValueIsValid (false); m_error.Clear(); if (!m_parent->UpdateValueIfNeeded(false)) { // our parent could not update.. as we are meaningless without a parent, just stop if (m_parent->GetError().Fail()) m_error = m_parent->GetError(); return false; } // regenerate the synthetic filter if our typename changes // ConstString new_parent_type_name = m_parent->GetTypeName(); if (new_parent_type_name != m_parent_type_name) { m_parent_type_name = new_parent_type_name; CreateSynthFilter(); } // let our backend do its update if (m_synth_filter_ap->Update() == false) { // filter said that cached values are stale m_children_byindex.clear(); m_name_toindex.clear(); // usually, an object's value can change but this does not alter its children count // for a synthetic VO that might indeed happen, so we need to tell the upper echelons // that they need to come back to us asking for children m_children_count_valid = false; m_synthetic_children_count = UINT32_MAX; m_might_have_children = eLazyBoolCalculate; } CopyParentData(); SetValueIsValid(true); return true; } lldb::ValueObjectSP ValueObjectSynthetic::GetChildAtIndex (size_t idx, bool can_create) { UpdateValueIfNeeded(); ByIndexIterator iter = m_children_byindex.find(idx); if (iter == m_children_byindex.end()) { if (can_create && m_synth_filter_ap.get() != NULL) { lldb::ValueObjectSP synth_guy = m_synth_filter_ap->GetChildAtIndex (idx); if (!synth_guy) return synth_guy; m_children_byindex[idx]= synth_guy.get(); return synth_guy; } else return lldb::ValueObjectSP(); } else return iter->second->GetSP(); } lldb::ValueObjectSP ValueObjectSynthetic::GetChildMemberWithName (const ConstString &name, bool can_create) { UpdateValueIfNeeded(); uint32_t index = GetIndexOfChildWithName(name); if (index == UINT32_MAX) return lldb::ValueObjectSP(); return GetChildAtIndex(index, can_create); } size_t ValueObjectSynthetic::GetIndexOfChildWithName (const ConstString &name) { UpdateValueIfNeeded(); NameToIndexIterator iter = m_name_toindex.find(name.GetCString()); if (iter == m_name_toindex.end() && m_synth_filter_ap.get() != NULL) { uint32_t index = m_synth_filter_ap->GetIndexOfChildWithName (name); if (index == UINT32_MAX) return index; m_name_toindex[name.GetCString()] = index; return index; } else if (iter == m_name_toindex.end() && m_synth_filter_ap.get() == NULL) return UINT32_MAX; else /*if (iter != m_name_toindex.end())*/ return iter->second; } bool ValueObjectSynthetic::IsInScope () { return m_parent->IsInScope(); } lldb::ValueObjectSP ValueObjectSynthetic::GetNonSyntheticValue () { return m_parent->GetSP(); } void ValueObjectSynthetic::CopyParentData () { m_value = m_parent->GetValue(); ExecutionContext exe_ctx (GetExecutionContextRef()); m_error = m_value.GetValueAsData (&exe_ctx, m_data, 0, GetModule().get()); }