LLDB  mainline
ValueObjectSyntheticFilter.cpp
Go to the documentation of this file.
1 //===-- ValueObjectSyntheticFilter.cpp --------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
10 
11 #include "lldb/Core/Value.h"
12 #include "lldb/Core/ValueObject.h"
15 #include "lldb/Utility/Log.h"
16 #include "lldb/Utility/Logging.h"
18 #include "lldb/Utility/Status.h"
19 
20 #include "llvm/ADT/STLExtras.h"
21 
22 namespace lldb_private {
23 class Declaration;
24 }
25 
26 using namespace lldb_private;
27 
29 public:
31  : SyntheticChildrenFrontEnd(backend) {}
32 
33  size_t CalculateNumChildren() override { return m_backend.GetNumChildren(); }
34 
35  lldb::ValueObjectSP GetChildAtIndex(size_t idx) override {
36  return m_backend.GetChildAtIndex(idx, true);
37  }
38 
39  size_t GetIndexOfChildWithName(ConstString name) override {
40  return m_backend.GetIndexOfChildWithName(name);
41  }
42 
43  bool MightHaveChildren() override { return true; }
44 
45  bool Update() override { return false; }
46 };
47 
48 ValueObjectSynthetic::ValueObjectSynthetic(ValueObject &parent,
49  lldb::SyntheticChildrenSP filter)
50  : ValueObject(parent), m_synth_sp(filter), m_children_byindex(),
51  m_name_toindex(), m_synthetic_children_count(UINT32_MAX),
52  m_synthetic_children_cache(), m_parent_type_name(parent.GetTypeName()),
53  m_might_have_children(eLazyBoolCalculate),
54  m_provides_value(eLazyBoolCalculate) {
55  SetName(parent.GetName());
56  CopyValueData(m_parent);
57  CreateSynthFilter();
58 }
59 
61 
63  return m_parent->GetCompilerType();
64 }
65 
67  return m_parent->GetTypeName();
68 }
69 
71  return m_parent->GetQualifiedTypeName();
72 }
73 
75  if (ConstString synth_name = m_synth_filter_up->GetSyntheticTypeName())
76  return synth_name;
77 
78  return m_parent->GetDisplayTypeName();
79 }
80 
83 
84  UpdateValueIfNeeded();
85  if (m_synthetic_children_count < UINT32_MAX)
86  return m_synthetic_children_count <= max ? m_synthetic_children_count : max;
87 
88  if (max < UINT32_MAX) {
89  size_t num_children = m_synth_filter_up->CalculateNumChildren(max);
90  if (log)
91  log->Printf("[ValueObjectSynthetic::CalculateNumChildren] for VO of name "
92  "%s and type %s, the filter returned %zu child values",
93  GetName().AsCString(), GetTypeName().AsCString(),
94  num_children);
95  return num_children;
96  } else {
97  size_t num_children = (m_synthetic_children_count =
98  m_synth_filter_up->CalculateNumChildren(max));
99  if (log)
100  log->Printf("[ValueObjectSynthetic::CalculateNumChildren] for VO of name "
101  "%s and type %s, the filter returned %zu child values",
102  GetName().AsCString(), GetTypeName().AsCString(),
103  num_children);
104  return num_children;
105  }
106 }
107 
108 lldb::ValueObjectSP
110  if (!m_parent)
111  return lldb::ValueObjectSP();
112  if (IsDynamic() && GetDynamicValueType() == valueType)
113  return GetSP();
114  return m_parent->GetDynamicValue(valueType);
115 }
116 
118  if (m_might_have_children == eLazyBoolCalculate)
119  m_might_have_children =
120  (m_synth_filter_up->MightHaveChildren() ? eLazyBoolYes : eLazyBoolNo);
121  return (m_might_have_children != eLazyBoolNo);
122 }
123 
124 uint64_t ValueObjectSynthetic::GetByteSize() { return m_parent->GetByteSize(); }
125 
127  return m_parent->GetValueType();
128 }
129 
131  ValueObject *valobj_for_frontend = m_parent;
132  if (m_synth_sp->WantsDereference())
133  {
134  CompilerType type = m_parent->GetCompilerType();
135  if (type.IsValid() && type.IsPointerOrReferenceType())
136  {
137  Status error;
138  lldb::ValueObjectSP deref_sp = m_parent->Dereference(error);
139  if (error.Success())
140  valobj_for_frontend = deref_sp.get();
141  }
142  }
143  m_synth_filter_up = (m_synth_sp->GetFrontEnd(*valobj_for_frontend));
144  if (!m_synth_filter_up)
145  m_synth_filter_up = llvm::make_unique<DummySyntheticFrontEnd>(*m_parent);
146 }
147 
150 
151  SetValueIsValid(false);
152  m_error.Clear();
153 
154  if (!m_parent->UpdateValueIfNeeded(false)) {
155  // our parent could not update.. as we are meaningless without a parent,
156  // just stop
157  if (m_parent->GetError().Fail())
158  m_error = m_parent->GetError();
159  return false;
160  }
161 
162  // regenerate the synthetic filter if our typename changes
163  // <rdar://problem/12424824>
164  ConstString new_parent_type_name = m_parent->GetTypeName();
165  if (new_parent_type_name != m_parent_type_name) {
166  if (log)
167  log->Printf("[ValueObjectSynthetic::UpdateValue] name=%s, type changed "
168  "from %s to %s, recomputing synthetic filter",
169  GetName().AsCString(), m_parent_type_name.AsCString(),
170  new_parent_type_name.AsCString());
171  m_parent_type_name = new_parent_type_name;
172  CreateSynthFilter();
173  }
174 
175  // let our backend do its update
176  if (!m_synth_filter_up->Update()) {
177  if (log)
178  log->Printf("[ValueObjectSynthetic::UpdateValue] name=%s, synthetic "
179  "filter said caches are stale - clearing",
180  GetName().AsCString());
181  // filter said that cached values are stale
182  m_children_byindex.Clear();
183  m_name_toindex.Clear();
184  // usually, an object's value can change but this does not alter its
185  // children count for a synthetic VO that might indeed happen, so we need
186  // to tell the upper echelons that they need to come back to us asking for
187  // children
188  m_children_count_valid = false;
189  m_synthetic_children_cache.Clear();
190  m_synthetic_children_count = UINT32_MAX;
191  m_might_have_children = eLazyBoolCalculate;
192  } else {
193  if (log)
194  log->Printf("[ValueObjectSynthetic::UpdateValue] name=%s, synthetic "
195  "filter said caches are still valid",
196  GetName().AsCString());
197  }
198 
199  m_provides_value = eLazyBoolCalculate;
200 
201  lldb::ValueObjectSP synth_val(m_synth_filter_up->GetSyntheticValue());
202 
203  if (synth_val && synth_val->CanProvideValue()) {
204  if (log)
205  log->Printf("[ValueObjectSynthetic::UpdateValue] name=%s, synthetic "
206  "filter said it can provide a value",
207  GetName().AsCString());
208 
209  m_provides_value = eLazyBoolYes;
210  CopyValueData(synth_val.get());
211  } else {
212  if (log)
213  log->Printf("[ValueObjectSynthetic::UpdateValue] name=%s, synthetic "
214  "filter said it will not provide a value",
215  GetName().AsCString());
216 
217  m_provides_value = eLazyBoolNo;
218  CopyValueData(m_parent);
219  }
220 
221  SetValueIsValid(true);
222  return true;
223 }
224 
225 lldb::ValueObjectSP ValueObjectSynthetic::GetChildAtIndex(size_t idx,
226  bool can_create) {
228 
229  if (log)
230  log->Printf("[ValueObjectSynthetic::GetChildAtIndex] name=%s, retrieving "
231  "child at index %zu",
232  GetName().AsCString(), idx);
233 
234  UpdateValueIfNeeded();
235 
236  ValueObject *valobj;
237  if (!m_children_byindex.GetValueForKey(idx, valobj)) {
238  if (can_create && m_synth_filter_up != nullptr) {
239  if (log)
240  log->Printf("[ValueObjectSynthetic::GetChildAtIndex] name=%s, child at "
241  "index %zu not cached and will be created",
242  GetName().AsCString(), idx);
243 
244  lldb::ValueObjectSP synth_guy = m_synth_filter_up->GetChildAtIndex(idx);
245 
246  if (log)
247  log->Printf(
248  "[ValueObjectSynthetic::GetChildAtIndex] name=%s, child at index "
249  "%zu created as %p (is "
250  "synthetic: %s)",
251  GetName().AsCString(), idx, static_cast<void *>(synth_guy.get()),
252  synth_guy.get()
253  ? (synth_guy->IsSyntheticChildrenGenerated() ? "yes" : "no")
254  : "no");
255 
256  if (!synth_guy)
257  return synth_guy;
258 
259  if (synth_guy->IsSyntheticChildrenGenerated())
260  m_synthetic_children_cache.AppendObject(synth_guy);
261  m_children_byindex.SetValueForKey(idx, synth_guy.get());
262  synth_guy->SetPreferredDisplayLanguageIfNeeded(
263  GetPreferredDisplayLanguage());
264  return synth_guy;
265  } else {
266  if (log)
267  log->Printf("[ValueObjectSynthetic::GetChildAtIndex] name=%s, child at "
268  "index %zu not cached and cannot "
269  "be created (can_create = %s, synth_filter = %p)",
270  GetName().AsCString(), idx, can_create ? "yes" : "no",
271  static_cast<void *>(m_synth_filter_up.get()));
272 
273  return lldb::ValueObjectSP();
274  }
275  } else {
276  if (log)
277  log->Printf("[ValueObjectSynthetic::GetChildAtIndex] name=%s, child at "
278  "index %zu cached as %p",
279  GetName().AsCString(), idx, static_cast<void *>(valobj));
280 
281  return valobj->GetSP();
282  }
283 }
284 
285 lldb::ValueObjectSP
287  bool can_create) {
288  UpdateValueIfNeeded();
289 
290  uint32_t index = GetIndexOfChildWithName(name);
291 
292  if (index == UINT32_MAX)
293  return lldb::ValueObjectSP();
294 
295  return GetChildAtIndex(index, can_create);
296 }
297 
299  UpdateValueIfNeeded();
300 
301  uint32_t found_index = UINT32_MAX;
302  bool did_find = m_name_toindex.GetValueForKey(name.GetCString(), found_index);
303 
304  if (!did_find && m_synth_filter_up != nullptr) {
305  uint32_t index = m_synth_filter_up->GetIndexOfChildWithName(name);
306  if (index == UINT32_MAX)
307  return index;
308  m_name_toindex.SetValueForKey(name.GetCString(), index);
309  return index;
310  } else if (!did_find && m_synth_filter_up == nullptr)
311  return UINT32_MAX;
312  else /*if (iter != m_name_toindex.end())*/
313  return found_index;
314 }
315 
316 bool ValueObjectSynthetic::IsInScope() { return m_parent->IsInScope(); }
317 
319  return m_parent->GetSP();
320 }
321 
322 void ValueObjectSynthetic::CopyValueData(ValueObject *source) {
323  m_value = (source->UpdateValueIfNeeded(), source->GetValue());
324  ExecutionContext exe_ctx(GetExecutionContextRef());
325  m_error = m_value.GetValueAsData(&exe_ctx, m_data, 0, GetModule().get());
326 }
327 
329  if (!UpdateValueIfNeeded())
330  return false;
331  if (m_provides_value == eLazyBoolYes)
332  return true;
333  return m_parent->CanProvideValue();
334 }
335 
336 bool ValueObjectSynthetic::SetValueFromCString(const char *value_str,
337  Status &error) {
338  return m_parent->SetValueFromCString(value_str, error);
339 }
340 
342  if (m_parent) {
343  m_parent->ClearUserVisibleData(eClearUserVisibleDataItemsAll);
344  m_parent->SetFormat(format);
345  }
346  this->ValueObject::SetFormat(format);
347  this->ClearUserVisibleData(eClearUserVisibleDataItemsAll);
348 }
349 
351  lldb::LanguageType lang) {
353  if (m_parent)
354  m_parent->SetPreferredDisplayLanguage(lang);
355 }
356 
358  if (m_preferred_display_language == lldb::eLanguageTypeUnknown) {
359  if (m_parent)
360  return m_parent->GetPreferredDisplayLanguage();
362  } else
363  return m_preferred_display_language;
364 }
365 
367  if (m_parent)
368  return m_parent->IsSyntheticChildrenGenerated();
369  return false;
370 }
371 
373  if (m_parent)
374  m_parent->SetSyntheticChildrenGenerated(b);
376 }
377 
379  if (m_parent)
380  return m_parent->GetDeclaration(decl);
381 
382  return ValueObject::GetDeclaration(decl);
383 }
384 
386  if (m_parent)
387  return m_parent->GetLanguageFlags();
388  return this->ValueObject::GetLanguageFlags();
389 }
390 
392  if (m_parent)
393  m_parent->SetLanguageFlags(flags);
394  else
395  this->ValueObject::SetLanguageFlags(flags);
396 }
#define LIBLLDB_LOG_DATAFORMATTERS
Definition: Logging.h:43
Enumerations for broadcasting.
Definition: SBLaunchInfo.h:14
bool IsPointerOrReferenceType(CompilerType *pointee_type=nullptr) const
const char * AsCString(const char *value_if_empty=nullptr) const
Get the string value as a C string.
Definition: ConstString.h:224
bool SetValueFromCString(const char *value_str, Status &error) override
virtual ConstString GetTypeName()
void SetFormat(lldb::Format format) override
ConstString GetName() const
void SetPreferredDisplayLanguage(lldb::LanguageType)
virtual uint64_t GetLanguageFlags()
"lldb/Target/ExecutionContext.h" A class that contains an execution context.
lldb::ValueObjectSP GetChildMemberWithName(ConstString name, bool can_create) override
lldb::LanguageType GetPreferredDisplayLanguage() override
#define UINT32_MAX
Definition: lldb-defines.h:31
LanguageType
Programming language type.
virtual void SetFormat(lldb::Format format)
Definition: ValueObject.h:715
Log * GetLogIfAllCategoriesSet(uint32_t mask)
Definition: Logging.cpp:57
lldb::ValueObjectSP GetChildAtIndex(size_t idx) override
size_t GetIndexOfChildWithName(ConstString name) override
bool Success() const
Test for success condition.
Definition: Status.cpp:287
bool GetDeclaration(Declaration &decl) override
bool UpdateValueIfNeeded(bool update_format=true)
lldb::ValueObjectSP GetChildAtIndex(size_t idx, bool can_create) override
A uniqued constant string class.
Definition: ConstString.h:38
Unknown or invalid language value.
virtual bool GetDeclaration(Declaration &decl)
const char * GetCString() const
Get the string value as a C string.
Definition: ConstString.h:247
lldb::ValueObjectSP GetNonSyntheticValue() override
lldb::ValueObjectSP GetSP()
Definition: ValueObject.h:565
lldb::ValueObjectSP GetDynamicValue(lldb::DynamicValueType valueType) override
size_t CalculateNumChildren(uint32_t max) override
const Value & GetValue() const
virtual void SetLanguageFlags(uint64_t flags)
DummySyntheticFrontEnd(ValueObject &backend)
virtual void SetSyntheticChildrenGenerated(bool b)
A class that describes the declaration location of a lldb object.
Definition: Declaration.h:24
void Printf(const char *format,...) __attribute__((format(printf
Definition: Log.cpp:113
bool MightHaveChildren() override
Find out if a ValueObject might have children.
size_t GetIndexOfChildWithName(ConstString name) override
void SetLanguageFlags(uint64_t flags) override
lldb::ValueType GetValueType() const override
An error handling class.
Definition: Status.h:44