ValueObjectSyntheticFilter.cpp revision 263363
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 21using namespace lldb_private; 22 23class DummySyntheticFrontEnd : public SyntheticChildrenFrontEnd 24{ 25public: 26 DummySyntheticFrontEnd(ValueObject &backend) : 27 SyntheticChildrenFrontEnd(backend) 28 {} 29 30 size_t 31 CalculateNumChildren() 32 { 33 return m_backend.GetNumChildren(); 34 } 35 36 lldb::ValueObjectSP 37 GetChildAtIndex (size_t idx) 38 { 39 return m_backend.GetChildAtIndex(idx, true); 40 } 41 42 size_t 43 GetIndexOfChildWithName (const ConstString &name) 44 { 45 return m_backend.GetIndexOfChildWithName(name); 46 } 47 48 bool 49 MightHaveChildren () 50 { 51 return true; 52 } 53 54 bool 55 Update() 56 { 57 return false; 58 } 59 60}; 61 62ValueObjectSynthetic::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 82ValueObjectSynthetic::~ValueObjectSynthetic() 83{ 84} 85 86ClangASTType 87ValueObjectSynthetic::GetClangTypeImpl () 88{ 89 return m_parent->GetClangType(); 90} 91 92ConstString 93ValueObjectSynthetic::GetTypeName() 94{ 95 return m_parent->GetTypeName(); 96} 97 98ConstString 99ValueObjectSynthetic::GetQualifiedTypeName() 100{ 101 return m_parent->GetQualifiedTypeName(); 102} 103 104size_t 105ValueObjectSynthetic::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 113lldb::ValueObjectSP 114ValueObjectSynthetic::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 123bool 124ValueObjectSynthetic::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 131uint64_t 132ValueObjectSynthetic::GetByteSize() 133{ 134 return m_parent->GetByteSize(); 135} 136 137lldb::ValueType 138ValueObjectSynthetic::GetValueType() const 139{ 140 return m_parent->GetValueType(); 141} 142 143void 144ValueObjectSynthetic::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 151bool 152ValueObjectSynthetic::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 194lldb::ValueObjectSP 195ValueObjectSynthetic::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 218lldb::ValueObjectSP 219ValueObjectSynthetic::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 231size_t 232ValueObjectSynthetic::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 252bool 253ValueObjectSynthetic::IsInScope () 254{ 255 return m_parent->IsInScope(); 256} 257 258lldb::ValueObjectSP 259ValueObjectSynthetic::GetNonSyntheticValue () 260{ 261 return m_parent->GetSP(); 262} 263 264void 265ValueObjectSynthetic::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