[NFC][Coroutines] Use structured binding with llvm::enumerate in CoroSplit (#116879)
[llvm-project.git] / lldb / source / ValueObject / ValueObjectSyntheticFilter.cpp
blobfbb329b0896ded1547c518e3736483b1c9176629
1 //===-- ValueObjectSyntheticFilter.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 //===----------------------------------------------------------------------===//
9 #include "lldb/ValueObject/ValueObjectSyntheticFilter.h"
11 #include "lldb/Core/Value.h"
12 #include "lldb/DataFormatters/TypeSynthetic.h"
13 #include "lldb/Target/ExecutionContext.h"
14 #include "lldb/Utility/ConstString.h"
15 #include "lldb/Utility/LLDBLog.h"
16 #include "lldb/Utility/Log.h"
17 #include "lldb/Utility/Status.h"
18 #include "lldb/ValueObject/ValueObject.h"
20 #include "llvm/ADT/STLExtras.h"
21 #include <optional>
23 namespace lldb_private {
24 class Declaration;
27 using namespace lldb_private;
29 class DummySyntheticFrontEnd : public SyntheticChildrenFrontEnd {
30 public:
31 DummySyntheticFrontEnd(ValueObject &backend)
32 : SyntheticChildrenFrontEnd(backend) {}
34 llvm::Expected<uint32_t> CalculateNumChildren() override {
35 return m_backend.GetNumChildren();
38 lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override {
39 return m_backend.GetChildAtIndex(idx);
42 size_t GetIndexOfChildWithName(ConstString name) override {
43 return m_backend.GetIndexOfChildWithName(name);
46 bool MightHaveChildren() override { return m_backend.MightHaveChildren(); }
48 lldb::ChildCacheState Update() override {
49 return lldb::ChildCacheState::eRefetch;
53 ValueObjectSynthetic::ValueObjectSynthetic(ValueObject &parent,
54 lldb::SyntheticChildrenSP filter)
55 : ValueObject(parent), m_synth_sp(std::move(filter)), m_children_byindex(),
56 m_name_toindex(), m_synthetic_children_cache(),
57 m_synthetic_children_count(UINT32_MAX),
58 m_parent_type_name(parent.GetTypeName()),
59 m_might_have_children(eLazyBoolCalculate),
60 m_provides_value(eLazyBoolCalculate) {
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())
64 CopyValueData(m_parent);
65 CreateSynthFilter();
68 ValueObjectSynthetic::~ValueObjectSynthetic() = default;
70 CompilerType ValueObjectSynthetic::GetCompilerTypeImpl() {
71 return m_parent->GetCompilerType();
74 ConstString ValueObjectSynthetic::GetTypeName() {
75 return m_parent->GetTypeName();
78 ConstString ValueObjectSynthetic::GetQualifiedTypeName() {
79 return m_parent->GetQualifiedTypeName();
82 ConstString ValueObjectSynthetic::GetDisplayTypeName() {
83 if (ConstString synth_name = m_synth_filter_up->GetSyntheticTypeName())
84 return synth_name;
86 return m_parent->GetDisplayTypeName();
89 llvm::Expected<uint32_t>
90 ValueObjectSynthetic::CalculateNumChildren(uint32_t max) {
91 Log *log = GetLog(LLDBLog::DataFormatters);
93 UpdateValueIfNeeded();
94 if (m_synthetic_children_count < UINT32_MAX)
95 return m_synthetic_children_count <= max ? m_synthetic_children_count : max;
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) {
108 m_synthetic_children_count = 0;
109 return num_children_or_err;
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;
120 lldb::ValueObjectSP
121 ValueObjectSynthetic::GetDynamicValue(lldb::DynamicValueType valueType) {
122 if (!m_parent)
123 return lldb::ValueObjectSP();
124 if (IsDynamic() && GetDynamicValueType() == valueType)
125 return GetSP();
126 return m_parent->GetDynamicValue(valueType);
129 bool ValueObjectSynthetic::MightHaveChildren() {
130 if (m_might_have_children == eLazyBoolCalculate)
131 m_might_have_children =
132 (m_synth_filter_up->MightHaveChildren() ? eLazyBoolYes : eLazyBoolNo);
133 return (m_might_have_children != eLazyBoolNo);
136 std::optional<uint64_t> ValueObjectSynthetic::GetByteSize() {
137 return m_parent->GetByteSize();
140 lldb::ValueType ValueObjectSynthetic::GetValueType() const {
141 return m_parent->GetValueType();
144 void ValueObjectSynthetic::CreateSynthFilter() {
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()) {
149 Status error;
150 lldb::ValueObjectSP deref_sp = m_parent->Dereference(error);
151 if (error.Success())
152 valobj_for_frontend = deref_sp.get();
155 m_synth_filter_up = (m_synth_sp->GetFrontEnd(*valobj_for_frontend));
156 if (!m_synth_filter_up)
157 m_synth_filter_up = std::make_unique<DummySyntheticFrontEnd>(*m_parent);
160 bool ValueObjectSynthetic::UpdateValue() {
161 Log *log = GetLog(LLDBLog::DataFormatters);
163 SetValueIsValid(false);
164 m_error.Clear();
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;
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;
184 CreateSynthFilter();
187 // let our backend do its update
188 if (m_synth_filter_up->Update() == lldb::ChildCacheState::eRefetch) {
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
195 std::lock_guard<std::mutex> guard(m_child_mutex);
196 m_children_byindex.clear();
197 m_name_toindex.clear();
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;
205 std::lock_guard<std::mutex> guard(m_child_mutex);
206 m_synthetic_children_cache.clear();
208 m_synthetic_children_count = UINT32_MAX;
209 m_might_have_children = eLazyBoolCalculate;
210 } else {
211 LLDB_LOGF(log,
212 "[ValueObjectSynthetic::UpdateValue] name=%s, synthetic "
213 "filter said caches are still valid",
214 GetName().AsCString());
217 m_provides_value = eLazyBoolCalculate;
219 lldb::ValueObjectSP synth_val(m_synth_filter_up->GetSyntheticValue());
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());
227 m_provides_value = eLazyBoolYes;
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());
235 m_provides_value = eLazyBoolNo;
236 // Copying the data of an incomplete type won't work as it has no byte size.
237 if (m_parent->GetCompilerType().IsCompleteType())
238 CopyValueData(m_parent);
241 SetValueIsValid(true);
242 return true;
245 lldb::ValueObjectSP ValueObjectSynthetic::GetChildAtIndex(uint32_t idx,
246 bool can_create) {
247 Log *log = GetLog(LLDBLog::DataFormatters);
249 LLDB_LOGF(log,
250 "[ValueObjectSynthetic::GetChildAtIndex] name=%s, retrieving "
251 "child at index %u",
252 GetName().AsCString(), idx);
254 UpdateValueIfNeeded();
256 ValueObject *valobj;
257 bool child_is_cached;
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;
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);
273 lldb::ValueObjectSP synth_guy = m_synth_filter_up->GetChildAtIndex(idx);
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");
285 if (!synth_guy)
286 return synth_guy;
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();
294 synth_guy->SetPreferredDisplayLanguageIfNeeded(
295 GetPreferredDisplayLanguage());
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()));
305 return lldb::ValueObjectSP();
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));
313 return valobj->GetSP();
317 lldb::ValueObjectSP
318 ValueObjectSynthetic::GetChildMemberWithName(llvm::StringRef name,
319 bool can_create) {
320 UpdateValueIfNeeded();
322 uint32_t index = GetIndexOfChildWithName(name);
324 if (index == UINT32_MAX)
325 return lldb::ValueObjectSP();
327 return GetChildAtIndex(index, can_create);
330 size_t ValueObjectSynthetic::GetIndexOfChildWithName(llvm::StringRef name_ref) {
331 UpdateValueIfNeeded();
333 ConstString name(name_ref);
335 uint32_t found_index = UINT32_MAX;
336 bool did_find;
338 std::lock_guard<std::mutex> guard(m_child_mutex);
339 auto name_to_index = m_name_toindex.find(name.GetCString());
340 did_find = name_to_index != m_name_toindex.end();
341 if (did_find)
342 found_index = name_to_index->second;
345 if (!did_find && m_synth_filter_up != nullptr) {
346 uint32_t index = m_synth_filter_up->GetIndexOfChildWithName(name);
347 if (index == UINT32_MAX)
348 return index;
349 std::lock_guard<std::mutex> guard(m_child_mutex);
350 m_name_toindex[name.GetCString()] = index;
351 return index;
352 } else if (!did_find && m_synth_filter_up == nullptr)
353 return UINT32_MAX;
354 else /*if (iter != m_name_toindex.end())*/
355 return found_index;
358 bool ValueObjectSynthetic::IsInScope() { return m_parent->IsInScope(); }
360 lldb::ValueObjectSP ValueObjectSynthetic::GetNonSyntheticValue() {
361 return m_parent->GetSP();
364 void ValueObjectSynthetic::CopyValueData(ValueObject *source) {
365 m_value = (source->UpdateValueIfNeeded(), source->GetValue());
366 ExecutionContext exe_ctx(GetExecutionContextRef());
367 m_error = m_value.GetValueAsData(&exe_ctx, m_data, GetModule().get());
370 bool ValueObjectSynthetic::CanProvideValue() {
371 if (!UpdateValueIfNeeded())
372 return false;
373 if (m_provides_value == eLazyBoolYes)
374 return true;
375 return m_parent->CanProvideValue();
378 bool ValueObjectSynthetic::SetValueFromCString(const char *value_str,
379 Status &error) {
380 return m_parent->SetValueFromCString(value_str, error);
383 void ValueObjectSynthetic::SetFormat(lldb::Format format) {
384 if (m_parent) {
385 m_parent->ClearUserVisibleData(eClearUserVisibleDataItemsAll);
386 m_parent->SetFormat(format);
388 this->ValueObject::SetFormat(format);
389 this->ClearUserVisibleData(eClearUserVisibleDataItemsAll);
392 void ValueObjectSynthetic::SetPreferredDisplayLanguage(
393 lldb::LanguageType lang) {
394 this->ValueObject::SetPreferredDisplayLanguage(lang);
395 if (m_parent)
396 m_parent->SetPreferredDisplayLanguage(lang);
399 lldb::LanguageType ValueObjectSynthetic::GetPreferredDisplayLanguage() {
400 if (m_preferred_display_language == lldb::eLanguageTypeUnknown) {
401 if (m_parent)
402 return m_parent->GetPreferredDisplayLanguage();
403 return lldb::eLanguageTypeUnknown;
404 } else
405 return m_preferred_display_language;
408 bool ValueObjectSynthetic::IsSyntheticChildrenGenerated() {
409 if (m_parent)
410 return m_parent->IsSyntheticChildrenGenerated();
411 return false;
414 void ValueObjectSynthetic::SetSyntheticChildrenGenerated(bool b) {
415 if (m_parent)
416 m_parent->SetSyntheticChildrenGenerated(b);
417 this->ValueObject::SetSyntheticChildrenGenerated(b);
420 bool ValueObjectSynthetic::GetDeclaration(Declaration &decl) {
421 if (m_parent)
422 return m_parent->GetDeclaration(decl);
424 return ValueObject::GetDeclaration(decl);
427 uint64_t ValueObjectSynthetic::GetLanguageFlags() {
428 if (m_parent)
429 return m_parent->GetLanguageFlags();
430 return this->ValueObject::GetLanguageFlags();
433 void ValueObjectSynthetic::SetLanguageFlags(uint64_t flags) {
434 if (m_parent)
435 m_parent->SetLanguageFlags(flags);
436 else
437 this->ValueObject::SetLanguageFlags(flags);