LLDB mainline
ValueObjectSynthetic.cpp
Go to the documentation of this file.
1//===-- ValueObjectSynthetic.cpp ------------------------------------===//
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"
16#include "lldb/Utility/Log.h"
17#include "lldb/Utility/Status.h"
19
20#include "llvm/ADT/STLExtras.h"
21#include <optional>
22
23namespace lldb_private {
24class Declaration;
25}
26
27using namespace lldb_private;
28
30public:
33
34 llvm::Expected<uint32_t> CalculateNumChildren() override {
35 return m_backend.GetNumChildren();
36 }
37
38 lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override {
39 return m_backend.GetChildAtIndex(idx);
40 }
41
42 llvm::Expected<size_t> GetIndexOfChildWithName(ConstString name) override {
43 return m_backend.GetIndexOfChildWithName(name);
44 }
45
46 bool MightHaveChildren() override { return m_backend.MightHaveChildren(); }
47
51};
52
55 : ValueObject(parent), m_synth_sp(std::move(filter)), m_children_byindex(),
61 SetName(parent.GetName());
62 // Copying the data of an incomplete type won't work as it has no byte size.
63 if (m_parent->GetCompilerType().IsCompleteType())
66}
67
69
73
75 return m_parent->GetTypeName();
76}
77
79 return m_parent->GetQualifiedTypeName();
80}
81
83 if (ConstString synth_name = m_synth_filter_up->GetSyntheticTypeName())
84 return synth_name;
85
86 return m_parent->GetDisplayTypeName();
87}
88
89llvm::Expected<uint32_t>
92
96
97 if (max < UINT32_MAX) {
98 auto num_children = m_synth_filter_up->CalculateNumChildren(max);
99 LLDB_LOGF(log,
100 "[ValueObjectSynthetic::CalculateNumChildren] for VO of name "
101 "%s and type %s, the filter returned %u child values",
102 GetName().AsCString(), GetTypeName().AsCString(),
103 num_children ? *num_children : 0);
104 return num_children;
105 } else {
106 auto num_children_or_err = m_synth_filter_up->CalculateNumChildren(max);
107 if (!num_children_or_err) {
109 return num_children_or_err;
110 }
111 auto num_children = (m_synthetic_children_count = *num_children_or_err);
112 LLDB_LOGF(log,
113 "[ValueObjectSynthetic::CalculateNumChildren] for VO of name "
114 "%s and type %s, the filter returned %u child values",
115 GetName().AsCString(), GetTypeName().AsCString(), num_children);
116 return num_children;
117 }
118}
119
122 if (!m_parent)
123 return lldb::ValueObjectSP();
124 if (IsDynamic() && GetDynamicValueType() == valueType)
125 return GetSP();
126 return m_parent->GetDynamicValue(valueType);
127}
128
135
136llvm::Expected<uint64_t> ValueObjectSynthetic::GetByteSize() {
137 return m_parent->GetByteSize();
138}
139
141 return m_parent->GetValueType();
142}
143
145 ValueObject *valobj_for_frontend = m_parent;
146 if (m_synth_sp->WantsDereference()) {
147 CompilerType type = m_parent->GetCompilerType();
148 if (type.IsValid() && type.IsPointerOrReferenceType()) {
150 lldb::ValueObjectSP deref_sp = m_parent->Dereference(error);
151 if (error.Success())
152 valobj_for_frontend = deref_sp.get();
153 }
154 }
155 m_synth_filter_up = (m_synth_sp->GetFrontEnd(*valobj_for_frontend));
157 m_synth_filter_up = std::make_unique<DummySyntheticFrontEnd>(*m_parent);
158}
159
162
163 SetValueIsValid(false);
164 m_error.Clear();
165
166 if (!m_parent->UpdateValueIfNeeded(false)) {
167 // our parent could not update.. as we are meaningless without a parent,
168 // just stop
169 if (m_parent->GetError().Fail())
170 m_error = m_parent->GetError().Clone();
171 return false;
172 }
173
174 // Regenerate the synthetic filter if our typename changes. When the (dynamic)
175 // type of an object changes, so does their synthetic filter of choice.
176 ConstString new_parent_type_name = m_parent->GetTypeName();
177 if (new_parent_type_name != m_parent_type_name) {
178 LLDB_LOGF(log,
179 "[ValueObjectSynthetic::UpdateValue] name=%s, type changed "
180 "from %s to %s, recomputing synthetic filter",
181 GetName().AsCString(), m_parent_type_name.AsCString(),
182 new_parent_type_name.AsCString());
183 m_parent_type_name = new_parent_type_name;
185 }
186
187 // let our backend do its update
189 LLDB_LOGF(log,
190 "[ValueObjectSynthetic::UpdateValue] name=%s, synthetic "
191 "filter said caches are stale - clearing",
192 GetName().AsCString());
193 // filter said that cached values are stale
194 {
195 std::lock_guard<std::mutex> guard(m_child_mutex);
196 m_children_byindex.clear();
197 m_name_toindex.clear();
198 }
199 // usually, an object's value can change but this does not alter its
200 // children count for a synthetic VO that might indeed happen, so we need
201 // to tell the upper echelons that they need to come back to us asking for
202 // children
203 m_flags.m_children_count_valid = false;
204 {
205 std::lock_guard<std::mutex> guard(m_child_mutex);
207 }
210 } else {
211 LLDB_LOGF(log,
212 "[ValueObjectSynthetic::UpdateValue] name=%s, synthetic "
213 "filter said caches are still valid",
214 GetName().AsCString());
215 }
216
218
219 lldb::ValueObjectSP synth_val(m_synth_filter_up->GetSyntheticValue());
220
221 if (synth_val && synth_val->CanProvideValue()) {
222 LLDB_LOGF(log,
223 "[ValueObjectSynthetic::UpdateValue] name=%s, synthetic "
224 "filter said it can provide a value",
225 GetName().AsCString());
226
228 CopyValueData(synth_val.get());
229 } else {
230 LLDB_LOGF(log,
231 "[ValueObjectSynthetic::UpdateValue] name=%s, synthetic "
232 "filter said it will not provide a value",
233 GetName().AsCString());
234
236 // Copying the data of an incomplete type won't work as it has no byte size.
237 if (m_parent->GetCompilerType().IsCompleteType())
239 }
240
241 SetValueIsValid(true);
242 return true;
243}
244
246 bool can_create) {
248
249 LLDB_LOGF(log,
250 "[ValueObjectSynthetic::GetChildAtIndex] name=%s, retrieving "
251 "child at index %u",
252 GetName().AsCString(), idx);
253
255
256 ValueObject *valobj;
257 bool child_is_cached;
258 {
259 std::lock_guard<std::mutex> guard(m_child_mutex);
260 auto cached_child_it = m_children_byindex.find(idx);
261 child_is_cached = cached_child_it != m_children_byindex.end();
262 if (child_is_cached)
263 valobj = cached_child_it->second;
264 }
265
266 if (!child_is_cached) {
267 if (can_create && m_synth_filter_up != nullptr) {
268 LLDB_LOGF(log,
269 "[ValueObjectSynthetic::GetChildAtIndex] name=%s, child at "
270 "index %u not cached and will be created",
271 GetName().AsCString(), idx);
272
273 lldb::ValueObjectSP synth_guy = m_synth_filter_up->GetChildAtIndex(idx);
274
275 LLDB_LOGF(
276 log,
277 "[ValueObjectSynthetic::GetChildAtIndex] name=%s, child at index "
278 "%u created as %p (is "
279 "synthetic: %s)",
280 GetName().AsCString(), idx, static_cast<void *>(synth_guy.get()),
281 synth_guy.get()
282 ? (synth_guy->IsSyntheticChildrenGenerated() ? "yes" : "no")
283 : "no");
284
285 if (!synth_guy)
286 return synth_guy;
287
288 {
289 std::lock_guard<std::mutex> guard(m_child_mutex);
290 if (synth_guy->IsSyntheticChildrenGenerated())
291 m_synthetic_children_cache.push_back(synth_guy);
292 m_children_byindex[idx] = synth_guy.get();
293 }
294 synth_guy->SetPreferredDisplayLanguageIfNeeded(
296 return synth_guy;
297 } else {
298 LLDB_LOGF(log,
299 "[ValueObjectSynthetic::GetChildAtIndex] name=%s, child at "
300 "index %u not cached and cannot "
301 "be created (can_create = %s, synth_filter = %p)",
302 GetName().AsCString(), idx, can_create ? "yes" : "no",
303 static_cast<void *>(m_synth_filter_up.get()));
304
305 return lldb::ValueObjectSP();
306 }
307 } else {
308 LLDB_LOGF(log,
309 "[ValueObjectSynthetic::GetChildAtIndex] name=%s, child at "
310 "index %u cached as %p",
311 GetName().AsCString(), idx, static_cast<void *>(valobj));
312
313 return valobj->GetSP();
314 }
315}
316
319 bool can_create) {
321
322 auto index_or_err = GetIndexOfChildWithName(name);
323
324 if (!index_or_err) {
325 llvm::consumeError(index_or_err.takeError());
326 return lldb::ValueObjectSP();
327 }
328
329 return GetChildAtIndex(*index_or_err, can_create);
330}
331
332llvm::Expected<size_t>
335
336 ConstString name(name_ref);
337
338 std::optional<uint32_t> found_index = std::nullopt;
339 {
340 std::lock_guard<std::mutex> guard(m_child_mutex);
341 auto name_to_index = m_name_toindex.find(name.GetCString());
342 if (name_to_index != m_name_toindex.end())
343 found_index = name_to_index->second;
344 }
345
346 if (!found_index && m_synth_filter_up != nullptr) {
347 auto index_or_err = m_synth_filter_up->GetIndexOfChildWithName(name);
348 if (!index_or_err)
349 return index_or_err.takeError();
350 std::lock_guard<std::mutex> guard(m_child_mutex);
351 m_name_toindex[name.GetCString()] = *index_or_err;
352 return *index_or_err;
353 } else if (!found_index && m_synth_filter_up == nullptr) {
354 return llvm::createStringError("Type has no child named '%s'",
355 name.AsCString());
356 } else if (found_index)
357 return *found_index;
358
359 return llvm::createStringError("Type has no child named '%s'",
360 name.AsCString());
361}
362
363bool ValueObjectSynthetic::IsInScope() { return m_parent->IsInScope(); }
364
368
370 if (!source->UpdateValueIfNeeded())
371 return;
372 m_value = source->GetValue();
374 m_error = m_value.GetValueAsData(&exe_ctx, m_data, GetModule().get());
375}
376
378 if (!UpdateValueIfNeeded())
379 return false;
381 return true;
382 return m_parent->CanProvideValue();
383}
384
386 Status &error) {
387 return m_parent->SetValueFromCString(value_str, error);
388}
389
391 if (m_parent) {
392 m_parent->ClearUserVisibleData(eClearUserVisibleDataItemsAll);
393 m_parent->SetFormat(format);
394 }
395 this->ValueObject::SetFormat(format);
397}
398
400 lldb::LanguageType lang) {
402 if (m_parent)
403 m_parent->SetPreferredDisplayLanguage(lang);
404}
405
414
416 if (m_parent)
417 return m_parent->IsSyntheticChildrenGenerated();
418 return false;
419}
420
422 if (m_parent)
423 m_parent->SetSyntheticChildrenGenerated(b);
425}
426
428 if (m_parent)
429 return m_parent->GetDeclaration(decl);
430
431 return ValueObject::GetDeclaration(decl);
432}
433
435 if (m_parent)
436 return m_parent->GetLanguageFlags();
437 return this->ValueObject::GetLanguageFlags();
438}
439
441 if (m_parent)
442 m_parent->SetLanguageFlags(flags);
443 else
445}
static llvm::raw_ostream & error(Stream &strm)
#define LLDB_LOGF(log,...)
Definition Log.h:376
llvm::Expected< uint32_t > CalculateNumChildren() override
llvm::Expected< size_t > GetIndexOfChildWithName(ConstString name) override
lldb::ChildCacheState Update() override
This function is assumed to always succeed and if it fails, the front-end should know to deal with it...
lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override
DummySyntheticFrontEnd(ValueObject &backend)
Generic representation of a type in a programming language.
bool IsPointerOrReferenceType(CompilerType *pointee_type=nullptr) const
A uniqued constant string class.
Definition ConstString.h:40
const char * AsCString(const char *value_if_empty=nullptr) const
Get the string value as a C string.
const char * GetCString() const
Get the string value as a C string.
A class that describes the declaration location of a lldb object.
Definition Declaration.h:24
"lldb/Target/ExecutionContext.h" A class that contains an execution context.
An error handling class.
Definition Status.h:118
SyntheticChildrenFrontEnd(ValueObject &backend)
virtual lldb::DynamicValueType GetDynamicValueType()
lldb::ValueObjectSP GetChildAtIndex(uint32_t idx, bool can_create=true) override
bool SetValueFromCString(const char *value_str, Status &error) override
lldb::ValueType GetValueType() const override
lldb::LanguageType GetPreferredDisplayLanguage() override
void SetFormat(lldb::Format format) override
NameToIndexMap m_name_toindex
Guarded by m_child_mutex;.
ByIndexMap m_children_byindex
Guarded by m_child_mutex;.
std::unique_ptr< SyntheticChildrenFrontEnd > m_synth_filter_up
lldb::ValueObjectSP GetDynamicValue(lldb::DynamicValueType valueType) override
void SetSyntheticChildrenGenerated(bool b) override
void SetPreferredDisplayLanguage(lldb::LanguageType)
lldb::ValueObjectSP GetNonSyntheticValue() override
SyntheticChildrenCache m_synthetic_children_cache
Guarded by m_child_mutex;.
llvm::Expected< size_t > GetIndexOfChildWithName(llvm::StringRef name) override
bool GetDeclaration(Declaration &decl) override
bool MightHaveChildren() override
Find out if a ValueObject might have children.
lldb::ValueObjectSP GetChildMemberWithName(llvm::StringRef name, bool can_create=true) override
llvm::Expected< uint64_t > GetByteSize() override
ValueObjectSynthetic(ValueObject &parent, lldb::SyntheticChildrenSP filter)
void SetLanguageFlags(uint64_t flags) override
llvm::Expected< uint32_t > CalculateNumChildren(uint32_t max) override
Should only be called by ValueObject::GetNumChildren().
void SetValueIsValid(bool valid)
void ClearUserVisibleData(uint32_t items=ValueObject::eClearUserVisibleDataItemsAllStrings)
void SetPreferredDisplayLanguage(lldb::LanguageType lt)
struct lldb_private::ValueObject::Bitflags m_flags
lldb::ValueObjectSP GetSP()
virtual void SetLanguageFlags(uint64_t flags)
Status m_error
An error object that can describe any errors that occur when updating values.
virtual uint64_t GetLanguageFlags()
virtual void SetSyntheticChildrenGenerated(bool b)
DataExtractor m_data
A data extractor that can be used to extract the value.
virtual lldb::ModuleSP GetModule()
Return the module associated with this value object in case the value is from an executable file and ...
lldb::LanguageType m_preferred_display_language
ValueObject * m_parent
The parent value object, or nullptr if this has no parent.
virtual bool GetDeclaration(Declaration &decl)
bool UpdateValueIfNeeded(bool update_format=true)
void SetName(ConstString name)
Change the name of the current ValueObject.
ConstString GetName() const
virtual void SetFormat(lldb::Format format)
const ExecutionContextRef & GetExecutionContextRef() const
const Value & GetValue() const
#define UINT32_MAX
A class that represents a running process on the host machine.
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
Definition Log.h:332
ChildCacheState
Specifies if children need to be re-computed after a call to SyntheticChildrenFrontEnd::Update.
@ eRefetch
Children need to be recomputed dynamically.
std::shared_ptr< lldb_private::ValueObject > ValueObjectSP
Format
Display format definitions.
LanguageType
Programming language type.
@ eLanguageTypeUnknown
Unknown or invalid language value.
std::shared_ptr< lldb_private::SyntheticChildren > SyntheticChildrenSP