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: 26 DummySyntheticFrontEnd(ValueObject &backend) : 27 SyntheticChildrenFrontEnd(backend) 28 {} 29 30 size_t 31 CalculateNumChildren() 32 { 33 return 0; 34 } 35 36 lldb::ValueObjectSP 37 GetChildAtIndex (size_t idx) 38 { 39 return lldb::ValueObjectSP(); 40 } 41 42 size_t 43 GetIndexOfChildWithName (const ConstString &name) 44 { 45 return UINT32_MAX; 46 } 47 48 bool 49 MightHaveChildren () 50 { 51 return true; 52 } 53 54 bool 55 Update() 56 { 57 return false; 58 } 59 60 }; 61 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 82 ValueObjectSynthetic::~ValueObjectSynthetic() 83 { 84 } 85 86 ClangASTType 87 ValueObjectSynthetic::GetClangTypeImpl () 88 { 89 return m_parent->GetClangType(); 90 } 91 92 ConstString 93 ValueObjectSynthetic::GetTypeName() 94 { 95 return m_parent->GetTypeName(); 96 } 97 98 ConstString 99 ValueObjectSynthetic::GetQualifiedTypeName() 100 { 101 return m_parent->GetQualifiedTypeName(); 102 } 103 104 size_t 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 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 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 132 ValueObjectSynthetic::GetByteSize() 133 { 134 return m_parent->GetByteSize(); 135 } 136 137 lldb::ValueType 138 ValueObjectSynthetic::GetValueType() const 139 { 140 return m_parent->GetValueType(); 141 } 142 143 void 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 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 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 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 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 253 ValueObjectSynthetic::IsInScope () 254 { 255 return m_parent->IsInScope(); 256 } 257 258 lldb::ValueObjectSP 259 ValueObjectSynthetic::GetNonSyntheticValue () 260 { 261 return m_parent->GetSP(); 262 } 263 264 void 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