xref: /openbsd-src/gnu/llvm/lldb/source/Core/ValueObject.cpp (revision f6aab3d83b51b91c24247ad2c2573574de475a82)
1dda28197Spatrick //===-- ValueObject.cpp ---------------------------------------------------===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick 
9061da546Spatrick #include "lldb/Core/ValueObject.h"
10061da546Spatrick 
11061da546Spatrick #include "lldb/Core/Address.h"
12be691f3bSpatrick #include "lldb/Core/Declaration.h"
13061da546Spatrick #include "lldb/Core/Module.h"
14061da546Spatrick #include "lldb/Core/ValueObjectCast.h"
15061da546Spatrick #include "lldb/Core/ValueObjectChild.h"
16061da546Spatrick #include "lldb/Core/ValueObjectConstResult.h"
17061da546Spatrick #include "lldb/Core/ValueObjectDynamicValue.h"
18061da546Spatrick #include "lldb/Core/ValueObjectMemory.h"
19061da546Spatrick #include "lldb/Core/ValueObjectSyntheticFilter.h"
20061da546Spatrick #include "lldb/DataFormatters/DataVisualization.h"
21061da546Spatrick #include "lldb/DataFormatters/DumpValueObjectOptions.h"
22061da546Spatrick #include "lldb/DataFormatters/FormatManager.h"
23061da546Spatrick #include "lldb/DataFormatters/StringPrinter.h"
24061da546Spatrick #include "lldb/DataFormatters/TypeFormat.h"
25061da546Spatrick #include "lldb/DataFormatters/TypeSummary.h"
26061da546Spatrick #include "lldb/DataFormatters/ValueObjectPrinter.h"
27061da546Spatrick #include "lldb/Expression/ExpressionVariable.h"
28061da546Spatrick #include "lldb/Host/Config.h"
29061da546Spatrick #include "lldb/Symbol/CompileUnit.h"
30061da546Spatrick #include "lldb/Symbol/CompilerType.h"
31061da546Spatrick #include "lldb/Symbol/SymbolContext.h"
32061da546Spatrick #include "lldb/Symbol/Type.h"
33061da546Spatrick #include "lldb/Symbol/Variable.h"
34061da546Spatrick #include "lldb/Target/ExecutionContext.h"
35061da546Spatrick #include "lldb/Target/Language.h"
36061da546Spatrick #include "lldb/Target/LanguageRuntime.h"
37061da546Spatrick #include "lldb/Target/Process.h"
38061da546Spatrick #include "lldb/Target/StackFrame.h"
39061da546Spatrick #include "lldb/Target/Target.h"
40061da546Spatrick #include "lldb/Target/Thread.h"
41061da546Spatrick #include "lldb/Target/ThreadList.h"
42061da546Spatrick #include "lldb/Utility/DataBuffer.h"
43061da546Spatrick #include "lldb/Utility/DataBufferHeap.h"
44061da546Spatrick #include "lldb/Utility/Flags.h"
45*f6aab3d8Srobert #include "lldb/Utility/LLDBLog.h"
46061da546Spatrick #include "lldb/Utility/Log.h"
47061da546Spatrick #include "lldb/Utility/Scalar.h"
48061da546Spatrick #include "lldb/Utility/Stream.h"
49061da546Spatrick #include "lldb/Utility/StreamString.h"
50061da546Spatrick #include "lldb/lldb-private-types.h"
51061da546Spatrick 
52061da546Spatrick #include "llvm/Support/Compiler.h"
53061da546Spatrick 
54061da546Spatrick #include <algorithm>
55061da546Spatrick #include <cstdint>
56061da546Spatrick #include <cstdlib>
57061da546Spatrick #include <memory>
58*f6aab3d8Srobert #include <optional>
59061da546Spatrick #include <tuple>
60061da546Spatrick 
61be691f3bSpatrick #include <cassert>
62be691f3bSpatrick #include <cinttypes>
63be691f3bSpatrick #include <cstdio>
64be691f3bSpatrick #include <cstring>
65be691f3bSpatrick 
66be691f3bSpatrick #include <lldb/Core/ValueObject.h>
67061da546Spatrick 
68061da546Spatrick namespace lldb_private {
69061da546Spatrick class ExecutionContextScope;
70061da546Spatrick }
71061da546Spatrick namespace lldb_private {
72061da546Spatrick class SymbolContextScope;
73061da546Spatrick }
74061da546Spatrick 
75061da546Spatrick using namespace lldb;
76061da546Spatrick using namespace lldb_private;
77061da546Spatrick 
78061da546Spatrick static user_id_t g_value_obj_uid = 0;
79061da546Spatrick 
80061da546Spatrick // ValueObject constructor
ValueObject(ValueObject & parent)81061da546Spatrick ValueObject::ValueObject(ValueObject &parent)
82be691f3bSpatrick     : m_parent(&parent), m_update_point(parent.GetUpdatePoint()),
83be691f3bSpatrick       m_manager(parent.GetManager()), m_id(++g_value_obj_uid) {
84be691f3bSpatrick   m_flags.m_is_synthetic_children_generated =
85be691f3bSpatrick       parent.m_flags.m_is_synthetic_children_generated;
86061da546Spatrick   m_data.SetByteOrder(parent.GetDataExtractor().GetByteOrder());
87061da546Spatrick   m_data.SetAddressByteSize(parent.GetDataExtractor().GetAddressByteSize());
88061da546Spatrick   m_manager->ManageObject(this);
89061da546Spatrick }
90061da546Spatrick 
91061da546Spatrick // ValueObject constructor
ValueObject(ExecutionContextScope * exe_scope,ValueObjectManager & manager,AddressType child_ptr_or_ref_addr_type)92061da546Spatrick ValueObject::ValueObject(ExecutionContextScope *exe_scope,
93dda28197Spatrick                          ValueObjectManager &manager,
94061da546Spatrick                          AddressType child_ptr_or_ref_addr_type)
95be691f3bSpatrick     : m_update_point(exe_scope), m_manager(&manager),
96061da546Spatrick       m_address_type_of_ptr_or_ref_children(child_ptr_or_ref_addr_type),
97be691f3bSpatrick       m_id(++g_value_obj_uid) {
98061da546Spatrick   if (exe_scope) {
99061da546Spatrick     TargetSP target_sp(exe_scope->CalculateTarget());
100061da546Spatrick     if (target_sp) {
101061da546Spatrick       const ArchSpec &arch = target_sp->GetArchitecture();
102061da546Spatrick       m_data.SetByteOrder(arch.GetByteOrder());
103061da546Spatrick       m_data.SetAddressByteSize(arch.GetAddressByteSize());
104061da546Spatrick     }
105061da546Spatrick   }
106061da546Spatrick   m_manager->ManageObject(this);
107061da546Spatrick }
108061da546Spatrick 
109061da546Spatrick // Destructor
110be691f3bSpatrick ValueObject::~ValueObject() = default;
111061da546Spatrick 
UpdateValueIfNeeded(bool update_format)112061da546Spatrick bool ValueObject::UpdateValueIfNeeded(bool update_format) {
113061da546Spatrick 
114061da546Spatrick   bool did_change_formats = false;
115061da546Spatrick 
116061da546Spatrick   if (update_format)
117061da546Spatrick     did_change_formats = UpdateFormatsIfNeeded();
118061da546Spatrick 
119061da546Spatrick   // If this is a constant value, then our success is predicated on whether we
120061da546Spatrick   // have an error or not
121061da546Spatrick   if (GetIsConstant()) {
122061da546Spatrick     // if you are constant, things might still have changed behind your back
123061da546Spatrick     // (e.g. you are a frozen object and things have changed deeper than you
124061da546Spatrick     // cared to freeze-dry yourself) in this case, your value has not changed,
125061da546Spatrick     // but "computed" entries might have, so you might now have a different
126061da546Spatrick     // summary, or a different object description. clear these so we will
127061da546Spatrick     // recompute them
128061da546Spatrick     if (update_format && !did_change_formats)
129061da546Spatrick       ClearUserVisibleData(eClearUserVisibleDataItemsSummary |
130061da546Spatrick                            eClearUserVisibleDataItemsDescription);
131061da546Spatrick     return m_error.Success();
132061da546Spatrick   }
133061da546Spatrick 
134061da546Spatrick   bool first_update = IsChecksumEmpty();
135061da546Spatrick 
136061da546Spatrick   if (NeedsUpdating()) {
137061da546Spatrick     m_update_point.SetUpdated();
138061da546Spatrick 
139061da546Spatrick     // Save the old value using swap to avoid a string copy which also will
140061da546Spatrick     // clear our m_value_str
141061da546Spatrick     if (m_value_str.empty()) {
142be691f3bSpatrick       m_flags.m_old_value_valid = false;
143061da546Spatrick     } else {
144be691f3bSpatrick       m_flags.m_old_value_valid = true;
145061da546Spatrick       m_old_value_str.swap(m_value_str);
146061da546Spatrick       ClearUserVisibleData(eClearUserVisibleDataItemsValue);
147061da546Spatrick     }
148061da546Spatrick 
149061da546Spatrick     ClearUserVisibleData();
150061da546Spatrick 
151061da546Spatrick     if (IsInScope()) {
152061da546Spatrick       const bool value_was_valid = GetValueIsValid();
153061da546Spatrick       SetValueDidChange(false);
154061da546Spatrick 
155061da546Spatrick       m_error.Clear();
156061da546Spatrick 
157061da546Spatrick       // Call the pure virtual function to update the value
158061da546Spatrick 
159061da546Spatrick       bool need_compare_checksums = false;
160061da546Spatrick       llvm::SmallVector<uint8_t, 16> old_checksum;
161061da546Spatrick 
162061da546Spatrick       if (!first_update && CanProvideValue()) {
163061da546Spatrick         need_compare_checksums = true;
164061da546Spatrick         old_checksum.resize(m_value_checksum.size());
165061da546Spatrick         std::copy(m_value_checksum.begin(), m_value_checksum.end(),
166061da546Spatrick                   old_checksum.begin());
167061da546Spatrick       }
168061da546Spatrick 
169061da546Spatrick       bool success = UpdateValue();
170061da546Spatrick 
171061da546Spatrick       SetValueIsValid(success);
172061da546Spatrick 
173061da546Spatrick       if (success) {
174061da546Spatrick         UpdateChildrenAddressType();
175061da546Spatrick         const uint64_t max_checksum_size = 128;
176061da546Spatrick         m_data.Checksum(m_value_checksum, max_checksum_size);
177061da546Spatrick       } else {
178061da546Spatrick         need_compare_checksums = false;
179061da546Spatrick         m_value_checksum.clear();
180061da546Spatrick       }
181061da546Spatrick 
182061da546Spatrick       assert(!need_compare_checksums ||
183061da546Spatrick              (!old_checksum.empty() && !m_value_checksum.empty()));
184061da546Spatrick 
185061da546Spatrick       if (first_update)
186061da546Spatrick         SetValueDidChange(false);
187be691f3bSpatrick       else if (!m_flags.m_value_did_change && !success) {
188061da546Spatrick         // The value wasn't gotten successfully, so we mark this as changed if
189061da546Spatrick         // the value used to be valid and now isn't
190061da546Spatrick         SetValueDidChange(value_was_valid);
191061da546Spatrick       } else if (need_compare_checksums) {
192061da546Spatrick         SetValueDidChange(memcmp(&old_checksum[0], &m_value_checksum[0],
193061da546Spatrick                                  m_value_checksum.size()));
194061da546Spatrick       }
195061da546Spatrick 
196061da546Spatrick     } else {
197061da546Spatrick       m_error.SetErrorString("out of scope");
198061da546Spatrick     }
199061da546Spatrick   }
200061da546Spatrick   return m_error.Success();
201061da546Spatrick }
202061da546Spatrick 
UpdateFormatsIfNeeded()203061da546Spatrick bool ValueObject::UpdateFormatsIfNeeded() {
204*f6aab3d8Srobert   Log *log = GetLog(LLDBLog::DataFormatters);
205061da546Spatrick   LLDB_LOGF(log,
206061da546Spatrick             "[%s %p] checking for FormatManager revisions. ValueObject "
207061da546Spatrick             "rev: %d - Global rev: %d",
208061da546Spatrick             GetName().GetCString(), static_cast<void *>(this),
209061da546Spatrick             m_last_format_mgr_revision,
210061da546Spatrick             DataVisualization::GetCurrentRevision());
211061da546Spatrick 
212061da546Spatrick   bool any_change = false;
213061da546Spatrick 
214061da546Spatrick   if ((m_last_format_mgr_revision != DataVisualization::GetCurrentRevision())) {
215061da546Spatrick     m_last_format_mgr_revision = DataVisualization::GetCurrentRevision();
216061da546Spatrick     any_change = true;
217061da546Spatrick 
218061da546Spatrick     SetValueFormat(DataVisualization::GetFormat(*this, eNoDynamicValues));
219061da546Spatrick     SetSummaryFormat(
220061da546Spatrick         DataVisualization::GetSummaryFormat(*this, GetDynamicValueType()));
221061da546Spatrick #if LLDB_ENABLE_PYTHON
222061da546Spatrick     SetSyntheticChildren(
223061da546Spatrick         DataVisualization::GetSyntheticChildren(*this, GetDynamicValueType()));
224061da546Spatrick #endif
225061da546Spatrick   }
226061da546Spatrick 
227061da546Spatrick   return any_change;
228061da546Spatrick }
229061da546Spatrick 
SetNeedsUpdate()230061da546Spatrick void ValueObject::SetNeedsUpdate() {
231061da546Spatrick   m_update_point.SetNeedsUpdate();
232061da546Spatrick   // We have to clear the value string here so ConstResult children will notice
233061da546Spatrick   // if their values are changed by hand (i.e. with SetValueAsCString).
234061da546Spatrick   ClearUserVisibleData(eClearUserVisibleDataItemsValue);
235061da546Spatrick }
236061da546Spatrick 
ClearDynamicTypeInformation()237061da546Spatrick void ValueObject::ClearDynamicTypeInformation() {
238be691f3bSpatrick   m_flags.m_children_count_valid = false;
239be691f3bSpatrick   m_flags.m_did_calculate_complete_objc_class_type = false;
240061da546Spatrick   m_last_format_mgr_revision = 0;
241061da546Spatrick   m_override_type = CompilerType();
242061da546Spatrick   SetValueFormat(lldb::TypeFormatImplSP());
243061da546Spatrick   SetSummaryFormat(lldb::TypeSummaryImplSP());
244061da546Spatrick   SetSyntheticChildren(lldb::SyntheticChildrenSP());
245061da546Spatrick }
246061da546Spatrick 
MaybeCalculateCompleteType()247061da546Spatrick CompilerType ValueObject::MaybeCalculateCompleteType() {
248061da546Spatrick   CompilerType compiler_type(GetCompilerTypeImpl());
249061da546Spatrick 
250be691f3bSpatrick   if (m_flags.m_did_calculate_complete_objc_class_type) {
251061da546Spatrick     if (m_override_type.IsValid())
252061da546Spatrick       return m_override_type;
253061da546Spatrick     else
254061da546Spatrick       return compiler_type;
255061da546Spatrick   }
256061da546Spatrick 
257be691f3bSpatrick   m_flags.m_did_calculate_complete_objc_class_type = true;
258061da546Spatrick 
259061da546Spatrick   ProcessSP process_sp(
260061da546Spatrick       GetUpdatePoint().GetExecutionContextRef().GetProcessSP());
261061da546Spatrick 
262061da546Spatrick   if (!process_sp)
263061da546Spatrick     return compiler_type;
264061da546Spatrick 
265061da546Spatrick   if (auto *runtime =
266061da546Spatrick           process_sp->GetLanguageRuntime(GetObjectRuntimeLanguage())) {
267*f6aab3d8Srobert     if (std::optional<CompilerType> complete_type =
268061da546Spatrick             runtime->GetRuntimeType(compiler_type)) {
269*f6aab3d8Srobert       m_override_type = *complete_type;
270061da546Spatrick       if (m_override_type.IsValid())
271061da546Spatrick         return m_override_type;
272061da546Spatrick     }
273061da546Spatrick   }
274061da546Spatrick   return compiler_type;
275061da546Spatrick }
276061da546Spatrick 
277061da546Spatrick 
278061da546Spatrick 
GetDataExtractor()279061da546Spatrick DataExtractor &ValueObject::GetDataExtractor() {
280061da546Spatrick   UpdateValueIfNeeded(false);
281061da546Spatrick   return m_data;
282061da546Spatrick }
283061da546Spatrick 
GetError()284061da546Spatrick const Status &ValueObject::GetError() {
285061da546Spatrick   UpdateValueIfNeeded(false);
286061da546Spatrick   return m_error;
287061da546Spatrick }
288061da546Spatrick 
GetLocationAsCStringImpl(const Value & value,const DataExtractor & data)289061da546Spatrick const char *ValueObject::GetLocationAsCStringImpl(const Value &value,
290061da546Spatrick                                                   const DataExtractor &data) {
291061da546Spatrick   if (UpdateValueIfNeeded(false)) {
292061da546Spatrick     if (m_location_str.empty()) {
293061da546Spatrick       StreamString sstr;
294061da546Spatrick 
295061da546Spatrick       Value::ValueType value_type = value.GetValueType();
296061da546Spatrick 
297061da546Spatrick       switch (value_type) {
298be691f3bSpatrick       case Value::ValueType::Invalid:
299be691f3bSpatrick         m_location_str = "invalid";
300be691f3bSpatrick         break;
301be691f3bSpatrick       case Value::ValueType::Scalar:
302be691f3bSpatrick         if (value.GetContextType() == Value::ContextType::RegisterInfo) {
303061da546Spatrick           RegisterInfo *reg_info = value.GetRegisterInfo();
304061da546Spatrick           if (reg_info) {
305061da546Spatrick             if (reg_info->name)
306061da546Spatrick               m_location_str = reg_info->name;
307061da546Spatrick             else if (reg_info->alt_name)
308061da546Spatrick               m_location_str = reg_info->alt_name;
309061da546Spatrick             if (m_location_str.empty())
310061da546Spatrick               m_location_str = (reg_info->encoding == lldb::eEncodingVector)
311061da546Spatrick                                    ? "vector"
312061da546Spatrick                                    : "scalar";
313061da546Spatrick           }
314061da546Spatrick         }
315061da546Spatrick         if (m_location_str.empty())
316be691f3bSpatrick           m_location_str = "scalar";
317061da546Spatrick         break;
318061da546Spatrick 
319be691f3bSpatrick       case Value::ValueType::LoadAddress:
320be691f3bSpatrick       case Value::ValueType::FileAddress:
321be691f3bSpatrick       case Value::ValueType::HostAddress: {
322061da546Spatrick         uint32_t addr_nibble_size = data.GetAddressByteSize() * 2;
323061da546Spatrick         sstr.Printf("0x%*.*llx", addr_nibble_size, addr_nibble_size,
324061da546Spatrick                     value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS));
325dda28197Spatrick         m_location_str = std::string(sstr.GetString());
326061da546Spatrick       } break;
327061da546Spatrick       }
328061da546Spatrick     }
329061da546Spatrick   }
330061da546Spatrick   return m_location_str.c_str();
331061da546Spatrick }
332061da546Spatrick 
ResolveValue(Scalar & scalar)333061da546Spatrick bool ValueObject::ResolveValue(Scalar &scalar) {
334061da546Spatrick   if (UpdateValueIfNeeded(
335061da546Spatrick           false)) // make sure that you are up to date before returning anything
336061da546Spatrick   {
337061da546Spatrick     ExecutionContext exe_ctx(GetExecutionContextRef());
338061da546Spatrick     Value tmp_value(m_value);
339061da546Spatrick     scalar = tmp_value.ResolveValue(&exe_ctx);
340061da546Spatrick     if (scalar.IsValid()) {
341061da546Spatrick       const uint32_t bitfield_bit_size = GetBitfieldBitSize();
342061da546Spatrick       if (bitfield_bit_size)
343061da546Spatrick         return scalar.ExtractBitfield(bitfield_bit_size,
344061da546Spatrick                                       GetBitfieldBitOffset());
345061da546Spatrick       return true;
346061da546Spatrick     }
347061da546Spatrick   }
348061da546Spatrick   return false;
349061da546Spatrick }
350061da546Spatrick 
IsLogicalTrue(Status & error)351061da546Spatrick bool ValueObject::IsLogicalTrue(Status &error) {
352061da546Spatrick   if (Language *language = Language::FindPlugin(GetObjectRuntimeLanguage())) {
353061da546Spatrick     LazyBool is_logical_true = language->IsLogicalTrue(*this, error);
354061da546Spatrick     switch (is_logical_true) {
355061da546Spatrick     case eLazyBoolYes:
356061da546Spatrick     case eLazyBoolNo:
357061da546Spatrick       return (is_logical_true == true);
358061da546Spatrick     case eLazyBoolCalculate:
359061da546Spatrick       break;
360061da546Spatrick     }
361061da546Spatrick   }
362061da546Spatrick 
363061da546Spatrick   Scalar scalar_value;
364061da546Spatrick 
365061da546Spatrick   if (!ResolveValue(scalar_value)) {
366061da546Spatrick     error.SetErrorString("failed to get a scalar result");
367061da546Spatrick     return false;
368061da546Spatrick   }
369061da546Spatrick 
370061da546Spatrick   bool ret;
371061da546Spatrick   ret = scalar_value.ULongLong(1) != 0;
372061da546Spatrick   error.Clear();
373061da546Spatrick   return ret;
374061da546Spatrick }
375061da546Spatrick 
GetChildAtIndex(size_t idx,bool can_create)376061da546Spatrick ValueObjectSP ValueObject::GetChildAtIndex(size_t idx, bool can_create) {
377061da546Spatrick   ValueObjectSP child_sp;
378061da546Spatrick   // We may need to update our value if we are dynamic
379061da546Spatrick   if (IsPossibleDynamicType())
380061da546Spatrick     UpdateValueIfNeeded(false);
381061da546Spatrick   if (idx < GetNumChildren()) {
382061da546Spatrick     // Check if we have already made the child value object?
383061da546Spatrick     if (can_create && !m_children.HasChildAtIndex(idx)) {
384061da546Spatrick       // No we haven't created the child at this index, so lets have our
385061da546Spatrick       // subclass do it and cache the result for quick future access.
386061da546Spatrick       m_children.SetChildAtIndex(idx, CreateChildAtIndex(idx, false, 0));
387061da546Spatrick     }
388061da546Spatrick 
389061da546Spatrick     ValueObject *child = m_children.GetChildAtIndex(idx);
390061da546Spatrick     if (child != nullptr)
391061da546Spatrick       return child->GetSP();
392061da546Spatrick   }
393061da546Spatrick   return child_sp;
394061da546Spatrick }
395061da546Spatrick 
396061da546Spatrick lldb::ValueObjectSP
GetChildAtIndexPath(llvm::ArrayRef<size_t> idxs,size_t * index_of_error)397061da546Spatrick ValueObject::GetChildAtIndexPath(llvm::ArrayRef<size_t> idxs,
398061da546Spatrick                                  size_t *index_of_error) {
399061da546Spatrick   if (idxs.size() == 0)
400061da546Spatrick     return GetSP();
401061da546Spatrick   ValueObjectSP root(GetSP());
402061da546Spatrick   for (size_t idx : idxs) {
403061da546Spatrick     root = root->GetChildAtIndex(idx, true);
404061da546Spatrick     if (!root) {
405061da546Spatrick       if (index_of_error)
406061da546Spatrick         *index_of_error = idx;
407061da546Spatrick       return root;
408061da546Spatrick     }
409061da546Spatrick   }
410061da546Spatrick   return root;
411061da546Spatrick }
412061da546Spatrick 
GetChildAtIndexPath(llvm::ArrayRef<std::pair<size_t,bool>> idxs,size_t * index_of_error)413061da546Spatrick lldb::ValueObjectSP ValueObject::GetChildAtIndexPath(
414061da546Spatrick   llvm::ArrayRef<std::pair<size_t, bool>> idxs, size_t *index_of_error) {
415061da546Spatrick   if (idxs.size() == 0)
416061da546Spatrick     return GetSP();
417061da546Spatrick   ValueObjectSP root(GetSP());
418061da546Spatrick   for (std::pair<size_t, bool> idx : idxs) {
419061da546Spatrick     root = root->GetChildAtIndex(idx.first, idx.second);
420061da546Spatrick     if (!root) {
421061da546Spatrick       if (index_of_error)
422061da546Spatrick         *index_of_error = idx.first;
423061da546Spatrick       return root;
424061da546Spatrick     }
425061da546Spatrick   }
426061da546Spatrick   return root;
427061da546Spatrick }
428061da546Spatrick 
429061da546Spatrick lldb::ValueObjectSP
GetChildAtNamePath(llvm::ArrayRef<ConstString> names,ConstString * name_of_error)430061da546Spatrick ValueObject::GetChildAtNamePath(llvm::ArrayRef<ConstString> names,
431061da546Spatrick                                 ConstString *name_of_error) {
432061da546Spatrick   if (names.size() == 0)
433061da546Spatrick     return GetSP();
434061da546Spatrick   ValueObjectSP root(GetSP());
435061da546Spatrick   for (ConstString name : names) {
436061da546Spatrick     root = root->GetChildMemberWithName(name, true);
437061da546Spatrick     if (!root) {
438061da546Spatrick       if (name_of_error)
439061da546Spatrick         *name_of_error = name;
440061da546Spatrick       return root;
441061da546Spatrick     }
442061da546Spatrick   }
443061da546Spatrick   return root;
444061da546Spatrick }
445061da546Spatrick 
GetChildAtNamePath(llvm::ArrayRef<std::pair<ConstString,bool>> names,ConstString * name_of_error)446061da546Spatrick lldb::ValueObjectSP ValueObject::GetChildAtNamePath(
447061da546Spatrick     llvm::ArrayRef<std::pair<ConstString, bool>> names,
448061da546Spatrick     ConstString *name_of_error) {
449061da546Spatrick   if (names.size() == 0)
450061da546Spatrick     return GetSP();
451061da546Spatrick   ValueObjectSP root(GetSP());
452061da546Spatrick   for (std::pair<ConstString, bool> name : names) {
453061da546Spatrick     root = root->GetChildMemberWithName(name.first, name.second);
454061da546Spatrick     if (!root) {
455061da546Spatrick       if (name_of_error)
456061da546Spatrick         *name_of_error = name.first;
457061da546Spatrick       return root;
458061da546Spatrick     }
459061da546Spatrick   }
460061da546Spatrick   return root;
461061da546Spatrick }
462061da546Spatrick 
GetIndexOfChildWithName(ConstString name)463061da546Spatrick size_t ValueObject::GetIndexOfChildWithName(ConstString name) {
464061da546Spatrick   bool omit_empty_base_classes = true;
465061da546Spatrick   return GetCompilerType().GetIndexOfChildWithName(name.GetCString(),
466061da546Spatrick                                                    omit_empty_base_classes);
467061da546Spatrick }
468061da546Spatrick 
GetChildMemberWithName(ConstString name,bool can_create)469061da546Spatrick ValueObjectSP ValueObject::GetChildMemberWithName(ConstString name,
470061da546Spatrick                                                   bool can_create) {
471dda28197Spatrick   // We may need to update our value if we are dynamic.
472061da546Spatrick   if (IsPossibleDynamicType())
473061da546Spatrick     UpdateValueIfNeeded(false);
474061da546Spatrick 
475dda28197Spatrick   // When getting a child by name, it could be buried inside some base classes
476dda28197Spatrick   // (which really aren't part of the expression path), so we need a vector of
477dda28197Spatrick   // indexes that can get us down to the correct child.
478061da546Spatrick   std::vector<uint32_t> child_indexes;
479061da546Spatrick   bool omit_empty_base_classes = true;
480061da546Spatrick 
481061da546Spatrick   if (!GetCompilerType().IsValid())
482061da546Spatrick     return ValueObjectSP();
483061da546Spatrick 
484061da546Spatrick   const size_t num_child_indexes =
485061da546Spatrick       GetCompilerType().GetIndexOfChildMemberWithName(
486061da546Spatrick           name.GetCString(), omit_empty_base_classes, child_indexes);
487dda28197Spatrick   if (num_child_indexes == 0)
488dda28197Spatrick     return nullptr;
489061da546Spatrick 
490dda28197Spatrick   ValueObjectSP child_sp = GetSP();
491dda28197Spatrick   for (uint32_t idx : child_indexes)
492dda28197Spatrick     if (child_sp)
493dda28197Spatrick       child_sp = child_sp->GetChildAtIndex(idx, can_create);
494061da546Spatrick   return child_sp;
495061da546Spatrick }
496061da546Spatrick 
GetNumChildren(uint32_t max)497061da546Spatrick size_t ValueObject::GetNumChildren(uint32_t max) {
498061da546Spatrick   UpdateValueIfNeeded();
499061da546Spatrick 
500061da546Spatrick   if (max < UINT32_MAX) {
501be691f3bSpatrick     if (m_flags.m_children_count_valid) {
502061da546Spatrick       size_t children_count = m_children.GetChildrenCount();
503061da546Spatrick       return children_count <= max ? children_count : max;
504061da546Spatrick     } else
505061da546Spatrick       return CalculateNumChildren(max);
506061da546Spatrick   }
507061da546Spatrick 
508be691f3bSpatrick   if (!m_flags.m_children_count_valid) {
509061da546Spatrick     SetNumChildren(CalculateNumChildren());
510061da546Spatrick   }
511061da546Spatrick   return m_children.GetChildrenCount();
512061da546Spatrick }
513061da546Spatrick 
MightHaveChildren()514061da546Spatrick bool ValueObject::MightHaveChildren() {
515061da546Spatrick   bool has_children = false;
516061da546Spatrick   const uint32_t type_info = GetTypeInfo();
517061da546Spatrick   if (type_info) {
518061da546Spatrick     if (type_info & (eTypeHasChildren | eTypeIsPointer | eTypeIsReference))
519061da546Spatrick       has_children = true;
520061da546Spatrick   } else {
521061da546Spatrick     has_children = GetNumChildren() > 0;
522061da546Spatrick   }
523061da546Spatrick   return has_children;
524061da546Spatrick }
525061da546Spatrick 
526061da546Spatrick // Should only be called by ValueObject::GetNumChildren()
SetNumChildren(size_t num_children)527061da546Spatrick void ValueObject::SetNumChildren(size_t num_children) {
528be691f3bSpatrick   m_flags.m_children_count_valid = true;
529061da546Spatrick   m_children.SetChildrenCount(num_children);
530061da546Spatrick }
531061da546Spatrick 
CreateChildAtIndex(size_t idx,bool synthetic_array_member,int32_t synthetic_index)532061da546Spatrick ValueObject *ValueObject::CreateChildAtIndex(size_t idx,
533061da546Spatrick                                              bool synthetic_array_member,
534061da546Spatrick                                              int32_t synthetic_index) {
535061da546Spatrick   ValueObject *valobj = nullptr;
536061da546Spatrick 
537061da546Spatrick   bool omit_empty_base_classes = true;
538061da546Spatrick   bool ignore_array_bounds = synthetic_array_member;
539061da546Spatrick   std::string child_name_str;
540061da546Spatrick   uint32_t child_byte_size = 0;
541061da546Spatrick   int32_t child_byte_offset = 0;
542061da546Spatrick   uint32_t child_bitfield_bit_size = 0;
543061da546Spatrick   uint32_t child_bitfield_bit_offset = 0;
544061da546Spatrick   bool child_is_base_class = false;
545061da546Spatrick   bool child_is_deref_of_parent = false;
546061da546Spatrick   uint64_t language_flags = 0;
547061da546Spatrick 
548061da546Spatrick   const bool transparent_pointers = !synthetic_array_member;
549061da546Spatrick   CompilerType child_compiler_type;
550061da546Spatrick 
551061da546Spatrick   ExecutionContext exe_ctx(GetExecutionContextRef());
552061da546Spatrick 
553061da546Spatrick   child_compiler_type = GetCompilerType().GetChildCompilerTypeAtIndex(
554061da546Spatrick       &exe_ctx, idx, transparent_pointers, omit_empty_base_classes,
555061da546Spatrick       ignore_array_bounds, child_name_str, child_byte_size, child_byte_offset,
556061da546Spatrick       child_bitfield_bit_size, child_bitfield_bit_offset, child_is_base_class,
557061da546Spatrick       child_is_deref_of_parent, this, language_flags);
558061da546Spatrick   if (child_compiler_type) {
559061da546Spatrick     if (synthetic_index)
560061da546Spatrick       child_byte_offset += child_byte_size * synthetic_index;
561061da546Spatrick 
562061da546Spatrick     ConstString child_name;
563061da546Spatrick     if (!child_name_str.empty())
564061da546Spatrick       child_name.SetCString(child_name_str.c_str());
565061da546Spatrick 
566061da546Spatrick     valobj = new ValueObjectChild(
567061da546Spatrick         *this, child_compiler_type, child_name, child_byte_size,
568061da546Spatrick         child_byte_offset, child_bitfield_bit_size, child_bitfield_bit_offset,
569061da546Spatrick         child_is_base_class, child_is_deref_of_parent, eAddressTypeInvalid,
570061da546Spatrick         language_flags);
571061da546Spatrick   }
572061da546Spatrick 
573dda28197Spatrick   // In case of an incomplete type, try to use the ValueObject's
574dda28197Spatrick   // synthetic value to create the child ValueObject.
575dda28197Spatrick   if (!valobj && synthetic_array_member) {
576dda28197Spatrick     if (ValueObjectSP synth_valobj_sp = GetSyntheticValue()) {
577dda28197Spatrick       valobj = synth_valobj_sp
578dda28197Spatrick                    ->GetChildAtIndex(synthetic_index, synthetic_array_member)
579dda28197Spatrick                    .get();
580dda28197Spatrick     }
581dda28197Spatrick   }
582dda28197Spatrick 
583061da546Spatrick   return valobj;
584061da546Spatrick }
585061da546Spatrick 
GetSummaryAsCString(TypeSummaryImpl * summary_ptr,std::string & destination,lldb::LanguageType lang)586061da546Spatrick bool ValueObject::GetSummaryAsCString(TypeSummaryImpl *summary_ptr,
587061da546Spatrick                                       std::string &destination,
588061da546Spatrick                                       lldb::LanguageType lang) {
589061da546Spatrick   return GetSummaryAsCString(summary_ptr, destination,
590061da546Spatrick                              TypeSummaryOptions().SetLanguage(lang));
591061da546Spatrick }
592061da546Spatrick 
GetSummaryAsCString(TypeSummaryImpl * summary_ptr,std::string & destination,const TypeSummaryOptions & options)593061da546Spatrick bool ValueObject::GetSummaryAsCString(TypeSummaryImpl *summary_ptr,
594061da546Spatrick                                       std::string &destination,
595061da546Spatrick                                       const TypeSummaryOptions &options) {
596061da546Spatrick   destination.clear();
597061da546Spatrick 
598*f6aab3d8Srobert   // If we have a forcefully completed type, don't try and show a summary from
599*f6aab3d8Srobert   // a valid summary string or function because the type is not complete and
600*f6aab3d8Srobert   // no member variables or member functions will be available.
601*f6aab3d8Srobert   if (GetCompilerType().IsForcefullyCompleted()) {
602*f6aab3d8Srobert       destination = "<incomplete type>";
603*f6aab3d8Srobert       return true;
604*f6aab3d8Srobert   }
605*f6aab3d8Srobert 
606061da546Spatrick   // ideally we would like to bail out if passing NULL, but if we do so we end
607061da546Spatrick   // up not providing the summary for function pointers anymore
608be691f3bSpatrick   if (/*summary_ptr == NULL ||*/ m_flags.m_is_getting_summary)
609061da546Spatrick     return false;
610061da546Spatrick 
611be691f3bSpatrick   m_flags.m_is_getting_summary = true;
612061da546Spatrick 
613061da546Spatrick   TypeSummaryOptions actual_options(options);
614061da546Spatrick 
615061da546Spatrick   if (actual_options.GetLanguage() == lldb::eLanguageTypeUnknown)
616061da546Spatrick     actual_options.SetLanguage(GetPreferredDisplayLanguage());
617061da546Spatrick 
618061da546Spatrick   // this is a hot path in code and we prefer to avoid setting this string all
619061da546Spatrick   // too often also clearing out other information that we might care to see in
620061da546Spatrick   // a crash log. might be useful in very specific situations though.
621061da546Spatrick   /*Host::SetCrashDescriptionWithFormat("Trying to fetch a summary for %s %s.
622061da546Spatrick    Summary provider's description is %s",
623061da546Spatrick    GetTypeName().GetCString(),
624061da546Spatrick    GetName().GetCString(),
625061da546Spatrick    summary_ptr->GetDescription().c_str());*/
626061da546Spatrick 
627061da546Spatrick   if (UpdateValueIfNeeded(false) && summary_ptr) {
628061da546Spatrick     if (HasSyntheticValue())
629061da546Spatrick       m_synthetic_value->UpdateValueIfNeeded(); // the summary might depend on
630061da546Spatrick                                                 // the synthetic children being
631061da546Spatrick                                                 // up-to-date (e.g. ${svar%#})
632061da546Spatrick     summary_ptr->FormatObject(this, destination, actual_options);
633061da546Spatrick   }
634be691f3bSpatrick   m_flags.m_is_getting_summary = false;
635061da546Spatrick   return !destination.empty();
636061da546Spatrick }
637061da546Spatrick 
GetSummaryAsCString(lldb::LanguageType lang)638061da546Spatrick const char *ValueObject::GetSummaryAsCString(lldb::LanguageType lang) {
639061da546Spatrick   if (UpdateValueIfNeeded(true) && m_summary_str.empty()) {
640061da546Spatrick     TypeSummaryOptions summary_options;
641061da546Spatrick     summary_options.SetLanguage(lang);
642061da546Spatrick     GetSummaryAsCString(GetSummaryFormat().get(), m_summary_str,
643061da546Spatrick                         summary_options);
644061da546Spatrick   }
645061da546Spatrick   if (m_summary_str.empty())
646061da546Spatrick     return nullptr;
647061da546Spatrick   return m_summary_str.c_str();
648061da546Spatrick }
649061da546Spatrick 
GetSummaryAsCString(std::string & destination,const TypeSummaryOptions & options)650061da546Spatrick bool ValueObject::GetSummaryAsCString(std::string &destination,
651061da546Spatrick                                       const TypeSummaryOptions &options) {
652061da546Spatrick   return GetSummaryAsCString(GetSummaryFormat().get(), destination, options);
653061da546Spatrick }
654061da546Spatrick 
IsCStringContainer(bool check_pointer)655061da546Spatrick bool ValueObject::IsCStringContainer(bool check_pointer) {
656061da546Spatrick   CompilerType pointee_or_element_compiler_type;
657061da546Spatrick   const Flags type_flags(GetTypeInfo(&pointee_or_element_compiler_type));
658061da546Spatrick   bool is_char_arr_ptr(type_flags.AnySet(eTypeIsArray | eTypeIsPointer) &&
659061da546Spatrick                        pointee_or_element_compiler_type.IsCharType());
660061da546Spatrick   if (!is_char_arr_ptr)
661061da546Spatrick     return false;
662061da546Spatrick   if (!check_pointer)
663061da546Spatrick     return true;
664061da546Spatrick   if (type_flags.Test(eTypeIsArray))
665061da546Spatrick     return true;
666061da546Spatrick   addr_t cstr_address = LLDB_INVALID_ADDRESS;
667061da546Spatrick   AddressType cstr_address_type = eAddressTypeInvalid;
668dda28197Spatrick   cstr_address = GetPointerValue(&cstr_address_type);
669061da546Spatrick   return (cstr_address != LLDB_INVALID_ADDRESS);
670061da546Spatrick }
671061da546Spatrick 
GetPointeeData(DataExtractor & data,uint32_t item_idx,uint32_t item_count)672061da546Spatrick size_t ValueObject::GetPointeeData(DataExtractor &data, uint32_t item_idx,
673061da546Spatrick                                    uint32_t item_count) {
674061da546Spatrick   CompilerType pointee_or_element_compiler_type;
675061da546Spatrick   const uint32_t type_info = GetTypeInfo(&pointee_or_element_compiler_type);
676061da546Spatrick   const bool is_pointer_type = type_info & eTypeIsPointer;
677061da546Spatrick   const bool is_array_type = type_info & eTypeIsArray;
678061da546Spatrick   if (!(is_pointer_type || is_array_type))
679061da546Spatrick     return 0;
680061da546Spatrick 
681061da546Spatrick   if (item_count == 0)
682061da546Spatrick     return 0;
683061da546Spatrick 
684061da546Spatrick   ExecutionContext exe_ctx(GetExecutionContextRef());
685061da546Spatrick 
686*f6aab3d8Srobert   std::optional<uint64_t> item_type_size =
687061da546Spatrick       pointee_or_element_compiler_type.GetByteSize(
688061da546Spatrick           exe_ctx.GetBestExecutionContextScope());
689061da546Spatrick   if (!item_type_size)
690061da546Spatrick     return 0;
691061da546Spatrick   const uint64_t bytes = item_count * *item_type_size;
692061da546Spatrick   const uint64_t offset = item_idx * *item_type_size;
693061da546Spatrick 
694061da546Spatrick   if (item_idx == 0 && item_count == 1) // simply a deref
695061da546Spatrick   {
696061da546Spatrick     if (is_pointer_type) {
697061da546Spatrick       Status error;
698061da546Spatrick       ValueObjectSP pointee_sp = Dereference(error);
699061da546Spatrick       if (error.Fail() || pointee_sp.get() == nullptr)
700061da546Spatrick         return 0;
701061da546Spatrick       return pointee_sp->GetData(data, error);
702061da546Spatrick     } else {
703061da546Spatrick       ValueObjectSP child_sp = GetChildAtIndex(0, true);
704061da546Spatrick       if (child_sp.get() == nullptr)
705061da546Spatrick         return 0;
706061da546Spatrick       Status error;
707061da546Spatrick       return child_sp->GetData(data, error);
708061da546Spatrick     }
709061da546Spatrick     return true;
710061da546Spatrick   } else /* (items > 1) */
711061da546Spatrick   {
712061da546Spatrick     Status error;
713061da546Spatrick     lldb_private::DataBufferHeap *heap_buf_ptr = nullptr;
714061da546Spatrick     lldb::DataBufferSP data_sp(heap_buf_ptr =
715061da546Spatrick                                    new lldb_private::DataBufferHeap());
716061da546Spatrick 
717061da546Spatrick     AddressType addr_type;
718061da546Spatrick     lldb::addr_t addr = is_pointer_type ? GetPointerValue(&addr_type)
719061da546Spatrick                                         : GetAddressOf(true, &addr_type);
720061da546Spatrick 
721061da546Spatrick     switch (addr_type) {
722061da546Spatrick     case eAddressTypeFile: {
723061da546Spatrick       ModuleSP module_sp(GetModule());
724061da546Spatrick       if (module_sp) {
725061da546Spatrick         addr = addr + offset;
726061da546Spatrick         Address so_addr;
727061da546Spatrick         module_sp->ResolveFileAddress(addr, so_addr);
728061da546Spatrick         ExecutionContext exe_ctx(GetExecutionContextRef());
729061da546Spatrick         Target *target = exe_ctx.GetTargetPtr();
730061da546Spatrick         if (target) {
731061da546Spatrick           heap_buf_ptr->SetByteSize(bytes);
732061da546Spatrick           size_t bytes_read = target->ReadMemory(
733be691f3bSpatrick               so_addr, heap_buf_ptr->GetBytes(), bytes, error, true);
734061da546Spatrick           if (error.Success()) {
735061da546Spatrick             data.SetData(data_sp);
736061da546Spatrick             return bytes_read;
737061da546Spatrick           }
738061da546Spatrick         }
739061da546Spatrick       }
740061da546Spatrick     } break;
741061da546Spatrick     case eAddressTypeLoad: {
742061da546Spatrick       ExecutionContext exe_ctx(GetExecutionContextRef());
743061da546Spatrick       Process *process = exe_ctx.GetProcessPtr();
744061da546Spatrick       if (process) {
745061da546Spatrick         heap_buf_ptr->SetByteSize(bytes);
746061da546Spatrick         size_t bytes_read = process->ReadMemory(
747061da546Spatrick             addr + offset, heap_buf_ptr->GetBytes(), bytes, error);
748061da546Spatrick         if (error.Success() || bytes_read > 0) {
749061da546Spatrick           data.SetData(data_sp);
750061da546Spatrick           return bytes_read;
751061da546Spatrick         }
752061da546Spatrick       }
753061da546Spatrick     } break;
754061da546Spatrick     case eAddressTypeHost: {
755061da546Spatrick       auto max_bytes =
756061da546Spatrick           GetCompilerType().GetByteSize(exe_ctx.GetBestExecutionContextScope());
757061da546Spatrick       if (max_bytes && *max_bytes > offset) {
758061da546Spatrick         size_t bytes_read = std::min<uint64_t>(*max_bytes - offset, bytes);
759061da546Spatrick         addr = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
760061da546Spatrick         if (addr == 0 || addr == LLDB_INVALID_ADDRESS)
761061da546Spatrick           break;
762061da546Spatrick         heap_buf_ptr->CopyData((uint8_t *)(addr + offset), bytes_read);
763061da546Spatrick         data.SetData(data_sp);
764061da546Spatrick         return bytes_read;
765061da546Spatrick       }
766061da546Spatrick     } break;
767061da546Spatrick     case eAddressTypeInvalid:
768061da546Spatrick       break;
769061da546Spatrick     }
770061da546Spatrick   }
771061da546Spatrick   return 0;
772061da546Spatrick }
773061da546Spatrick 
GetData(DataExtractor & data,Status & error)774061da546Spatrick uint64_t ValueObject::GetData(DataExtractor &data, Status &error) {
775061da546Spatrick   UpdateValueIfNeeded(false);
776061da546Spatrick   ExecutionContext exe_ctx(GetExecutionContextRef());
777061da546Spatrick   error = m_value.GetValueAsData(&exe_ctx, data, GetModule().get());
778061da546Spatrick   if (error.Fail()) {
779061da546Spatrick     if (m_data.GetByteSize()) {
780061da546Spatrick       data = m_data;
781061da546Spatrick       error.Clear();
782061da546Spatrick       return data.GetByteSize();
783061da546Spatrick     } else {
784061da546Spatrick       return 0;
785061da546Spatrick     }
786061da546Spatrick   }
787061da546Spatrick   data.SetAddressByteSize(m_data.GetAddressByteSize());
788061da546Spatrick   data.SetByteOrder(m_data.GetByteOrder());
789061da546Spatrick   return data.GetByteSize();
790061da546Spatrick }
791061da546Spatrick 
SetData(DataExtractor & data,Status & error)792061da546Spatrick bool ValueObject::SetData(DataExtractor &data, Status &error) {
793061da546Spatrick   error.Clear();
794061da546Spatrick   // Make sure our value is up to date first so that our location and location
795061da546Spatrick   // type is valid.
796061da546Spatrick   if (!UpdateValueIfNeeded(false)) {
797061da546Spatrick     error.SetErrorString("unable to read value");
798061da546Spatrick     return false;
799061da546Spatrick   }
800061da546Spatrick 
801061da546Spatrick   uint64_t count = 0;
802061da546Spatrick   const Encoding encoding = GetCompilerType().GetEncoding(count);
803061da546Spatrick 
804*f6aab3d8Srobert   const size_t byte_size = GetByteSize().value_or(0);
805061da546Spatrick 
806061da546Spatrick   Value::ValueType value_type = m_value.GetValueType();
807061da546Spatrick 
808061da546Spatrick   switch (value_type) {
809be691f3bSpatrick   case Value::ValueType::Invalid:
810be691f3bSpatrick     error.SetErrorString("invalid location");
811be691f3bSpatrick     return false;
812be691f3bSpatrick   case Value::ValueType::Scalar: {
813061da546Spatrick     Status set_error =
814061da546Spatrick         m_value.GetScalar().SetValueFromData(data, encoding, byte_size);
815061da546Spatrick 
816061da546Spatrick     if (!set_error.Success()) {
817061da546Spatrick       error.SetErrorStringWithFormat("unable to set scalar value: %s",
818061da546Spatrick                                      set_error.AsCString());
819061da546Spatrick       return false;
820061da546Spatrick     }
821061da546Spatrick   } break;
822be691f3bSpatrick   case Value::ValueType::LoadAddress: {
823061da546Spatrick     // If it is a load address, then the scalar value is the storage location
824061da546Spatrick     // of the data, and we have to shove this value down to that load location.
825061da546Spatrick     ExecutionContext exe_ctx(GetExecutionContextRef());
826061da546Spatrick     Process *process = exe_ctx.GetProcessPtr();
827061da546Spatrick     if (process) {
828061da546Spatrick       addr_t target_addr = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
829061da546Spatrick       size_t bytes_written = process->WriteMemory(
830061da546Spatrick           target_addr, data.GetDataStart(), byte_size, error);
831061da546Spatrick       if (!error.Success())
832061da546Spatrick         return false;
833061da546Spatrick       if (bytes_written != byte_size) {
834061da546Spatrick         error.SetErrorString("unable to write value to memory");
835061da546Spatrick         return false;
836061da546Spatrick       }
837061da546Spatrick     }
838061da546Spatrick   } break;
839be691f3bSpatrick   case Value::ValueType::HostAddress: {
840061da546Spatrick     // If it is a host address, then we stuff the scalar as a DataBuffer into
841061da546Spatrick     // the Value's data.
842061da546Spatrick     DataBufferSP buffer_sp(new DataBufferHeap(byte_size, 0));
843061da546Spatrick     m_data.SetData(buffer_sp, 0);
844061da546Spatrick     data.CopyByteOrderedData(0, byte_size,
845061da546Spatrick                              const_cast<uint8_t *>(m_data.GetDataStart()),
846061da546Spatrick                              byte_size, m_data.GetByteOrder());
847061da546Spatrick     m_value.GetScalar() = (uintptr_t)m_data.GetDataStart();
848061da546Spatrick   } break;
849be691f3bSpatrick   case Value::ValueType::FileAddress:
850061da546Spatrick     break;
851061da546Spatrick   }
852061da546Spatrick 
853061da546Spatrick   // If we have reached this point, then we have successfully changed the
854061da546Spatrick   // value.
855061da546Spatrick   SetNeedsUpdate();
856061da546Spatrick   return true;
857061da546Spatrick }
858061da546Spatrick 
CopyStringDataToBufferSP(const StreamString & source,lldb::WritableDataBufferSP & destination)859061da546Spatrick static bool CopyStringDataToBufferSP(const StreamString &source,
860*f6aab3d8Srobert                                      lldb::WritableDataBufferSP &destination) {
861*f6aab3d8Srobert   llvm::StringRef src = source.GetString();
862*f6aab3d8Srobert   src = src.rtrim('\0');
863*f6aab3d8Srobert   destination = std::make_shared<DataBufferHeap>(src.size(), 0);
864*f6aab3d8Srobert   memcpy(destination->GetBytes(), src.data(), src.size());
865061da546Spatrick   return true;
866061da546Spatrick }
867061da546Spatrick 
868061da546Spatrick std::pair<size_t, bool>
ReadPointedString(lldb::WritableDataBufferSP & buffer_sp,Status & error,uint32_t max_length,bool honor_array,Format item_format)869*f6aab3d8Srobert ValueObject::ReadPointedString(lldb::WritableDataBufferSP &buffer_sp,
870*f6aab3d8Srobert                                Status &error, uint32_t max_length,
871*f6aab3d8Srobert                                bool honor_array, Format item_format) {
872061da546Spatrick   bool was_capped = false;
873061da546Spatrick   StreamString s;
874061da546Spatrick   ExecutionContext exe_ctx(GetExecutionContextRef());
875061da546Spatrick   Target *target = exe_ctx.GetTargetPtr();
876061da546Spatrick 
877061da546Spatrick   if (!target) {
878061da546Spatrick     s << "<no target to read from>";
879061da546Spatrick     error.SetErrorString("no target to read from");
880061da546Spatrick     CopyStringDataToBufferSP(s, buffer_sp);
881061da546Spatrick     return {0, was_capped};
882061da546Spatrick   }
883061da546Spatrick 
884061da546Spatrick   if (max_length == 0)
885061da546Spatrick     max_length = target->GetMaximumSizeOfStringSummary();
886061da546Spatrick 
887061da546Spatrick   size_t bytes_read = 0;
888061da546Spatrick   size_t total_bytes_read = 0;
889061da546Spatrick 
890061da546Spatrick   CompilerType compiler_type = GetCompilerType();
891061da546Spatrick   CompilerType elem_or_pointee_compiler_type;
892061da546Spatrick   const Flags type_flags(GetTypeInfo(&elem_or_pointee_compiler_type));
893061da546Spatrick   if (type_flags.AnySet(eTypeIsArray | eTypeIsPointer) &&
894061da546Spatrick       elem_or_pointee_compiler_type.IsCharType()) {
895061da546Spatrick     addr_t cstr_address = LLDB_INVALID_ADDRESS;
896061da546Spatrick     AddressType cstr_address_type = eAddressTypeInvalid;
897061da546Spatrick 
898061da546Spatrick     size_t cstr_len = 0;
899061da546Spatrick     bool capped_data = false;
900061da546Spatrick     const bool is_array = type_flags.Test(eTypeIsArray);
901061da546Spatrick     if (is_array) {
902061da546Spatrick       // We have an array
903061da546Spatrick       uint64_t array_size = 0;
904be691f3bSpatrick       if (compiler_type.IsArrayType(nullptr, &array_size)) {
905061da546Spatrick         cstr_len = array_size;
906061da546Spatrick         if (cstr_len > max_length) {
907061da546Spatrick           capped_data = true;
908061da546Spatrick           cstr_len = max_length;
909061da546Spatrick         }
910061da546Spatrick       }
911061da546Spatrick       cstr_address = GetAddressOf(true, &cstr_address_type);
912061da546Spatrick     } else {
913061da546Spatrick       // We have a pointer
914061da546Spatrick       cstr_address = GetPointerValue(&cstr_address_type);
915061da546Spatrick     }
916061da546Spatrick 
917061da546Spatrick     if (cstr_address == 0 || cstr_address == LLDB_INVALID_ADDRESS) {
918061da546Spatrick       if (cstr_address_type == eAddressTypeHost && is_array) {
919061da546Spatrick         const char *cstr = GetDataExtractor().PeekCStr(0);
920061da546Spatrick         if (cstr == nullptr) {
921061da546Spatrick           s << "<invalid address>";
922061da546Spatrick           error.SetErrorString("invalid address");
923061da546Spatrick           CopyStringDataToBufferSP(s, buffer_sp);
924061da546Spatrick           return {0, was_capped};
925061da546Spatrick         }
926*f6aab3d8Srobert         s << llvm::StringRef(cstr, cstr_len);
927*f6aab3d8Srobert         CopyStringDataToBufferSP(s, buffer_sp);
928061da546Spatrick         return {cstr_len, was_capped};
929061da546Spatrick       } else {
930061da546Spatrick         s << "<invalid address>";
931061da546Spatrick         error.SetErrorString("invalid address");
932061da546Spatrick         CopyStringDataToBufferSP(s, buffer_sp);
933061da546Spatrick         return {0, was_capped};
934061da546Spatrick       }
935061da546Spatrick     }
936061da546Spatrick 
937061da546Spatrick     Address cstr_so_addr(cstr_address);
938061da546Spatrick     DataExtractor data;
939061da546Spatrick     if (cstr_len > 0 && honor_array) {
940061da546Spatrick       // I am using GetPointeeData() here to abstract the fact that some
941061da546Spatrick       // ValueObjects are actually frozen pointers in the host but the pointed-
942061da546Spatrick       // to data lives in the debuggee, and GetPointeeData() automatically
943061da546Spatrick       // takes care of this
944061da546Spatrick       GetPointeeData(data, 0, cstr_len);
945061da546Spatrick 
946061da546Spatrick       if ((bytes_read = data.GetByteSize()) > 0) {
947061da546Spatrick         total_bytes_read = bytes_read;
948061da546Spatrick         for (size_t offset = 0; offset < bytes_read; offset++)
949061da546Spatrick           s.Printf("%c", *data.PeekData(offset, 1));
950061da546Spatrick         if (capped_data)
951061da546Spatrick           was_capped = true;
952061da546Spatrick       }
953061da546Spatrick     } else {
954061da546Spatrick       cstr_len = max_length;
955061da546Spatrick       const size_t k_max_buf_size = 64;
956061da546Spatrick 
957061da546Spatrick       size_t offset = 0;
958061da546Spatrick 
959061da546Spatrick       int cstr_len_displayed = -1;
960061da546Spatrick       bool capped_cstr = false;
961061da546Spatrick       // I am using GetPointeeData() here to abstract the fact that some
962061da546Spatrick       // ValueObjects are actually frozen pointers in the host but the pointed-
963061da546Spatrick       // to data lives in the debuggee, and GetPointeeData() automatically
964061da546Spatrick       // takes care of this
965061da546Spatrick       while ((bytes_read = GetPointeeData(data, offset, k_max_buf_size)) > 0) {
966061da546Spatrick         total_bytes_read += bytes_read;
967061da546Spatrick         const char *cstr = data.PeekCStr(0);
968061da546Spatrick         size_t len = strnlen(cstr, k_max_buf_size);
969061da546Spatrick         if (cstr_len_displayed < 0)
970061da546Spatrick           cstr_len_displayed = len;
971061da546Spatrick 
972061da546Spatrick         if (len == 0)
973061da546Spatrick           break;
974061da546Spatrick         cstr_len_displayed += len;
975061da546Spatrick         if (len > bytes_read)
976061da546Spatrick           len = bytes_read;
977061da546Spatrick         if (len > cstr_len)
978061da546Spatrick           len = cstr_len;
979061da546Spatrick 
980061da546Spatrick         for (size_t offset = 0; offset < bytes_read; offset++)
981061da546Spatrick           s.Printf("%c", *data.PeekData(offset, 1));
982061da546Spatrick 
983061da546Spatrick         if (len < k_max_buf_size)
984061da546Spatrick           break;
985061da546Spatrick 
986061da546Spatrick         if (len >= cstr_len) {
987061da546Spatrick           capped_cstr = true;
988061da546Spatrick           break;
989061da546Spatrick         }
990061da546Spatrick 
991061da546Spatrick         cstr_len -= len;
992061da546Spatrick         offset += len;
993061da546Spatrick       }
994061da546Spatrick 
995061da546Spatrick       if (cstr_len_displayed >= 0) {
996061da546Spatrick         if (capped_cstr)
997061da546Spatrick           was_capped = true;
998061da546Spatrick       }
999061da546Spatrick     }
1000061da546Spatrick   } else {
1001061da546Spatrick     error.SetErrorString("not a string object");
1002061da546Spatrick     s << "<not a string object>";
1003061da546Spatrick   }
1004061da546Spatrick   CopyStringDataToBufferSP(s, buffer_sp);
1005061da546Spatrick   return {total_bytes_read, was_capped};
1006061da546Spatrick }
1007061da546Spatrick 
GetObjectDescription()1008061da546Spatrick const char *ValueObject::GetObjectDescription() {
1009061da546Spatrick   if (!UpdateValueIfNeeded(true))
1010061da546Spatrick     return nullptr;
1011061da546Spatrick 
1012061da546Spatrick   // Return cached value.
1013061da546Spatrick   if (!m_object_desc_str.empty())
1014061da546Spatrick     return m_object_desc_str.c_str();
1015061da546Spatrick 
1016061da546Spatrick   ExecutionContext exe_ctx(GetExecutionContextRef());
1017061da546Spatrick   Process *process = exe_ctx.GetProcessPtr();
1018061da546Spatrick   if (!process)
1019061da546Spatrick     return nullptr;
1020061da546Spatrick 
1021061da546Spatrick   // Returns the object description produced by one language runtime.
1022061da546Spatrick   auto get_object_description = [&](LanguageType language) -> const char * {
1023061da546Spatrick     if (LanguageRuntime *runtime = process->GetLanguageRuntime(language)) {
1024061da546Spatrick       StreamString s;
1025061da546Spatrick       if (runtime->GetObjectDescription(s, *this)) {
1026dda28197Spatrick         m_object_desc_str.append(std::string(s.GetString()));
1027061da546Spatrick         return m_object_desc_str.c_str();
1028061da546Spatrick       }
1029061da546Spatrick     }
1030061da546Spatrick     return nullptr;
1031061da546Spatrick   };
1032061da546Spatrick 
1033061da546Spatrick   // Try the native language runtime first.
1034061da546Spatrick   LanguageType native_language = GetObjectRuntimeLanguage();
1035061da546Spatrick   if (const char *desc = get_object_description(native_language))
1036061da546Spatrick     return desc;
1037061da546Spatrick 
1038061da546Spatrick   // Try the Objective-C language runtime. This fallback is necessary
1039061da546Spatrick   // for Objective-C++ and mixed Objective-C / C++ programs.
1040061da546Spatrick   if (Language::LanguageIsCFamily(native_language))
1041061da546Spatrick     return get_object_description(eLanguageTypeObjC);
1042061da546Spatrick   return nullptr;
1043061da546Spatrick }
1044061da546Spatrick 
GetValueAsCString(const lldb_private::TypeFormatImpl & format,std::string & destination)1045061da546Spatrick bool ValueObject::GetValueAsCString(const lldb_private::TypeFormatImpl &format,
1046061da546Spatrick                                     std::string &destination) {
1047061da546Spatrick   if (UpdateValueIfNeeded(false))
1048061da546Spatrick     return format.FormatObject(this, destination);
1049061da546Spatrick   else
1050061da546Spatrick     return false;
1051061da546Spatrick }
1052061da546Spatrick 
GetValueAsCString(lldb::Format format,std::string & destination)1053061da546Spatrick bool ValueObject::GetValueAsCString(lldb::Format format,
1054061da546Spatrick                                     std::string &destination) {
1055061da546Spatrick   return GetValueAsCString(TypeFormatImpl_Format(format), destination);
1056061da546Spatrick }
1057061da546Spatrick 
GetValueAsCString()1058061da546Spatrick const char *ValueObject::GetValueAsCString() {
1059061da546Spatrick   if (UpdateValueIfNeeded(true)) {
1060061da546Spatrick     lldb::TypeFormatImplSP format_sp;
1061061da546Spatrick     lldb::Format my_format = GetFormat();
1062061da546Spatrick     if (my_format == lldb::eFormatDefault) {
1063061da546Spatrick       if (m_type_format_sp)
1064061da546Spatrick         format_sp = m_type_format_sp;
1065061da546Spatrick       else {
1066be691f3bSpatrick         if (m_flags.m_is_bitfield_for_scalar)
1067061da546Spatrick           my_format = eFormatUnsigned;
1068061da546Spatrick         else {
1069be691f3bSpatrick           if (m_value.GetContextType() == Value::ContextType::RegisterInfo) {
1070061da546Spatrick             const RegisterInfo *reg_info = m_value.GetRegisterInfo();
1071061da546Spatrick             if (reg_info)
1072061da546Spatrick               my_format = reg_info->format;
1073061da546Spatrick           } else {
1074061da546Spatrick             my_format = GetValue().GetCompilerType().GetFormat();
1075061da546Spatrick           }
1076061da546Spatrick         }
1077061da546Spatrick       }
1078061da546Spatrick     }
1079061da546Spatrick     if (my_format != m_last_format || m_value_str.empty()) {
1080061da546Spatrick       m_last_format = my_format;
1081061da546Spatrick       if (!format_sp)
1082061da546Spatrick         format_sp = std::make_shared<TypeFormatImpl_Format>(my_format);
1083061da546Spatrick       if (GetValueAsCString(*format_sp.get(), m_value_str)) {
1084be691f3bSpatrick         if (!m_flags.m_value_did_change && m_flags.m_old_value_valid) {
1085061da546Spatrick           // The value was gotten successfully, so we consider the value as
1086061da546Spatrick           // changed if the value string differs
1087061da546Spatrick           SetValueDidChange(m_old_value_str != m_value_str);
1088061da546Spatrick         }
1089061da546Spatrick       }
1090061da546Spatrick     }
1091061da546Spatrick   }
1092061da546Spatrick   if (m_value_str.empty())
1093061da546Spatrick     return nullptr;
1094061da546Spatrick   return m_value_str.c_str();
1095061da546Spatrick }
1096061da546Spatrick 
1097061da546Spatrick // if > 8bytes, 0 is returned. this method should mostly be used to read
1098061da546Spatrick // address values out of pointers
GetValueAsUnsigned(uint64_t fail_value,bool * success)1099061da546Spatrick uint64_t ValueObject::GetValueAsUnsigned(uint64_t fail_value, bool *success) {
1100061da546Spatrick   // If our byte size is zero this is an aggregate type that has children
1101061da546Spatrick   if (CanProvideValue()) {
1102061da546Spatrick     Scalar scalar;
1103061da546Spatrick     if (ResolveValue(scalar)) {
1104061da546Spatrick       if (success)
1105061da546Spatrick         *success = true;
1106dda28197Spatrick       scalar.MakeUnsigned();
1107061da546Spatrick       return scalar.ULongLong(fail_value);
1108061da546Spatrick     }
1109061da546Spatrick     // fallthrough, otherwise...
1110061da546Spatrick   }
1111061da546Spatrick 
1112061da546Spatrick   if (success)
1113061da546Spatrick     *success = false;
1114061da546Spatrick   return fail_value;
1115061da546Spatrick }
1116061da546Spatrick 
GetValueAsSigned(int64_t fail_value,bool * success)1117061da546Spatrick int64_t ValueObject::GetValueAsSigned(int64_t fail_value, bool *success) {
1118061da546Spatrick   // If our byte size is zero this is an aggregate type that has children
1119061da546Spatrick   if (CanProvideValue()) {
1120061da546Spatrick     Scalar scalar;
1121061da546Spatrick     if (ResolveValue(scalar)) {
1122061da546Spatrick       if (success)
1123061da546Spatrick         *success = true;
1124dda28197Spatrick       scalar.MakeSigned();
1125061da546Spatrick       return scalar.SLongLong(fail_value);
1126061da546Spatrick     }
1127061da546Spatrick     // fallthrough, otherwise...
1128061da546Spatrick   }
1129061da546Spatrick 
1130061da546Spatrick   if (success)
1131061da546Spatrick     *success = false;
1132061da546Spatrick   return fail_value;
1133061da546Spatrick }
1134061da546Spatrick 
1135061da546Spatrick // if any more "special cases" are added to
1136061da546Spatrick // ValueObject::DumpPrintableRepresentation() please keep this call up to date
1137061da546Spatrick // by returning true for your new special cases. We will eventually move to
1138061da546Spatrick // checking this call result before trying to display special cases
HasSpecialPrintableRepresentation(ValueObjectRepresentationStyle val_obj_display,Format custom_format)1139061da546Spatrick bool ValueObject::HasSpecialPrintableRepresentation(
1140061da546Spatrick     ValueObjectRepresentationStyle val_obj_display, Format custom_format) {
1141061da546Spatrick   Flags flags(GetTypeInfo());
1142061da546Spatrick   if (flags.AnySet(eTypeIsArray | eTypeIsPointer) &&
1143061da546Spatrick       val_obj_display == ValueObject::eValueObjectRepresentationStyleValue) {
1144061da546Spatrick     if (IsCStringContainer(true) &&
1145061da546Spatrick         (custom_format == eFormatCString || custom_format == eFormatCharArray ||
1146061da546Spatrick          custom_format == eFormatChar || custom_format == eFormatVectorOfChar))
1147061da546Spatrick       return true;
1148061da546Spatrick 
1149061da546Spatrick     if (flags.Test(eTypeIsArray)) {
1150061da546Spatrick       if ((custom_format == eFormatBytes) ||
1151061da546Spatrick           (custom_format == eFormatBytesWithASCII))
1152061da546Spatrick         return true;
1153061da546Spatrick 
1154061da546Spatrick       if ((custom_format == eFormatVectorOfChar) ||
1155061da546Spatrick           (custom_format == eFormatVectorOfFloat32) ||
1156061da546Spatrick           (custom_format == eFormatVectorOfFloat64) ||
1157061da546Spatrick           (custom_format == eFormatVectorOfSInt16) ||
1158061da546Spatrick           (custom_format == eFormatVectorOfSInt32) ||
1159061da546Spatrick           (custom_format == eFormatVectorOfSInt64) ||
1160061da546Spatrick           (custom_format == eFormatVectorOfSInt8) ||
1161061da546Spatrick           (custom_format == eFormatVectorOfUInt128) ||
1162061da546Spatrick           (custom_format == eFormatVectorOfUInt16) ||
1163061da546Spatrick           (custom_format == eFormatVectorOfUInt32) ||
1164061da546Spatrick           (custom_format == eFormatVectorOfUInt64) ||
1165061da546Spatrick           (custom_format == eFormatVectorOfUInt8))
1166061da546Spatrick         return true;
1167061da546Spatrick     }
1168061da546Spatrick   }
1169061da546Spatrick   return false;
1170061da546Spatrick }
1171061da546Spatrick 
DumpPrintableRepresentation(Stream & s,ValueObjectRepresentationStyle val_obj_display,Format custom_format,PrintableRepresentationSpecialCases special,bool do_dump_error)1172061da546Spatrick bool ValueObject::DumpPrintableRepresentation(
1173061da546Spatrick     Stream &s, ValueObjectRepresentationStyle val_obj_display,
1174061da546Spatrick     Format custom_format, PrintableRepresentationSpecialCases special,
1175061da546Spatrick     bool do_dump_error) {
1176061da546Spatrick 
1177061da546Spatrick   Flags flags(GetTypeInfo());
1178061da546Spatrick 
1179061da546Spatrick   bool allow_special =
1180061da546Spatrick       (special == ValueObject::PrintableRepresentationSpecialCases::eAllow);
1181061da546Spatrick   const bool only_special = false;
1182061da546Spatrick 
1183061da546Spatrick   if (allow_special) {
1184061da546Spatrick     if (flags.AnySet(eTypeIsArray | eTypeIsPointer) &&
1185061da546Spatrick         val_obj_display == ValueObject::eValueObjectRepresentationStyleValue) {
1186061da546Spatrick       // when being asked to get a printable display an array or pointer type
1187061da546Spatrick       // directly, try to "do the right thing"
1188061da546Spatrick 
1189061da546Spatrick       if (IsCStringContainer(true) &&
1190061da546Spatrick           (custom_format == eFormatCString ||
1191061da546Spatrick            custom_format == eFormatCharArray || custom_format == eFormatChar ||
1192061da546Spatrick            custom_format ==
1193061da546Spatrick                eFormatVectorOfChar)) // print char[] & char* directly
1194061da546Spatrick       {
1195061da546Spatrick         Status error;
1196*f6aab3d8Srobert         lldb::WritableDataBufferSP buffer_sp;
1197061da546Spatrick         std::pair<size_t, bool> read_string = ReadPointedString(
1198061da546Spatrick             buffer_sp, error, 0, (custom_format == eFormatVectorOfChar) ||
1199061da546Spatrick                                      (custom_format == eFormatCharArray));
1200061da546Spatrick         lldb_private::formatters::StringPrinter::
1201061da546Spatrick             ReadBufferAndDumpToStreamOptions options(*this);
1202061da546Spatrick         options.SetData(DataExtractor(
1203061da546Spatrick             buffer_sp, lldb::eByteOrderInvalid,
1204061da546Spatrick             8)); // none of this matters for a string - pass some defaults
1205061da546Spatrick         options.SetStream(&s);
1206061da546Spatrick         options.SetPrefixToken(nullptr);
1207061da546Spatrick         options.SetQuote('"');
1208061da546Spatrick         options.SetSourceSize(buffer_sp->GetByteSize());
1209061da546Spatrick         options.SetIsTruncated(read_string.second);
1210*f6aab3d8Srobert         options.SetBinaryZeroIsTerminator(custom_format != eFormatVectorOfChar);
1211061da546Spatrick         formatters::StringPrinter::ReadBufferAndDumpToStream<
1212061da546Spatrick             lldb_private::formatters::StringPrinter::StringElementType::ASCII>(
1213061da546Spatrick             options);
1214061da546Spatrick         return !error.Fail();
1215061da546Spatrick       }
1216061da546Spatrick 
1217061da546Spatrick       if (custom_format == eFormatEnum)
1218061da546Spatrick         return false;
1219061da546Spatrick 
1220061da546Spatrick       // this only works for arrays, because I have no way to know when the
1221061da546Spatrick       // pointed memory ends, and no special \0 end of data marker
1222061da546Spatrick       if (flags.Test(eTypeIsArray)) {
1223061da546Spatrick         if ((custom_format == eFormatBytes) ||
1224061da546Spatrick             (custom_format == eFormatBytesWithASCII)) {
1225061da546Spatrick           const size_t count = GetNumChildren();
1226061da546Spatrick 
1227061da546Spatrick           s << '[';
1228061da546Spatrick           for (size_t low = 0; low < count; low++) {
1229061da546Spatrick 
1230061da546Spatrick             if (low)
1231061da546Spatrick               s << ',';
1232061da546Spatrick 
1233061da546Spatrick             ValueObjectSP child = GetChildAtIndex(low, true);
1234061da546Spatrick             if (!child.get()) {
1235061da546Spatrick               s << "<invalid child>";
1236061da546Spatrick               continue;
1237061da546Spatrick             }
1238061da546Spatrick             child->DumpPrintableRepresentation(
1239061da546Spatrick                 s, ValueObject::eValueObjectRepresentationStyleValue,
1240061da546Spatrick                 custom_format);
1241061da546Spatrick           }
1242061da546Spatrick 
1243061da546Spatrick           s << ']';
1244061da546Spatrick 
1245061da546Spatrick           return true;
1246061da546Spatrick         }
1247061da546Spatrick 
1248061da546Spatrick         if ((custom_format == eFormatVectorOfChar) ||
1249061da546Spatrick             (custom_format == eFormatVectorOfFloat32) ||
1250061da546Spatrick             (custom_format == eFormatVectorOfFloat64) ||
1251061da546Spatrick             (custom_format == eFormatVectorOfSInt16) ||
1252061da546Spatrick             (custom_format == eFormatVectorOfSInt32) ||
1253061da546Spatrick             (custom_format == eFormatVectorOfSInt64) ||
1254061da546Spatrick             (custom_format == eFormatVectorOfSInt8) ||
1255061da546Spatrick             (custom_format == eFormatVectorOfUInt128) ||
1256061da546Spatrick             (custom_format == eFormatVectorOfUInt16) ||
1257061da546Spatrick             (custom_format == eFormatVectorOfUInt32) ||
1258061da546Spatrick             (custom_format == eFormatVectorOfUInt64) ||
1259061da546Spatrick             (custom_format == eFormatVectorOfUInt8)) // arrays of bytes, bytes
1260061da546Spatrick                                                      // with ASCII or any vector
1261061da546Spatrick                                                      // format should be printed
1262061da546Spatrick                                                      // directly
1263061da546Spatrick         {
1264061da546Spatrick           const size_t count = GetNumChildren();
1265061da546Spatrick 
1266061da546Spatrick           Format format = FormatManager::GetSingleItemFormat(custom_format);
1267061da546Spatrick 
1268061da546Spatrick           s << '[';
1269061da546Spatrick           for (size_t low = 0; low < count; low++) {
1270061da546Spatrick 
1271061da546Spatrick             if (low)
1272061da546Spatrick               s << ',';
1273061da546Spatrick 
1274061da546Spatrick             ValueObjectSP child = GetChildAtIndex(low, true);
1275061da546Spatrick             if (!child.get()) {
1276061da546Spatrick               s << "<invalid child>";
1277061da546Spatrick               continue;
1278061da546Spatrick             }
1279061da546Spatrick             child->DumpPrintableRepresentation(
1280061da546Spatrick                 s, ValueObject::eValueObjectRepresentationStyleValue, format);
1281061da546Spatrick           }
1282061da546Spatrick 
1283061da546Spatrick           s << ']';
1284061da546Spatrick 
1285061da546Spatrick           return true;
1286061da546Spatrick         }
1287061da546Spatrick       }
1288061da546Spatrick 
1289061da546Spatrick       if ((custom_format == eFormatBoolean) ||
1290061da546Spatrick           (custom_format == eFormatBinary) || (custom_format == eFormatChar) ||
1291061da546Spatrick           (custom_format == eFormatCharPrintable) ||
1292061da546Spatrick           (custom_format == eFormatComplexFloat) ||
1293061da546Spatrick           (custom_format == eFormatDecimal) || (custom_format == eFormatHex) ||
1294061da546Spatrick           (custom_format == eFormatHexUppercase) ||
1295061da546Spatrick           (custom_format == eFormatFloat) || (custom_format == eFormatOctal) ||
1296061da546Spatrick           (custom_format == eFormatOSType) ||
1297061da546Spatrick           (custom_format == eFormatUnicode16) ||
1298061da546Spatrick           (custom_format == eFormatUnicode32) ||
1299061da546Spatrick           (custom_format == eFormatUnsigned) ||
1300061da546Spatrick           (custom_format == eFormatPointer) ||
1301061da546Spatrick           (custom_format == eFormatComplexInteger) ||
1302061da546Spatrick           (custom_format == eFormatComplex) ||
1303061da546Spatrick           (custom_format == eFormatDefault)) // use the [] operator
1304061da546Spatrick         return false;
1305061da546Spatrick     }
1306061da546Spatrick   }
1307061da546Spatrick 
1308061da546Spatrick   if (only_special)
1309061da546Spatrick     return false;
1310061da546Spatrick 
1311061da546Spatrick   bool var_success = false;
1312061da546Spatrick 
1313061da546Spatrick   {
1314061da546Spatrick     llvm::StringRef str;
1315061da546Spatrick 
1316061da546Spatrick     // this is a local stream that we are using to ensure that the data pointed
1317061da546Spatrick     // to by cstr survives long enough for us to copy it to its destination -
1318061da546Spatrick     // it is necessary to have this temporary storage area for cases where our
1319061da546Spatrick     // desired output is not backed by some other longer-term storage
1320061da546Spatrick     StreamString strm;
1321061da546Spatrick 
1322061da546Spatrick     if (custom_format != eFormatInvalid)
1323061da546Spatrick       SetFormat(custom_format);
1324061da546Spatrick 
1325061da546Spatrick     switch (val_obj_display) {
1326061da546Spatrick     case eValueObjectRepresentationStyleValue:
1327061da546Spatrick       str = GetValueAsCString();
1328061da546Spatrick       break;
1329061da546Spatrick 
1330061da546Spatrick     case eValueObjectRepresentationStyleSummary:
1331061da546Spatrick       str = GetSummaryAsCString();
1332061da546Spatrick       break;
1333061da546Spatrick 
1334061da546Spatrick     case eValueObjectRepresentationStyleLanguageSpecific:
1335061da546Spatrick       str = GetObjectDescription();
1336061da546Spatrick       break;
1337061da546Spatrick 
1338061da546Spatrick     case eValueObjectRepresentationStyleLocation:
1339061da546Spatrick       str = GetLocationAsCString();
1340061da546Spatrick       break;
1341061da546Spatrick 
1342061da546Spatrick     case eValueObjectRepresentationStyleChildrenCount:
1343061da546Spatrick       strm.Printf("%" PRIu64 "", (uint64_t)GetNumChildren());
1344061da546Spatrick       str = strm.GetString();
1345061da546Spatrick       break;
1346061da546Spatrick 
1347061da546Spatrick     case eValueObjectRepresentationStyleType:
1348061da546Spatrick       str = GetTypeName().GetStringRef();
1349061da546Spatrick       break;
1350061da546Spatrick 
1351061da546Spatrick     case eValueObjectRepresentationStyleName:
1352061da546Spatrick       str = GetName().GetStringRef();
1353061da546Spatrick       break;
1354061da546Spatrick 
1355061da546Spatrick     case eValueObjectRepresentationStyleExpressionPath:
1356dda28197Spatrick       GetExpressionPath(strm);
1357061da546Spatrick       str = strm.GetString();
1358061da546Spatrick       break;
1359061da546Spatrick     }
1360061da546Spatrick 
1361061da546Spatrick     if (str.empty()) {
1362061da546Spatrick       if (val_obj_display == eValueObjectRepresentationStyleValue)
1363061da546Spatrick         str = GetSummaryAsCString();
1364061da546Spatrick       else if (val_obj_display == eValueObjectRepresentationStyleSummary) {
1365061da546Spatrick         if (!CanProvideValue()) {
1366061da546Spatrick           strm.Printf("%s @ %s", GetTypeName().AsCString(),
1367061da546Spatrick                       GetLocationAsCString());
1368061da546Spatrick           str = strm.GetString();
1369061da546Spatrick         } else
1370061da546Spatrick           str = GetValueAsCString();
1371061da546Spatrick       }
1372061da546Spatrick     }
1373061da546Spatrick 
1374061da546Spatrick     if (!str.empty())
1375061da546Spatrick       s << str;
1376061da546Spatrick     else {
1377061da546Spatrick       if (m_error.Fail()) {
1378061da546Spatrick         if (do_dump_error)
1379061da546Spatrick           s.Printf("<%s>", m_error.AsCString());
1380061da546Spatrick         else
1381061da546Spatrick           return false;
1382061da546Spatrick       } else if (val_obj_display == eValueObjectRepresentationStyleSummary)
1383061da546Spatrick         s.PutCString("<no summary available>");
1384061da546Spatrick       else if (val_obj_display == eValueObjectRepresentationStyleValue)
1385061da546Spatrick         s.PutCString("<no value available>");
1386061da546Spatrick       else if (val_obj_display ==
1387061da546Spatrick                eValueObjectRepresentationStyleLanguageSpecific)
1388061da546Spatrick         s.PutCString("<not a valid Objective-C object>"); // edit this if we
1389061da546Spatrick                                                           // have other runtimes
1390061da546Spatrick                                                           // that support a
1391061da546Spatrick                                                           // description
1392061da546Spatrick       else
1393061da546Spatrick         s.PutCString("<no printable representation>");
1394061da546Spatrick     }
1395061da546Spatrick 
1396061da546Spatrick     // we should only return false here if we could not do *anything* even if
1397061da546Spatrick     // we have an error message as output, that's a success from our callers'
1398061da546Spatrick     // perspective, so return true
1399061da546Spatrick     var_success = true;
1400061da546Spatrick 
1401061da546Spatrick     if (custom_format != eFormatInvalid)
1402061da546Spatrick       SetFormat(eFormatDefault);
1403061da546Spatrick   }
1404061da546Spatrick 
1405061da546Spatrick   return var_success;
1406061da546Spatrick }
1407061da546Spatrick 
GetAddressOf(bool scalar_is_load_address,AddressType * address_type)1408061da546Spatrick addr_t ValueObject::GetAddressOf(bool scalar_is_load_address,
1409061da546Spatrick                                  AddressType *address_type) {
1410061da546Spatrick   // Can't take address of a bitfield
1411061da546Spatrick   if (IsBitfield())
1412061da546Spatrick     return LLDB_INVALID_ADDRESS;
1413061da546Spatrick 
1414061da546Spatrick   if (!UpdateValueIfNeeded(false))
1415061da546Spatrick     return LLDB_INVALID_ADDRESS;
1416061da546Spatrick 
1417061da546Spatrick   switch (m_value.GetValueType()) {
1418be691f3bSpatrick   case Value::ValueType::Invalid:
1419be691f3bSpatrick     return LLDB_INVALID_ADDRESS;
1420be691f3bSpatrick   case Value::ValueType::Scalar:
1421061da546Spatrick     if (scalar_is_load_address) {
1422061da546Spatrick       if (address_type)
1423061da546Spatrick         *address_type = eAddressTypeLoad;
1424061da546Spatrick       return m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
1425061da546Spatrick     }
1426061da546Spatrick     break;
1427061da546Spatrick 
1428be691f3bSpatrick   case Value::ValueType::LoadAddress:
1429be691f3bSpatrick   case Value::ValueType::FileAddress: {
1430061da546Spatrick     if (address_type)
1431061da546Spatrick       *address_type = m_value.GetValueAddressType();
1432061da546Spatrick     return m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
1433061da546Spatrick   } break;
1434be691f3bSpatrick   case Value::ValueType::HostAddress: {
1435061da546Spatrick     if (address_type)
1436061da546Spatrick       *address_type = m_value.GetValueAddressType();
1437061da546Spatrick     return LLDB_INVALID_ADDRESS;
1438061da546Spatrick   } break;
1439061da546Spatrick   }
1440061da546Spatrick   if (address_type)
1441061da546Spatrick     *address_type = eAddressTypeInvalid;
1442061da546Spatrick   return LLDB_INVALID_ADDRESS;
1443061da546Spatrick }
1444061da546Spatrick 
GetPointerValue(AddressType * address_type)1445061da546Spatrick addr_t ValueObject::GetPointerValue(AddressType *address_type) {
1446061da546Spatrick   addr_t address = LLDB_INVALID_ADDRESS;
1447061da546Spatrick   if (address_type)
1448061da546Spatrick     *address_type = eAddressTypeInvalid;
1449061da546Spatrick 
1450061da546Spatrick   if (!UpdateValueIfNeeded(false))
1451061da546Spatrick     return address;
1452061da546Spatrick 
1453061da546Spatrick   switch (m_value.GetValueType()) {
1454be691f3bSpatrick   case Value::ValueType::Invalid:
1455be691f3bSpatrick     return LLDB_INVALID_ADDRESS;
1456be691f3bSpatrick   case Value::ValueType::Scalar:
1457061da546Spatrick     address = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
1458061da546Spatrick     break;
1459061da546Spatrick 
1460be691f3bSpatrick   case Value::ValueType::HostAddress:
1461be691f3bSpatrick   case Value::ValueType::LoadAddress:
1462be691f3bSpatrick   case Value::ValueType::FileAddress: {
1463061da546Spatrick     lldb::offset_t data_offset = 0;
1464dda28197Spatrick     address = m_data.GetAddress(&data_offset);
1465061da546Spatrick   } break;
1466061da546Spatrick   }
1467061da546Spatrick 
1468061da546Spatrick   if (address_type)
1469061da546Spatrick     *address_type = GetAddressTypeOfChildren();
1470061da546Spatrick 
1471061da546Spatrick   return address;
1472061da546Spatrick }
1473061da546Spatrick 
SetValueFromCString(const char * value_str,Status & error)1474061da546Spatrick bool ValueObject::SetValueFromCString(const char *value_str, Status &error) {
1475061da546Spatrick   error.Clear();
1476061da546Spatrick   // Make sure our value is up to date first so that our location and location
1477061da546Spatrick   // type is valid.
1478061da546Spatrick   if (!UpdateValueIfNeeded(false)) {
1479061da546Spatrick     error.SetErrorString("unable to read value");
1480061da546Spatrick     return false;
1481061da546Spatrick   }
1482061da546Spatrick 
1483061da546Spatrick   uint64_t count = 0;
1484061da546Spatrick   const Encoding encoding = GetCompilerType().GetEncoding(count);
1485061da546Spatrick 
1486*f6aab3d8Srobert   const size_t byte_size = GetByteSize().value_or(0);
1487061da546Spatrick 
1488061da546Spatrick   Value::ValueType value_type = m_value.GetValueType();
1489061da546Spatrick 
1490be691f3bSpatrick   if (value_type == Value::ValueType::Scalar) {
1491061da546Spatrick     // If the value is already a scalar, then let the scalar change itself:
1492061da546Spatrick     m_value.GetScalar().SetValueFromCString(value_str, encoding, byte_size);
1493061da546Spatrick   } else if (byte_size <= 16) {
1494061da546Spatrick     // If the value fits in a scalar, then make a new scalar and again let the
1495061da546Spatrick     // scalar code do the conversion, then figure out where to put the new
1496061da546Spatrick     // value.
1497061da546Spatrick     Scalar new_scalar;
1498061da546Spatrick     error = new_scalar.SetValueFromCString(value_str, encoding, byte_size);
1499061da546Spatrick     if (error.Success()) {
1500061da546Spatrick       switch (value_type) {
1501be691f3bSpatrick       case Value::ValueType::LoadAddress: {
1502061da546Spatrick         // If it is a load address, then the scalar value is the storage
1503061da546Spatrick         // location of the data, and we have to shove this value down to that
1504061da546Spatrick         // load location.
1505061da546Spatrick         ExecutionContext exe_ctx(GetExecutionContextRef());
1506061da546Spatrick         Process *process = exe_ctx.GetProcessPtr();
1507061da546Spatrick         if (process) {
1508061da546Spatrick           addr_t target_addr =
1509061da546Spatrick               m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
1510061da546Spatrick           size_t bytes_written = process->WriteScalarToMemory(
1511061da546Spatrick               target_addr, new_scalar, byte_size, error);
1512061da546Spatrick           if (!error.Success())
1513061da546Spatrick             return false;
1514061da546Spatrick           if (bytes_written != byte_size) {
1515061da546Spatrick             error.SetErrorString("unable to write value to memory");
1516061da546Spatrick             return false;
1517061da546Spatrick           }
1518061da546Spatrick         }
1519061da546Spatrick       } break;
1520be691f3bSpatrick       case Value::ValueType::HostAddress: {
1521061da546Spatrick         // If it is a host address, then we stuff the scalar as a DataBuffer
1522061da546Spatrick         // into the Value's data.
1523061da546Spatrick         DataExtractor new_data;
1524061da546Spatrick         new_data.SetByteOrder(m_data.GetByteOrder());
1525061da546Spatrick 
1526061da546Spatrick         DataBufferSP buffer_sp(new DataBufferHeap(byte_size, 0));
1527061da546Spatrick         m_data.SetData(buffer_sp, 0);
1528061da546Spatrick         bool success = new_scalar.GetData(new_data);
1529061da546Spatrick         if (success) {
1530061da546Spatrick           new_data.CopyByteOrderedData(
1531061da546Spatrick               0, byte_size, const_cast<uint8_t *>(m_data.GetDataStart()),
1532061da546Spatrick               byte_size, m_data.GetByteOrder());
1533061da546Spatrick         }
1534061da546Spatrick         m_value.GetScalar() = (uintptr_t)m_data.GetDataStart();
1535061da546Spatrick 
1536061da546Spatrick       } break;
1537be691f3bSpatrick       case Value::ValueType::Invalid:
1538be691f3bSpatrick         error.SetErrorString("invalid location");
1539be691f3bSpatrick         return false;
1540be691f3bSpatrick       case Value::ValueType::FileAddress:
1541be691f3bSpatrick       case Value::ValueType::Scalar:
1542061da546Spatrick         break;
1543061da546Spatrick       }
1544061da546Spatrick     } else {
1545061da546Spatrick       return false;
1546061da546Spatrick     }
1547061da546Spatrick   } else {
1548061da546Spatrick     // We don't support setting things bigger than a scalar at present.
1549061da546Spatrick     error.SetErrorString("unable to write aggregate data type");
1550061da546Spatrick     return false;
1551061da546Spatrick   }
1552061da546Spatrick 
1553061da546Spatrick   // If we have reached this point, then we have successfully changed the
1554061da546Spatrick   // value.
1555061da546Spatrick   SetNeedsUpdate();
1556061da546Spatrick   return true;
1557061da546Spatrick }
1558061da546Spatrick 
GetDeclaration(Declaration & decl)1559061da546Spatrick bool ValueObject::GetDeclaration(Declaration &decl) {
1560061da546Spatrick   decl.Clear();
1561061da546Spatrick   return false;
1562061da546Spatrick }
1563061da546Spatrick 
AddSyntheticChild(ConstString key,ValueObject * valobj)1564061da546Spatrick void ValueObject::AddSyntheticChild(ConstString key,
1565061da546Spatrick                                     ValueObject *valobj) {
1566061da546Spatrick   m_synthetic_children[key] = valobj;
1567061da546Spatrick }
1568061da546Spatrick 
GetSyntheticChild(ConstString key) const1569061da546Spatrick ValueObjectSP ValueObject::GetSyntheticChild(ConstString key) const {
1570061da546Spatrick   ValueObjectSP synthetic_child_sp;
1571061da546Spatrick   std::map<ConstString, ValueObject *>::const_iterator pos =
1572061da546Spatrick       m_synthetic_children.find(key);
1573061da546Spatrick   if (pos != m_synthetic_children.end())
1574061da546Spatrick     synthetic_child_sp = pos->second->GetSP();
1575061da546Spatrick   return synthetic_child_sp;
1576061da546Spatrick }
1577061da546Spatrick 
IsPossibleDynamicType()1578061da546Spatrick bool ValueObject::IsPossibleDynamicType() {
1579061da546Spatrick   ExecutionContext exe_ctx(GetExecutionContextRef());
1580061da546Spatrick   Process *process = exe_ctx.GetProcessPtr();
1581061da546Spatrick   if (process)
1582061da546Spatrick     return process->IsPossibleDynamicValue(*this);
1583061da546Spatrick   else
1584061da546Spatrick     return GetCompilerType().IsPossibleDynamicType(nullptr, true, true);
1585061da546Spatrick }
1586061da546Spatrick 
IsRuntimeSupportValue()1587061da546Spatrick bool ValueObject::IsRuntimeSupportValue() {
1588061da546Spatrick   Process *process(GetProcessSP().get());
1589061da546Spatrick   if (!process)
1590061da546Spatrick     return false;
1591061da546Spatrick 
1592be691f3bSpatrick   // We trust that the compiler did the right thing and marked runtime support
1593061da546Spatrick   // values as artificial.
1594061da546Spatrick   if (!GetVariable() || !GetVariable()->IsArtificial())
1595061da546Spatrick     return false;
1596061da546Spatrick 
1597061da546Spatrick   if (auto *runtime = process->GetLanguageRuntime(GetVariable()->GetLanguage()))
1598dda28197Spatrick     if (runtime->IsAllowedRuntimeValue(GetName()))
1599061da546Spatrick       return false;
1600061da546Spatrick 
1601061da546Spatrick   return true;
1602061da546Spatrick }
1603061da546Spatrick 
IsNilReference()1604061da546Spatrick bool ValueObject::IsNilReference() {
1605061da546Spatrick   if (Language *language = Language::FindPlugin(GetObjectRuntimeLanguage())) {
1606061da546Spatrick     return language->IsNilReference(*this);
1607061da546Spatrick   }
1608061da546Spatrick   return false;
1609061da546Spatrick }
1610061da546Spatrick 
IsUninitializedReference()1611061da546Spatrick bool ValueObject::IsUninitializedReference() {
1612061da546Spatrick   if (Language *language = Language::FindPlugin(GetObjectRuntimeLanguage())) {
1613061da546Spatrick     return language->IsUninitializedReference(*this);
1614061da546Spatrick   }
1615061da546Spatrick   return false;
1616061da546Spatrick }
1617061da546Spatrick 
1618061da546Spatrick // This allows you to create an array member using and index that doesn't not
1619061da546Spatrick // fall in the normal bounds of the array. Many times structure can be defined
1620061da546Spatrick // as: struct Collection {
1621061da546Spatrick //     uint32_t item_count;
1622061da546Spatrick //     Item item_array[0];
1623061da546Spatrick // };
1624061da546Spatrick // The size of the "item_array" is 1, but many times in practice there are more
1625061da546Spatrick // items in "item_array".
1626061da546Spatrick 
GetSyntheticArrayMember(size_t index,bool can_create)1627061da546Spatrick ValueObjectSP ValueObject::GetSyntheticArrayMember(size_t index,
1628061da546Spatrick                                                    bool can_create) {
1629061da546Spatrick   ValueObjectSP synthetic_child_sp;
1630061da546Spatrick   if (IsPointerType() || IsArrayType()) {
1631be691f3bSpatrick     std::string index_str = llvm::formatv("[{0}]", index);
1632061da546Spatrick     ConstString index_const_str(index_str);
1633061da546Spatrick     // Check if we have already created a synthetic array member in this valid
1634061da546Spatrick     // object. If we have we will re-use it.
1635061da546Spatrick     synthetic_child_sp = GetSyntheticChild(index_const_str);
1636061da546Spatrick     if (!synthetic_child_sp) {
1637061da546Spatrick       ValueObject *synthetic_child;
1638061da546Spatrick       // We haven't made a synthetic array member for INDEX yet, so lets make
1639061da546Spatrick       // one and cache it for any future reference.
1640061da546Spatrick       synthetic_child = CreateChildAtIndex(0, true, index);
1641061da546Spatrick 
1642061da546Spatrick       // Cache the value if we got one back...
1643061da546Spatrick       if (synthetic_child) {
1644061da546Spatrick         AddSyntheticChild(index_const_str, synthetic_child);
1645061da546Spatrick         synthetic_child_sp = synthetic_child->GetSP();
1646061da546Spatrick         synthetic_child_sp->SetName(ConstString(index_str));
1647be691f3bSpatrick         synthetic_child_sp->m_flags.m_is_array_item_for_pointer = true;
1648061da546Spatrick       }
1649061da546Spatrick     }
1650061da546Spatrick   }
1651061da546Spatrick   return synthetic_child_sp;
1652061da546Spatrick }
1653061da546Spatrick 
GetSyntheticBitFieldChild(uint32_t from,uint32_t to,bool can_create)1654061da546Spatrick ValueObjectSP ValueObject::GetSyntheticBitFieldChild(uint32_t from, uint32_t to,
1655061da546Spatrick                                                      bool can_create) {
1656061da546Spatrick   ValueObjectSP synthetic_child_sp;
1657061da546Spatrick   if (IsScalarType()) {
1658be691f3bSpatrick     std::string index_str = llvm::formatv("[{0}-{1}]", from, to);
1659061da546Spatrick     ConstString index_const_str(index_str);
1660061da546Spatrick     // Check if we have already created a synthetic array member in this valid
1661061da546Spatrick     // object. If we have we will re-use it.
1662061da546Spatrick     synthetic_child_sp = GetSyntheticChild(index_const_str);
1663061da546Spatrick     if (!synthetic_child_sp) {
1664061da546Spatrick       uint32_t bit_field_size = to - from + 1;
1665061da546Spatrick       uint32_t bit_field_offset = from;
1666061da546Spatrick       if (GetDataExtractor().GetByteOrder() == eByteOrderBig)
1667061da546Spatrick         bit_field_offset =
1668*f6aab3d8Srobert             GetByteSize().value_or(0) * 8 - bit_field_size - bit_field_offset;
1669061da546Spatrick       // We haven't made a synthetic array member for INDEX yet, so lets make
1670061da546Spatrick       // one and cache it for any future reference.
1671061da546Spatrick       ValueObjectChild *synthetic_child = new ValueObjectChild(
1672*f6aab3d8Srobert           *this, GetCompilerType(), index_const_str, GetByteSize().value_or(0),
1673*f6aab3d8Srobert           0, bit_field_size, bit_field_offset, false, false,
1674*f6aab3d8Srobert           eAddressTypeInvalid, 0);
1675061da546Spatrick 
1676061da546Spatrick       // Cache the value if we got one back...
1677061da546Spatrick       if (synthetic_child) {
1678061da546Spatrick         AddSyntheticChild(index_const_str, synthetic_child);
1679061da546Spatrick         synthetic_child_sp = synthetic_child->GetSP();
1680061da546Spatrick         synthetic_child_sp->SetName(ConstString(index_str));
1681be691f3bSpatrick         synthetic_child_sp->m_flags.m_is_bitfield_for_scalar = true;
1682061da546Spatrick       }
1683061da546Spatrick     }
1684061da546Spatrick   }
1685061da546Spatrick   return synthetic_child_sp;
1686061da546Spatrick }
1687061da546Spatrick 
GetSyntheticChildAtOffset(uint32_t offset,const CompilerType & type,bool can_create,ConstString name_const_str)1688061da546Spatrick ValueObjectSP ValueObject::GetSyntheticChildAtOffset(
1689061da546Spatrick     uint32_t offset, const CompilerType &type, bool can_create,
1690061da546Spatrick     ConstString name_const_str) {
1691061da546Spatrick 
1692061da546Spatrick   ValueObjectSP synthetic_child_sp;
1693061da546Spatrick 
1694061da546Spatrick   if (name_const_str.IsEmpty()) {
1695be691f3bSpatrick     name_const_str.SetString("@" + std::to_string(offset));
1696061da546Spatrick   }
1697061da546Spatrick 
1698061da546Spatrick   // Check if we have already created a synthetic array member in this valid
1699061da546Spatrick   // object. If we have we will re-use it.
1700061da546Spatrick   synthetic_child_sp = GetSyntheticChild(name_const_str);
1701061da546Spatrick 
1702061da546Spatrick   if (synthetic_child_sp.get())
1703061da546Spatrick     return synthetic_child_sp;
1704061da546Spatrick 
1705061da546Spatrick   if (!can_create)
1706061da546Spatrick     return {};
1707061da546Spatrick 
1708061da546Spatrick   ExecutionContext exe_ctx(GetExecutionContextRef());
1709*f6aab3d8Srobert   std::optional<uint64_t> size =
1710061da546Spatrick       type.GetByteSize(exe_ctx.GetBestExecutionContextScope());
1711061da546Spatrick   if (!size)
1712061da546Spatrick     return {};
1713061da546Spatrick   ValueObjectChild *synthetic_child =
1714061da546Spatrick       new ValueObjectChild(*this, type, name_const_str, *size, offset, 0, 0,
1715061da546Spatrick                            false, false, eAddressTypeInvalid, 0);
1716061da546Spatrick   if (synthetic_child) {
1717061da546Spatrick     AddSyntheticChild(name_const_str, synthetic_child);
1718061da546Spatrick     synthetic_child_sp = synthetic_child->GetSP();
1719061da546Spatrick     synthetic_child_sp->SetName(name_const_str);
1720be691f3bSpatrick     synthetic_child_sp->m_flags.m_is_child_at_offset = true;
1721061da546Spatrick   }
1722061da546Spatrick   return synthetic_child_sp;
1723061da546Spatrick }
1724061da546Spatrick 
GetSyntheticBase(uint32_t offset,const CompilerType & type,bool can_create,ConstString name_const_str)1725061da546Spatrick ValueObjectSP ValueObject::GetSyntheticBase(uint32_t offset,
1726061da546Spatrick                                             const CompilerType &type,
1727061da546Spatrick                                             bool can_create,
1728061da546Spatrick                                             ConstString name_const_str) {
1729061da546Spatrick   ValueObjectSP synthetic_child_sp;
1730061da546Spatrick 
1731061da546Spatrick   if (name_const_str.IsEmpty()) {
1732061da546Spatrick     char name_str[128];
1733061da546Spatrick     snprintf(name_str, sizeof(name_str), "base%s@%i",
1734061da546Spatrick              type.GetTypeName().AsCString("<unknown>"), offset);
1735061da546Spatrick     name_const_str.SetCString(name_str);
1736061da546Spatrick   }
1737061da546Spatrick 
1738061da546Spatrick   // Check if we have already created a synthetic array member in this valid
1739061da546Spatrick   // object. If we have we will re-use it.
1740061da546Spatrick   synthetic_child_sp = GetSyntheticChild(name_const_str);
1741061da546Spatrick 
1742061da546Spatrick   if (synthetic_child_sp.get())
1743061da546Spatrick     return synthetic_child_sp;
1744061da546Spatrick 
1745061da546Spatrick   if (!can_create)
1746061da546Spatrick     return {};
1747061da546Spatrick 
1748061da546Spatrick   const bool is_base_class = true;
1749061da546Spatrick 
1750061da546Spatrick   ExecutionContext exe_ctx(GetExecutionContextRef());
1751*f6aab3d8Srobert   std::optional<uint64_t> size =
1752061da546Spatrick       type.GetByteSize(exe_ctx.GetBestExecutionContextScope());
1753061da546Spatrick   if (!size)
1754061da546Spatrick     return {};
1755061da546Spatrick   ValueObjectChild *synthetic_child =
1756061da546Spatrick       new ValueObjectChild(*this, type, name_const_str, *size, offset, 0, 0,
1757061da546Spatrick                            is_base_class, false, eAddressTypeInvalid, 0);
1758061da546Spatrick   if (synthetic_child) {
1759061da546Spatrick     AddSyntheticChild(name_const_str, synthetic_child);
1760061da546Spatrick     synthetic_child_sp = synthetic_child->GetSP();
1761061da546Spatrick     synthetic_child_sp->SetName(name_const_str);
1762061da546Spatrick   }
1763061da546Spatrick   return synthetic_child_sp;
1764061da546Spatrick }
1765061da546Spatrick 
1766061da546Spatrick // your expression path needs to have a leading . or -> (unless it somehow
1767061da546Spatrick // "looks like" an array, in which case it has a leading [ symbol). while the [
1768061da546Spatrick // is meaningful and should be shown to the user, . and -> are just parser
1769061da546Spatrick // design, but by no means added information for the user.. strip them off
SkipLeadingExpressionPathSeparators(const char * expression)1770061da546Spatrick static const char *SkipLeadingExpressionPathSeparators(const char *expression) {
1771061da546Spatrick   if (!expression || !expression[0])
1772061da546Spatrick     return expression;
1773061da546Spatrick   if (expression[0] == '.')
1774061da546Spatrick     return expression + 1;
1775061da546Spatrick   if (expression[0] == '-' && expression[1] == '>')
1776061da546Spatrick     return expression + 2;
1777061da546Spatrick   return expression;
1778061da546Spatrick }
1779061da546Spatrick 
1780061da546Spatrick ValueObjectSP
GetSyntheticExpressionPathChild(const char * expression,bool can_create)1781061da546Spatrick ValueObject::GetSyntheticExpressionPathChild(const char *expression,
1782061da546Spatrick                                              bool can_create) {
1783061da546Spatrick   ValueObjectSP synthetic_child_sp;
1784061da546Spatrick   ConstString name_const_string(expression);
1785061da546Spatrick   // Check if we have already created a synthetic array member in this valid
1786061da546Spatrick   // object. If we have we will re-use it.
1787061da546Spatrick   synthetic_child_sp = GetSyntheticChild(name_const_string);
1788061da546Spatrick   if (!synthetic_child_sp) {
1789061da546Spatrick     // We haven't made a synthetic array member for expression yet, so lets
1790061da546Spatrick     // make one and cache it for any future reference.
1791061da546Spatrick     synthetic_child_sp = GetValueForExpressionPath(
1792061da546Spatrick         expression, nullptr, nullptr,
1793061da546Spatrick         GetValueForExpressionPathOptions().SetSyntheticChildrenTraversal(
1794061da546Spatrick             GetValueForExpressionPathOptions::SyntheticChildrenTraversal::
1795061da546Spatrick                 None));
1796061da546Spatrick 
1797061da546Spatrick     // Cache the value if we got one back...
1798061da546Spatrick     if (synthetic_child_sp.get()) {
1799061da546Spatrick       // FIXME: this causes a "real" child to end up with its name changed to
1800061da546Spatrick       // the contents of expression
1801061da546Spatrick       AddSyntheticChild(name_const_string, synthetic_child_sp.get());
1802061da546Spatrick       synthetic_child_sp->SetName(
1803061da546Spatrick           ConstString(SkipLeadingExpressionPathSeparators(expression)));
1804061da546Spatrick     }
1805061da546Spatrick   }
1806061da546Spatrick   return synthetic_child_sp;
1807061da546Spatrick }
1808061da546Spatrick 
CalculateSyntheticValue()1809dda28197Spatrick void ValueObject::CalculateSyntheticValue() {
1810061da546Spatrick   TargetSP target_sp(GetTargetSP());
1811061da546Spatrick   if (target_sp && !target_sp->GetEnableSyntheticValue()) {
1812061da546Spatrick     m_synthetic_value = nullptr;
1813061da546Spatrick     return;
1814061da546Spatrick   }
1815061da546Spatrick 
1816061da546Spatrick   lldb::SyntheticChildrenSP current_synth_sp(m_synthetic_children_sp);
1817061da546Spatrick 
1818061da546Spatrick   if (!UpdateFormatsIfNeeded() && m_synthetic_value)
1819061da546Spatrick     return;
1820061da546Spatrick 
1821061da546Spatrick   if (m_synthetic_children_sp.get() == nullptr)
1822061da546Spatrick     return;
1823061da546Spatrick 
1824061da546Spatrick   if (current_synth_sp == m_synthetic_children_sp && m_synthetic_value)
1825061da546Spatrick     return;
1826061da546Spatrick 
1827061da546Spatrick   m_synthetic_value = new ValueObjectSynthetic(*this, m_synthetic_children_sp);
1828061da546Spatrick }
1829061da546Spatrick 
CalculateDynamicValue(DynamicValueType use_dynamic)1830061da546Spatrick void ValueObject::CalculateDynamicValue(DynamicValueType use_dynamic) {
1831061da546Spatrick   if (use_dynamic == eNoDynamicValues)
1832061da546Spatrick     return;
1833061da546Spatrick 
1834061da546Spatrick   if (!m_dynamic_value && !IsDynamic()) {
1835061da546Spatrick     ExecutionContext exe_ctx(GetExecutionContextRef());
1836061da546Spatrick     Process *process = exe_ctx.GetProcessPtr();
1837061da546Spatrick     if (process && process->IsPossibleDynamicValue(*this)) {
1838061da546Spatrick       ClearDynamicTypeInformation();
1839061da546Spatrick       m_dynamic_value = new ValueObjectDynamicValue(*this, use_dynamic);
1840061da546Spatrick     }
1841061da546Spatrick   }
1842061da546Spatrick }
1843061da546Spatrick 
GetDynamicValue(DynamicValueType use_dynamic)1844061da546Spatrick ValueObjectSP ValueObject::GetDynamicValue(DynamicValueType use_dynamic) {
1845061da546Spatrick   if (use_dynamic == eNoDynamicValues)
1846061da546Spatrick     return ValueObjectSP();
1847061da546Spatrick 
1848061da546Spatrick   if (!IsDynamic() && m_dynamic_value == nullptr) {
1849061da546Spatrick     CalculateDynamicValue(use_dynamic);
1850061da546Spatrick   }
1851061da546Spatrick   if (m_dynamic_value)
1852061da546Spatrick     return m_dynamic_value->GetSP();
1853061da546Spatrick   else
1854061da546Spatrick     return ValueObjectSP();
1855061da546Spatrick }
1856061da546Spatrick 
GetSyntheticValue()1857dda28197Spatrick ValueObjectSP ValueObject::GetSyntheticValue() {
1858dda28197Spatrick   CalculateSyntheticValue();
1859061da546Spatrick 
1860061da546Spatrick   if (m_synthetic_value)
1861061da546Spatrick     return m_synthetic_value->GetSP();
1862061da546Spatrick   else
1863061da546Spatrick     return ValueObjectSP();
1864061da546Spatrick }
1865061da546Spatrick 
HasSyntheticValue()1866061da546Spatrick bool ValueObject::HasSyntheticValue() {
1867061da546Spatrick   UpdateFormatsIfNeeded();
1868061da546Spatrick 
1869061da546Spatrick   if (m_synthetic_children_sp.get() == nullptr)
1870061da546Spatrick     return false;
1871061da546Spatrick 
1872dda28197Spatrick   CalculateSyntheticValue();
1873061da546Spatrick 
1874061da546Spatrick   return m_synthetic_value != nullptr;
1875061da546Spatrick }
1876061da546Spatrick 
GetNonBaseClassParent()1877061da546Spatrick ValueObject *ValueObject::GetNonBaseClassParent() {
1878061da546Spatrick   if (GetParent()) {
1879061da546Spatrick     if (GetParent()->IsBaseClass())
1880061da546Spatrick       return GetParent()->GetNonBaseClassParent();
1881061da546Spatrick     else
1882061da546Spatrick       return GetParent();
1883061da546Spatrick   }
1884061da546Spatrick   return nullptr;
1885061da546Spatrick }
1886061da546Spatrick 
IsBaseClass(uint32_t & depth)1887061da546Spatrick bool ValueObject::IsBaseClass(uint32_t &depth) {
1888061da546Spatrick   if (!IsBaseClass()) {
1889061da546Spatrick     depth = 0;
1890061da546Spatrick     return false;
1891061da546Spatrick   }
1892061da546Spatrick   if (GetParent()) {
1893061da546Spatrick     GetParent()->IsBaseClass(depth);
1894061da546Spatrick     depth = depth + 1;
1895061da546Spatrick     return true;
1896061da546Spatrick   }
1897061da546Spatrick   // TODO: a base of no parent? weird..
1898061da546Spatrick   depth = 1;
1899061da546Spatrick   return true;
1900061da546Spatrick }
1901061da546Spatrick 
GetExpressionPath(Stream & s,GetExpressionPathFormat epformat)1902dda28197Spatrick void ValueObject::GetExpressionPath(Stream &s,
1903061da546Spatrick                                     GetExpressionPathFormat epformat) {
1904061da546Spatrick   // synthetic children do not actually "exist" as part of the hierarchy, and
1905061da546Spatrick   // sometimes they are consed up in ways that don't make sense from an
1906061da546Spatrick   // underlying language/API standpoint. So, use a special code path here to
1907061da546Spatrick   // return something that can hopefully be used in expression
1908be691f3bSpatrick   if (m_flags.m_is_synthetic_children_generated) {
1909061da546Spatrick     UpdateValueIfNeeded();
1910061da546Spatrick 
1911be691f3bSpatrick     if (m_value.GetValueType() == Value::ValueType::LoadAddress) {
1912061da546Spatrick       if (IsPointerOrReferenceType()) {
1913061da546Spatrick         s.Printf("((%s)0x%" PRIx64 ")", GetTypeName().AsCString("void"),
1914061da546Spatrick                  GetValueAsUnsigned(0));
1915061da546Spatrick         return;
1916061da546Spatrick       } else {
1917061da546Spatrick         uint64_t load_addr =
1918061da546Spatrick             m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
1919061da546Spatrick         if (load_addr != LLDB_INVALID_ADDRESS) {
1920061da546Spatrick           s.Printf("(*( (%s *)0x%" PRIx64 "))", GetTypeName().AsCString("void"),
1921061da546Spatrick                    load_addr);
1922061da546Spatrick           return;
1923061da546Spatrick         }
1924061da546Spatrick       }
1925061da546Spatrick     }
1926061da546Spatrick 
1927061da546Spatrick     if (CanProvideValue()) {
1928061da546Spatrick       s.Printf("((%s)%s)", GetTypeName().AsCString("void"),
1929061da546Spatrick                GetValueAsCString());
1930061da546Spatrick       return;
1931061da546Spatrick     }
1932061da546Spatrick 
1933061da546Spatrick     return;
1934061da546Spatrick   }
1935061da546Spatrick 
1936061da546Spatrick   const bool is_deref_of_parent = IsDereferenceOfParent();
1937061da546Spatrick 
1938061da546Spatrick   if (is_deref_of_parent &&
1939061da546Spatrick       epformat == eGetExpressionPathFormatDereferencePointers) {
1940061da546Spatrick     // this is the original format of GetExpressionPath() producing code like
1941061da546Spatrick     // *(a_ptr).memberName, which is entirely fine, until you put this into
1942061da546Spatrick     // StackFrame::GetValueForVariableExpressionPath() which prefers to see
1943061da546Spatrick     // a_ptr->memberName. the eHonorPointers mode is meant to produce strings
1944061da546Spatrick     // in this latter format
1945061da546Spatrick     s.PutCString("*(");
1946061da546Spatrick   }
1947061da546Spatrick 
1948061da546Spatrick   ValueObject *parent = GetParent();
1949061da546Spatrick 
1950061da546Spatrick   if (parent)
1951dda28197Spatrick     parent->GetExpressionPath(s, epformat);
1952061da546Spatrick 
1953061da546Spatrick   // if we are a deref_of_parent just because we are synthetic array members
1954061da546Spatrick   // made up to allow ptr[%d] syntax to work in variable printing, then add our
1955061da546Spatrick   // name ([%d]) to the expression path
1956be691f3bSpatrick   if (m_flags.m_is_array_item_for_pointer &&
1957061da546Spatrick       epformat == eGetExpressionPathFormatHonorPointers)
1958dda28197Spatrick     s.PutCString(m_name.GetStringRef());
1959061da546Spatrick 
1960061da546Spatrick   if (!IsBaseClass()) {
1961061da546Spatrick     if (!is_deref_of_parent) {
1962061da546Spatrick       ValueObject *non_base_class_parent = GetNonBaseClassParent();
1963061da546Spatrick       if (non_base_class_parent &&
1964061da546Spatrick           !non_base_class_parent->GetName().IsEmpty()) {
1965061da546Spatrick         CompilerType non_base_class_parent_compiler_type =
1966061da546Spatrick             non_base_class_parent->GetCompilerType();
1967061da546Spatrick         if (non_base_class_parent_compiler_type) {
1968061da546Spatrick           if (parent && parent->IsDereferenceOfParent() &&
1969061da546Spatrick               epformat == eGetExpressionPathFormatHonorPointers) {
1970061da546Spatrick             s.PutCString("->");
1971061da546Spatrick           } else {
1972061da546Spatrick             const uint32_t non_base_class_parent_type_info =
1973061da546Spatrick                 non_base_class_parent_compiler_type.GetTypeInfo();
1974061da546Spatrick 
1975061da546Spatrick             if (non_base_class_parent_type_info & eTypeIsPointer) {
1976061da546Spatrick               s.PutCString("->");
1977061da546Spatrick             } else if ((non_base_class_parent_type_info & eTypeHasChildren) &&
1978061da546Spatrick                        !(non_base_class_parent_type_info & eTypeIsArray)) {
1979061da546Spatrick               s.PutChar('.');
1980061da546Spatrick             }
1981061da546Spatrick           }
1982061da546Spatrick         }
1983061da546Spatrick       }
1984061da546Spatrick 
1985061da546Spatrick       const char *name = GetName().GetCString();
1986dda28197Spatrick       if (name)
1987061da546Spatrick         s.PutCString(name);
1988061da546Spatrick     }
1989061da546Spatrick   }
1990061da546Spatrick 
1991061da546Spatrick   if (is_deref_of_parent &&
1992061da546Spatrick       epformat == eGetExpressionPathFormatDereferencePointers) {
1993061da546Spatrick     s.PutChar(')');
1994061da546Spatrick   }
1995061da546Spatrick }
1996061da546Spatrick 
GetValueForExpressionPath(llvm::StringRef expression,ExpressionPathScanEndReason * reason_to_stop,ExpressionPathEndResultType * final_value_type,const GetValueForExpressionPathOptions & options,ExpressionPathAftermath * final_task_on_target)1997061da546Spatrick ValueObjectSP ValueObject::GetValueForExpressionPath(
1998061da546Spatrick     llvm::StringRef expression, ExpressionPathScanEndReason *reason_to_stop,
1999061da546Spatrick     ExpressionPathEndResultType *final_value_type,
2000061da546Spatrick     const GetValueForExpressionPathOptions &options,
2001061da546Spatrick     ExpressionPathAftermath *final_task_on_target) {
2002061da546Spatrick 
2003061da546Spatrick   ExpressionPathScanEndReason dummy_reason_to_stop =
2004061da546Spatrick       ValueObject::eExpressionPathScanEndReasonUnknown;
2005061da546Spatrick   ExpressionPathEndResultType dummy_final_value_type =
2006061da546Spatrick       ValueObject::eExpressionPathEndResultTypeInvalid;
2007061da546Spatrick   ExpressionPathAftermath dummy_final_task_on_target =
2008061da546Spatrick       ValueObject::eExpressionPathAftermathNothing;
2009061da546Spatrick 
2010061da546Spatrick   ValueObjectSP ret_val = GetValueForExpressionPath_Impl(
2011061da546Spatrick       expression, reason_to_stop ? reason_to_stop : &dummy_reason_to_stop,
2012061da546Spatrick       final_value_type ? final_value_type : &dummy_final_value_type, options,
2013061da546Spatrick       final_task_on_target ? final_task_on_target
2014061da546Spatrick                            : &dummy_final_task_on_target);
2015061da546Spatrick 
2016061da546Spatrick   if (!final_task_on_target ||
2017061da546Spatrick       *final_task_on_target == ValueObject::eExpressionPathAftermathNothing)
2018061da546Spatrick     return ret_val;
2019061da546Spatrick 
2020061da546Spatrick   if (ret_val.get() &&
2021061da546Spatrick       ((final_value_type ? *final_value_type : dummy_final_value_type) ==
2022061da546Spatrick        eExpressionPathEndResultTypePlain)) // I can only deref and takeaddress
2023061da546Spatrick                                            // of plain objects
2024061da546Spatrick   {
2025061da546Spatrick     if ((final_task_on_target ? *final_task_on_target
2026061da546Spatrick                               : dummy_final_task_on_target) ==
2027061da546Spatrick         ValueObject::eExpressionPathAftermathDereference) {
2028061da546Spatrick       Status error;
2029061da546Spatrick       ValueObjectSP final_value = ret_val->Dereference(error);
2030061da546Spatrick       if (error.Fail() || !final_value.get()) {
2031061da546Spatrick         if (reason_to_stop)
2032061da546Spatrick           *reason_to_stop =
2033061da546Spatrick               ValueObject::eExpressionPathScanEndReasonDereferencingFailed;
2034061da546Spatrick         if (final_value_type)
2035061da546Spatrick           *final_value_type = ValueObject::eExpressionPathEndResultTypeInvalid;
2036061da546Spatrick         return ValueObjectSP();
2037061da546Spatrick       } else {
2038061da546Spatrick         if (final_task_on_target)
2039061da546Spatrick           *final_task_on_target = ValueObject::eExpressionPathAftermathNothing;
2040061da546Spatrick         return final_value;
2041061da546Spatrick       }
2042061da546Spatrick     }
2043061da546Spatrick     if (*final_task_on_target ==
2044061da546Spatrick         ValueObject::eExpressionPathAftermathTakeAddress) {
2045061da546Spatrick       Status error;
2046061da546Spatrick       ValueObjectSP final_value = ret_val->AddressOf(error);
2047061da546Spatrick       if (error.Fail() || !final_value.get()) {
2048061da546Spatrick         if (reason_to_stop)
2049061da546Spatrick           *reason_to_stop =
2050061da546Spatrick               ValueObject::eExpressionPathScanEndReasonTakingAddressFailed;
2051061da546Spatrick         if (final_value_type)
2052061da546Spatrick           *final_value_type = ValueObject::eExpressionPathEndResultTypeInvalid;
2053061da546Spatrick         return ValueObjectSP();
2054061da546Spatrick       } else {
2055061da546Spatrick         if (final_task_on_target)
2056061da546Spatrick           *final_task_on_target = ValueObject::eExpressionPathAftermathNothing;
2057061da546Spatrick         return final_value;
2058061da546Spatrick       }
2059061da546Spatrick     }
2060061da546Spatrick   }
2061061da546Spatrick   return ret_val; // final_task_on_target will still have its original value, so
2062061da546Spatrick                   // you know I did not do it
2063061da546Spatrick }
2064061da546Spatrick 
GetValueForExpressionPath_Impl(llvm::StringRef expression,ExpressionPathScanEndReason * reason_to_stop,ExpressionPathEndResultType * final_result,const GetValueForExpressionPathOptions & options,ExpressionPathAftermath * what_next)2065061da546Spatrick ValueObjectSP ValueObject::GetValueForExpressionPath_Impl(
2066061da546Spatrick     llvm::StringRef expression, ExpressionPathScanEndReason *reason_to_stop,
2067061da546Spatrick     ExpressionPathEndResultType *final_result,
2068061da546Spatrick     const GetValueForExpressionPathOptions &options,
2069061da546Spatrick     ExpressionPathAftermath *what_next) {
2070061da546Spatrick   ValueObjectSP root = GetSP();
2071061da546Spatrick 
2072061da546Spatrick   if (!root)
2073061da546Spatrick     return nullptr;
2074061da546Spatrick 
2075061da546Spatrick   llvm::StringRef remainder = expression;
2076061da546Spatrick 
2077061da546Spatrick   while (true) {
2078061da546Spatrick     llvm::StringRef temp_expression = remainder;
2079061da546Spatrick 
2080061da546Spatrick     CompilerType root_compiler_type = root->GetCompilerType();
2081061da546Spatrick     CompilerType pointee_compiler_type;
2082061da546Spatrick     Flags pointee_compiler_type_info;
2083061da546Spatrick 
2084061da546Spatrick     Flags root_compiler_type_info(
2085061da546Spatrick         root_compiler_type.GetTypeInfo(&pointee_compiler_type));
2086061da546Spatrick     if (pointee_compiler_type)
2087061da546Spatrick       pointee_compiler_type_info.Reset(pointee_compiler_type.GetTypeInfo());
2088061da546Spatrick 
2089061da546Spatrick     if (temp_expression.empty()) {
2090061da546Spatrick       *reason_to_stop = ValueObject::eExpressionPathScanEndReasonEndOfString;
2091061da546Spatrick       return root;
2092061da546Spatrick     }
2093061da546Spatrick 
2094061da546Spatrick     switch (temp_expression.front()) {
2095061da546Spatrick     case '-': {
2096061da546Spatrick       temp_expression = temp_expression.drop_front();
2097061da546Spatrick       if (options.m_check_dot_vs_arrow_syntax &&
2098061da546Spatrick           root_compiler_type_info.Test(eTypeIsPointer)) // if you are trying to
2099061da546Spatrick                                                         // use -> on a
2100061da546Spatrick                                                         // non-pointer and I
2101061da546Spatrick                                                         // must catch the error
2102061da546Spatrick       {
2103061da546Spatrick         *reason_to_stop =
2104061da546Spatrick             ValueObject::eExpressionPathScanEndReasonArrowInsteadOfDot;
2105061da546Spatrick         *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
2106061da546Spatrick         return ValueObjectSP();
2107061da546Spatrick       }
2108061da546Spatrick       if (root_compiler_type_info.Test(eTypeIsObjC) && // if yo are trying to
2109061da546Spatrick                                                        // extract an ObjC IVar
2110061da546Spatrick                                                        // when this is forbidden
2111061da546Spatrick           root_compiler_type_info.Test(eTypeIsPointer) &&
2112061da546Spatrick           options.m_no_fragile_ivar) {
2113061da546Spatrick         *reason_to_stop =
2114061da546Spatrick             ValueObject::eExpressionPathScanEndReasonFragileIVarNotAllowed;
2115061da546Spatrick         *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
2116061da546Spatrick         return ValueObjectSP();
2117061da546Spatrick       }
2118061da546Spatrick       if (!temp_expression.startswith(">")) {
2119061da546Spatrick         *reason_to_stop =
2120061da546Spatrick             ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol;
2121061da546Spatrick         *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
2122061da546Spatrick         return ValueObjectSP();
2123061da546Spatrick       }
2124061da546Spatrick     }
2125*f6aab3d8Srobert       [[fallthrough]];
2126061da546Spatrick     case '.': // or fallthrough from ->
2127061da546Spatrick     {
2128061da546Spatrick       if (options.m_check_dot_vs_arrow_syntax &&
2129061da546Spatrick           temp_expression.front() == '.' &&
2130061da546Spatrick           root_compiler_type_info.Test(eTypeIsPointer)) // if you are trying to
2131061da546Spatrick                                                         // use . on a pointer
2132061da546Spatrick                                                         // and I must catch the
2133061da546Spatrick                                                         // error
2134061da546Spatrick       {
2135061da546Spatrick         *reason_to_stop =
2136061da546Spatrick             ValueObject::eExpressionPathScanEndReasonDotInsteadOfArrow;
2137061da546Spatrick         *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
2138061da546Spatrick         return nullptr;
2139061da546Spatrick       }
2140061da546Spatrick       temp_expression = temp_expression.drop_front(); // skip . or >
2141061da546Spatrick 
2142061da546Spatrick       size_t next_sep_pos = temp_expression.find_first_of("-.[", 1);
2143061da546Spatrick       ConstString child_name;
2144061da546Spatrick       if (next_sep_pos == llvm::StringRef::npos) // if no other separator just
2145061da546Spatrick                                                  // expand this last layer
2146061da546Spatrick       {
2147061da546Spatrick         child_name.SetString(temp_expression);
2148061da546Spatrick         ValueObjectSP child_valobj_sp =
2149061da546Spatrick             root->GetChildMemberWithName(child_name, true);
2150061da546Spatrick 
2151061da546Spatrick         if (child_valobj_sp.get()) // we know we are done, so just return
2152061da546Spatrick         {
2153061da546Spatrick           *reason_to_stop =
2154061da546Spatrick               ValueObject::eExpressionPathScanEndReasonEndOfString;
2155061da546Spatrick           *final_result = ValueObject::eExpressionPathEndResultTypePlain;
2156061da546Spatrick           return child_valobj_sp;
2157061da546Spatrick         } else {
2158061da546Spatrick           switch (options.m_synthetic_children_traversal) {
2159061da546Spatrick           case GetValueForExpressionPathOptions::SyntheticChildrenTraversal::
2160061da546Spatrick               None:
2161061da546Spatrick             break;
2162061da546Spatrick           case GetValueForExpressionPathOptions::SyntheticChildrenTraversal::
2163061da546Spatrick               FromSynthetic:
2164061da546Spatrick             if (root->IsSynthetic()) {
2165061da546Spatrick               child_valobj_sp = root->GetNonSyntheticValue();
2166061da546Spatrick               if (child_valobj_sp.get())
2167061da546Spatrick                 child_valobj_sp =
2168061da546Spatrick                     child_valobj_sp->GetChildMemberWithName(child_name, true);
2169061da546Spatrick             }
2170061da546Spatrick             break;
2171061da546Spatrick           case GetValueForExpressionPathOptions::SyntheticChildrenTraversal::
2172061da546Spatrick               ToSynthetic:
2173061da546Spatrick             if (!root->IsSynthetic()) {
2174061da546Spatrick               child_valobj_sp = root->GetSyntheticValue();
2175061da546Spatrick               if (child_valobj_sp.get())
2176061da546Spatrick                 child_valobj_sp =
2177061da546Spatrick                     child_valobj_sp->GetChildMemberWithName(child_name, true);
2178061da546Spatrick             }
2179061da546Spatrick             break;
2180061da546Spatrick           case GetValueForExpressionPathOptions::SyntheticChildrenTraversal::
2181061da546Spatrick               Both:
2182061da546Spatrick             if (root->IsSynthetic()) {
2183061da546Spatrick               child_valobj_sp = root->GetNonSyntheticValue();
2184061da546Spatrick               if (child_valobj_sp.get())
2185061da546Spatrick                 child_valobj_sp =
2186061da546Spatrick                     child_valobj_sp->GetChildMemberWithName(child_name, true);
2187061da546Spatrick             } else {
2188061da546Spatrick               child_valobj_sp = root->GetSyntheticValue();
2189061da546Spatrick               if (child_valobj_sp.get())
2190061da546Spatrick                 child_valobj_sp =
2191061da546Spatrick                     child_valobj_sp->GetChildMemberWithName(child_name, true);
2192061da546Spatrick             }
2193061da546Spatrick             break;
2194061da546Spatrick           }
2195061da546Spatrick         }
2196061da546Spatrick 
2197061da546Spatrick         // if we are here and options.m_no_synthetic_children is true,
2198061da546Spatrick         // child_valobj_sp is going to be a NULL SP, so we hit the "else"
2199061da546Spatrick         // branch, and return an error
2200061da546Spatrick         if (child_valobj_sp.get()) // if it worked, just return
2201061da546Spatrick         {
2202061da546Spatrick           *reason_to_stop =
2203061da546Spatrick               ValueObject::eExpressionPathScanEndReasonEndOfString;
2204061da546Spatrick           *final_result = ValueObject::eExpressionPathEndResultTypePlain;
2205061da546Spatrick           return child_valobj_sp;
2206061da546Spatrick         } else {
2207061da546Spatrick           *reason_to_stop =
2208061da546Spatrick               ValueObject::eExpressionPathScanEndReasonNoSuchChild;
2209061da546Spatrick           *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
2210061da546Spatrick           return nullptr;
2211061da546Spatrick         }
2212061da546Spatrick       } else // other layers do expand
2213061da546Spatrick       {
2214061da546Spatrick         llvm::StringRef next_separator = temp_expression.substr(next_sep_pos);
2215061da546Spatrick 
2216061da546Spatrick         child_name.SetString(temp_expression.slice(0, next_sep_pos));
2217061da546Spatrick 
2218061da546Spatrick         ValueObjectSP child_valobj_sp =
2219061da546Spatrick             root->GetChildMemberWithName(child_name, true);
2220061da546Spatrick         if (child_valobj_sp.get()) // store the new root and move on
2221061da546Spatrick         {
2222061da546Spatrick           root = child_valobj_sp;
2223061da546Spatrick           remainder = next_separator;
2224061da546Spatrick           *final_result = ValueObject::eExpressionPathEndResultTypePlain;
2225061da546Spatrick           continue;
2226061da546Spatrick         } else {
2227061da546Spatrick           switch (options.m_synthetic_children_traversal) {
2228061da546Spatrick           case GetValueForExpressionPathOptions::SyntheticChildrenTraversal::
2229061da546Spatrick               None:
2230061da546Spatrick             break;
2231061da546Spatrick           case GetValueForExpressionPathOptions::SyntheticChildrenTraversal::
2232061da546Spatrick               FromSynthetic:
2233061da546Spatrick             if (root->IsSynthetic()) {
2234061da546Spatrick               child_valobj_sp = root->GetNonSyntheticValue();
2235061da546Spatrick               if (child_valobj_sp.get())
2236061da546Spatrick                 child_valobj_sp =
2237061da546Spatrick                     child_valobj_sp->GetChildMemberWithName(child_name, true);
2238061da546Spatrick             }
2239061da546Spatrick             break;
2240061da546Spatrick           case GetValueForExpressionPathOptions::SyntheticChildrenTraversal::
2241061da546Spatrick               ToSynthetic:
2242061da546Spatrick             if (!root->IsSynthetic()) {
2243061da546Spatrick               child_valobj_sp = root->GetSyntheticValue();
2244061da546Spatrick               if (child_valobj_sp.get())
2245061da546Spatrick                 child_valobj_sp =
2246061da546Spatrick                     child_valobj_sp->GetChildMemberWithName(child_name, true);
2247061da546Spatrick             }
2248061da546Spatrick             break;
2249061da546Spatrick           case GetValueForExpressionPathOptions::SyntheticChildrenTraversal::
2250061da546Spatrick               Both:
2251061da546Spatrick             if (root->IsSynthetic()) {
2252061da546Spatrick               child_valobj_sp = root->GetNonSyntheticValue();
2253061da546Spatrick               if (child_valobj_sp.get())
2254061da546Spatrick                 child_valobj_sp =
2255061da546Spatrick                     child_valobj_sp->GetChildMemberWithName(child_name, true);
2256061da546Spatrick             } else {
2257061da546Spatrick               child_valobj_sp = root->GetSyntheticValue();
2258061da546Spatrick               if (child_valobj_sp.get())
2259061da546Spatrick                 child_valobj_sp =
2260061da546Spatrick                     child_valobj_sp->GetChildMemberWithName(child_name, true);
2261061da546Spatrick             }
2262061da546Spatrick             break;
2263061da546Spatrick           }
2264061da546Spatrick         }
2265061da546Spatrick 
2266061da546Spatrick         // if we are here and options.m_no_synthetic_children is true,
2267061da546Spatrick         // child_valobj_sp is going to be a NULL SP, so we hit the "else"
2268061da546Spatrick         // branch, and return an error
2269061da546Spatrick         if (child_valobj_sp.get()) // if it worked, move on
2270061da546Spatrick         {
2271061da546Spatrick           root = child_valobj_sp;
2272061da546Spatrick           remainder = next_separator;
2273061da546Spatrick           *final_result = ValueObject::eExpressionPathEndResultTypePlain;
2274061da546Spatrick           continue;
2275061da546Spatrick         } else {
2276061da546Spatrick           *reason_to_stop =
2277061da546Spatrick               ValueObject::eExpressionPathScanEndReasonNoSuchChild;
2278061da546Spatrick           *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
2279061da546Spatrick           return nullptr;
2280061da546Spatrick         }
2281061da546Spatrick       }
2282061da546Spatrick       break;
2283061da546Spatrick     }
2284061da546Spatrick     case '[': {
2285061da546Spatrick       if (!root_compiler_type_info.Test(eTypeIsArray) &&
2286061da546Spatrick           !root_compiler_type_info.Test(eTypeIsPointer) &&
2287061da546Spatrick           !root_compiler_type_info.Test(
2288061da546Spatrick               eTypeIsVector)) // if this is not a T[] nor a T*
2289061da546Spatrick       {
2290061da546Spatrick         if (!root_compiler_type_info.Test(
2291061da546Spatrick                 eTypeIsScalar)) // if this is not even a scalar...
2292061da546Spatrick         {
2293061da546Spatrick           if (options.m_synthetic_children_traversal ==
2294061da546Spatrick               GetValueForExpressionPathOptions::SyntheticChildrenTraversal::
2295061da546Spatrick                   None) // ...only chance left is synthetic
2296061da546Spatrick           {
2297061da546Spatrick             *reason_to_stop =
2298061da546Spatrick                 ValueObject::eExpressionPathScanEndReasonRangeOperatorInvalid;
2299061da546Spatrick             *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
2300061da546Spatrick             return ValueObjectSP();
2301061da546Spatrick           }
2302061da546Spatrick         } else if (!options.m_allow_bitfields_syntax) // if this is a scalar,
2303061da546Spatrick                                                       // check that we can
2304061da546Spatrick                                                       // expand bitfields
2305061da546Spatrick         {
2306061da546Spatrick           *reason_to_stop =
2307061da546Spatrick               ValueObject::eExpressionPathScanEndReasonRangeOperatorNotAllowed;
2308061da546Spatrick           *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
2309061da546Spatrick           return ValueObjectSP();
2310061da546Spatrick         }
2311061da546Spatrick       }
2312061da546Spatrick       if (temp_expression[1] ==
2313061da546Spatrick           ']') // if this is an unbounded range it only works for arrays
2314061da546Spatrick       {
2315061da546Spatrick         if (!root_compiler_type_info.Test(eTypeIsArray)) {
2316061da546Spatrick           *reason_to_stop =
2317061da546Spatrick               ValueObject::eExpressionPathScanEndReasonEmptyRangeNotAllowed;
2318061da546Spatrick           *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
2319061da546Spatrick           return nullptr;
2320061da546Spatrick         } else // even if something follows, we cannot expand unbounded ranges,
2321061da546Spatrick                // just let the caller do it
2322061da546Spatrick         {
2323061da546Spatrick           *reason_to_stop =
2324061da546Spatrick               ValueObject::eExpressionPathScanEndReasonArrayRangeOperatorMet;
2325061da546Spatrick           *final_result =
2326061da546Spatrick               ValueObject::eExpressionPathEndResultTypeUnboundedRange;
2327061da546Spatrick           return root;
2328061da546Spatrick         }
2329061da546Spatrick       }
2330061da546Spatrick 
2331061da546Spatrick       size_t close_bracket_position = temp_expression.find(']', 1);
2332061da546Spatrick       if (close_bracket_position ==
2333061da546Spatrick           llvm::StringRef::npos) // if there is no ], this is a syntax error
2334061da546Spatrick       {
2335061da546Spatrick         *reason_to_stop =
2336061da546Spatrick             ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol;
2337061da546Spatrick         *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
2338061da546Spatrick         return nullptr;
2339061da546Spatrick       }
2340061da546Spatrick 
2341061da546Spatrick       llvm::StringRef bracket_expr =
2342061da546Spatrick           temp_expression.slice(1, close_bracket_position);
2343061da546Spatrick 
2344061da546Spatrick       // If this was an empty expression it would have been caught by the if
2345061da546Spatrick       // above.
2346061da546Spatrick       assert(!bracket_expr.empty());
2347061da546Spatrick 
2348061da546Spatrick       if (!bracket_expr.contains('-')) {
2349061da546Spatrick         // if no separator, this is of the form [N].  Note that this cannot be
2350061da546Spatrick         // an unbounded range of the form [], because that case was handled
2351061da546Spatrick         // above with an unconditional return.
2352061da546Spatrick         unsigned long index = 0;
2353061da546Spatrick         if (bracket_expr.getAsInteger(0, index)) {
2354061da546Spatrick           *reason_to_stop =
2355061da546Spatrick               ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol;
2356061da546Spatrick           *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
2357061da546Spatrick           return nullptr;
2358061da546Spatrick         }
2359061da546Spatrick 
2360061da546Spatrick         // from here on we do have a valid index
2361061da546Spatrick         if (root_compiler_type_info.Test(eTypeIsArray)) {
2362061da546Spatrick           ValueObjectSP child_valobj_sp = root->GetChildAtIndex(index, true);
2363061da546Spatrick           if (!child_valobj_sp)
2364061da546Spatrick             child_valobj_sp = root->GetSyntheticArrayMember(index, true);
2365061da546Spatrick           if (!child_valobj_sp)
2366061da546Spatrick             if (root->HasSyntheticValue() &&
2367061da546Spatrick                 root->GetSyntheticValue()->GetNumChildren() > index)
2368061da546Spatrick               child_valobj_sp =
2369061da546Spatrick                   root->GetSyntheticValue()->GetChildAtIndex(index, true);
2370061da546Spatrick           if (child_valobj_sp) {
2371061da546Spatrick             root = child_valobj_sp;
2372061da546Spatrick             remainder =
2373061da546Spatrick                 temp_expression.substr(close_bracket_position + 1); // skip ]
2374061da546Spatrick             *final_result = ValueObject::eExpressionPathEndResultTypePlain;
2375061da546Spatrick             continue;
2376061da546Spatrick           } else {
2377061da546Spatrick             *reason_to_stop =
2378061da546Spatrick                 ValueObject::eExpressionPathScanEndReasonNoSuchChild;
2379061da546Spatrick             *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
2380061da546Spatrick             return nullptr;
2381061da546Spatrick           }
2382061da546Spatrick         } else if (root_compiler_type_info.Test(eTypeIsPointer)) {
2383061da546Spatrick           if (*what_next ==
2384061da546Spatrick                   ValueObject::
2385061da546Spatrick                       eExpressionPathAftermathDereference && // if this is a
2386061da546Spatrick                                                              // ptr-to-scalar, I
2387061da546Spatrick                                                              // am accessing it
2388061da546Spatrick                                                              // by index and I
2389061da546Spatrick                                                              // would have
2390061da546Spatrick                                                              // deref'ed anyway,
2391061da546Spatrick                                                              // then do it now
2392061da546Spatrick                                                              // and use this as
2393061da546Spatrick                                                              // a bitfield
2394061da546Spatrick               pointee_compiler_type_info.Test(eTypeIsScalar)) {
2395061da546Spatrick             Status error;
2396061da546Spatrick             root = root->Dereference(error);
2397061da546Spatrick             if (error.Fail() || !root) {
2398061da546Spatrick               *reason_to_stop =
2399061da546Spatrick                   ValueObject::eExpressionPathScanEndReasonDereferencingFailed;
2400061da546Spatrick               *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
2401061da546Spatrick               return nullptr;
2402061da546Spatrick             } else {
2403061da546Spatrick               *what_next = eExpressionPathAftermathNothing;
2404061da546Spatrick               continue;
2405061da546Spatrick             }
2406061da546Spatrick           } else {
2407061da546Spatrick             if (root->GetCompilerType().GetMinimumLanguage() ==
2408061da546Spatrick                     eLanguageTypeObjC &&
2409061da546Spatrick                 pointee_compiler_type_info.AllClear(eTypeIsPointer) &&
2410061da546Spatrick                 root->HasSyntheticValue() &&
2411061da546Spatrick                 (options.m_synthetic_children_traversal ==
2412061da546Spatrick                      GetValueForExpressionPathOptions::
2413061da546Spatrick                          SyntheticChildrenTraversal::ToSynthetic ||
2414061da546Spatrick                  options.m_synthetic_children_traversal ==
2415061da546Spatrick                      GetValueForExpressionPathOptions::
2416061da546Spatrick                          SyntheticChildrenTraversal::Both)) {
2417061da546Spatrick               root = root->GetSyntheticValue()->GetChildAtIndex(index, true);
2418061da546Spatrick             } else
2419061da546Spatrick               root = root->GetSyntheticArrayMember(index, true);
2420061da546Spatrick             if (!root) {
2421061da546Spatrick               *reason_to_stop =
2422061da546Spatrick                   ValueObject::eExpressionPathScanEndReasonNoSuchChild;
2423061da546Spatrick               *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
2424061da546Spatrick               return nullptr;
2425061da546Spatrick             } else {
2426061da546Spatrick               remainder =
2427061da546Spatrick                   temp_expression.substr(close_bracket_position + 1); // skip ]
2428061da546Spatrick               *final_result = ValueObject::eExpressionPathEndResultTypePlain;
2429061da546Spatrick               continue;
2430061da546Spatrick             }
2431061da546Spatrick           }
2432061da546Spatrick         } else if (root_compiler_type_info.Test(eTypeIsScalar)) {
2433061da546Spatrick           root = root->GetSyntheticBitFieldChild(index, index, true);
2434061da546Spatrick           if (!root) {
2435061da546Spatrick             *reason_to_stop =
2436061da546Spatrick                 ValueObject::eExpressionPathScanEndReasonNoSuchChild;
2437061da546Spatrick             *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
2438061da546Spatrick             return nullptr;
2439061da546Spatrick           } else // we do not know how to expand members of bitfields, so we
2440061da546Spatrick                  // just return and let the caller do any further processing
2441061da546Spatrick           {
2442061da546Spatrick             *reason_to_stop = ValueObject::
2443061da546Spatrick                 eExpressionPathScanEndReasonBitfieldRangeOperatorMet;
2444061da546Spatrick             *final_result = ValueObject::eExpressionPathEndResultTypeBitfield;
2445061da546Spatrick             return root;
2446061da546Spatrick           }
2447061da546Spatrick         } else if (root_compiler_type_info.Test(eTypeIsVector)) {
2448061da546Spatrick           root = root->GetChildAtIndex(index, true);
2449061da546Spatrick           if (!root) {
2450061da546Spatrick             *reason_to_stop =
2451061da546Spatrick                 ValueObject::eExpressionPathScanEndReasonNoSuchChild;
2452061da546Spatrick             *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
2453061da546Spatrick             return ValueObjectSP();
2454061da546Spatrick           } else {
2455061da546Spatrick             remainder =
2456061da546Spatrick                 temp_expression.substr(close_bracket_position + 1); // skip ]
2457061da546Spatrick             *final_result = ValueObject::eExpressionPathEndResultTypePlain;
2458061da546Spatrick             continue;
2459061da546Spatrick           }
2460061da546Spatrick         } else if (options.m_synthetic_children_traversal ==
2461061da546Spatrick                        GetValueForExpressionPathOptions::
2462061da546Spatrick                            SyntheticChildrenTraversal::ToSynthetic ||
2463061da546Spatrick                    options.m_synthetic_children_traversal ==
2464061da546Spatrick                        GetValueForExpressionPathOptions::
2465061da546Spatrick                            SyntheticChildrenTraversal::Both) {
2466061da546Spatrick           if (root->HasSyntheticValue())
2467061da546Spatrick             root = root->GetSyntheticValue();
2468061da546Spatrick           else if (!root->IsSynthetic()) {
2469061da546Spatrick             *reason_to_stop =
2470061da546Spatrick                 ValueObject::eExpressionPathScanEndReasonSyntheticValueMissing;
2471061da546Spatrick             *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
2472061da546Spatrick             return nullptr;
2473061da546Spatrick           }
2474061da546Spatrick           // if we are here, then root itself is a synthetic VO.. should be
2475061da546Spatrick           // good to go
2476061da546Spatrick 
2477061da546Spatrick           if (!root) {
2478061da546Spatrick             *reason_to_stop =
2479061da546Spatrick                 ValueObject::eExpressionPathScanEndReasonSyntheticValueMissing;
2480061da546Spatrick             *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
2481061da546Spatrick             return nullptr;
2482061da546Spatrick           }
2483061da546Spatrick           root = root->GetChildAtIndex(index, true);
2484061da546Spatrick           if (!root) {
2485061da546Spatrick             *reason_to_stop =
2486061da546Spatrick                 ValueObject::eExpressionPathScanEndReasonNoSuchChild;
2487061da546Spatrick             *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
2488061da546Spatrick             return nullptr;
2489061da546Spatrick           } else {
2490061da546Spatrick             remainder =
2491061da546Spatrick                 temp_expression.substr(close_bracket_position + 1); // skip ]
2492061da546Spatrick             *final_result = ValueObject::eExpressionPathEndResultTypePlain;
2493061da546Spatrick             continue;
2494061da546Spatrick           }
2495061da546Spatrick         } else {
2496061da546Spatrick           *reason_to_stop =
2497061da546Spatrick               ValueObject::eExpressionPathScanEndReasonNoSuchChild;
2498061da546Spatrick           *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
2499061da546Spatrick           return nullptr;
2500061da546Spatrick         }
2501061da546Spatrick       } else {
2502061da546Spatrick         // we have a low and a high index
2503061da546Spatrick         llvm::StringRef sleft, sright;
2504061da546Spatrick         unsigned long low_index, high_index;
2505061da546Spatrick         std::tie(sleft, sright) = bracket_expr.split('-');
2506061da546Spatrick         if (sleft.getAsInteger(0, low_index) ||
2507061da546Spatrick             sright.getAsInteger(0, high_index)) {
2508061da546Spatrick           *reason_to_stop =
2509061da546Spatrick               ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol;
2510061da546Spatrick           *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
2511061da546Spatrick           return nullptr;
2512061da546Spatrick         }
2513061da546Spatrick 
2514061da546Spatrick         if (low_index > high_index) // swap indices if required
2515061da546Spatrick           std::swap(low_index, high_index);
2516061da546Spatrick 
2517061da546Spatrick         if (root_compiler_type_info.Test(
2518061da546Spatrick                 eTypeIsScalar)) // expansion only works for scalars
2519061da546Spatrick         {
2520061da546Spatrick           root = root->GetSyntheticBitFieldChild(low_index, high_index, true);
2521061da546Spatrick           if (!root) {
2522061da546Spatrick             *reason_to_stop =
2523061da546Spatrick                 ValueObject::eExpressionPathScanEndReasonNoSuchChild;
2524061da546Spatrick             *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
2525061da546Spatrick             return nullptr;
2526061da546Spatrick           } else {
2527061da546Spatrick             *reason_to_stop = ValueObject::
2528061da546Spatrick                 eExpressionPathScanEndReasonBitfieldRangeOperatorMet;
2529061da546Spatrick             *final_result = ValueObject::eExpressionPathEndResultTypeBitfield;
2530061da546Spatrick             return root;
2531061da546Spatrick           }
2532061da546Spatrick         } else if (root_compiler_type_info.Test(
2533061da546Spatrick                        eTypeIsPointer) && // if this is a ptr-to-scalar, I am
2534061da546Spatrick                                           // accessing it by index and I would
2535061da546Spatrick                                           // have deref'ed anyway, then do it
2536061da546Spatrick                                           // now and use this as a bitfield
2537061da546Spatrick                    *what_next ==
2538061da546Spatrick                        ValueObject::eExpressionPathAftermathDereference &&
2539061da546Spatrick                    pointee_compiler_type_info.Test(eTypeIsScalar)) {
2540061da546Spatrick           Status error;
2541061da546Spatrick           root = root->Dereference(error);
2542061da546Spatrick           if (error.Fail() || !root) {
2543061da546Spatrick             *reason_to_stop =
2544061da546Spatrick                 ValueObject::eExpressionPathScanEndReasonDereferencingFailed;
2545061da546Spatrick             *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
2546061da546Spatrick             return nullptr;
2547061da546Spatrick           } else {
2548061da546Spatrick             *what_next = ValueObject::eExpressionPathAftermathNothing;
2549061da546Spatrick             continue;
2550061da546Spatrick           }
2551061da546Spatrick         } else {
2552061da546Spatrick           *reason_to_stop =
2553061da546Spatrick               ValueObject::eExpressionPathScanEndReasonArrayRangeOperatorMet;
2554061da546Spatrick           *final_result = ValueObject::eExpressionPathEndResultTypeBoundedRange;
2555061da546Spatrick           return root;
2556061da546Spatrick         }
2557061da546Spatrick       }
2558061da546Spatrick       break;
2559061da546Spatrick     }
2560061da546Spatrick     default: // some non-separator is in the way
2561061da546Spatrick     {
2562061da546Spatrick       *reason_to_stop =
2563061da546Spatrick           ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol;
2564061da546Spatrick       *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
2565061da546Spatrick       return nullptr;
2566061da546Spatrick     }
2567061da546Spatrick     }
2568061da546Spatrick   }
2569061da546Spatrick }
2570061da546Spatrick 
Dump(Stream & s)2571061da546Spatrick void ValueObject::Dump(Stream &s) { Dump(s, DumpValueObjectOptions(*this)); }
2572061da546Spatrick 
Dump(Stream & s,const DumpValueObjectOptions & options)2573061da546Spatrick void ValueObject::Dump(Stream &s, const DumpValueObjectOptions &options) {
2574061da546Spatrick   ValueObjectPrinter printer(this, &s, options);
2575061da546Spatrick   printer.PrintValueObject();
2576061da546Spatrick }
2577061da546Spatrick 
CreateConstantValue(ConstString name)2578061da546Spatrick ValueObjectSP ValueObject::CreateConstantValue(ConstString name) {
2579061da546Spatrick   ValueObjectSP valobj_sp;
2580061da546Spatrick 
2581061da546Spatrick   if (UpdateValueIfNeeded(false) && m_error.Success()) {
2582061da546Spatrick     ExecutionContext exe_ctx(GetExecutionContextRef());
2583061da546Spatrick 
2584061da546Spatrick     DataExtractor data;
2585061da546Spatrick     data.SetByteOrder(m_data.GetByteOrder());
2586061da546Spatrick     data.SetAddressByteSize(m_data.GetAddressByteSize());
2587061da546Spatrick 
2588061da546Spatrick     if (IsBitfield()) {
2589061da546Spatrick       Value v(Scalar(GetValueAsUnsigned(UINT64_MAX)));
2590061da546Spatrick       m_error = v.GetValueAsData(&exe_ctx, data, GetModule().get());
2591061da546Spatrick     } else
2592061da546Spatrick       m_error = m_value.GetValueAsData(&exe_ctx, data, GetModule().get());
2593061da546Spatrick 
2594061da546Spatrick     valobj_sp = ValueObjectConstResult::Create(
2595061da546Spatrick         exe_ctx.GetBestExecutionContextScope(), GetCompilerType(), name, data,
2596061da546Spatrick         GetAddressOf());
2597061da546Spatrick   }
2598061da546Spatrick 
2599061da546Spatrick   if (!valobj_sp) {
2600061da546Spatrick     ExecutionContext exe_ctx(GetExecutionContextRef());
2601061da546Spatrick     valobj_sp = ValueObjectConstResult::Create(
2602061da546Spatrick         exe_ctx.GetBestExecutionContextScope(), m_error);
2603061da546Spatrick   }
2604061da546Spatrick   return valobj_sp;
2605061da546Spatrick }
2606061da546Spatrick 
GetQualifiedRepresentationIfAvailable(lldb::DynamicValueType dynValue,bool synthValue)2607061da546Spatrick ValueObjectSP ValueObject::GetQualifiedRepresentationIfAvailable(
2608061da546Spatrick     lldb::DynamicValueType dynValue, bool synthValue) {
2609061da546Spatrick   ValueObjectSP result_sp(GetSP());
2610061da546Spatrick 
2611061da546Spatrick   switch (dynValue) {
2612061da546Spatrick   case lldb::eDynamicCanRunTarget:
2613061da546Spatrick   case lldb::eDynamicDontRunTarget: {
2614061da546Spatrick     if (!result_sp->IsDynamic()) {
2615061da546Spatrick       if (result_sp->GetDynamicValue(dynValue))
2616061da546Spatrick         result_sp = result_sp->GetDynamicValue(dynValue);
2617061da546Spatrick     }
2618061da546Spatrick   } break;
2619061da546Spatrick   case lldb::eNoDynamicValues: {
2620061da546Spatrick     if (result_sp->IsDynamic()) {
2621061da546Spatrick       if (result_sp->GetStaticValue())
2622061da546Spatrick         result_sp = result_sp->GetStaticValue();
2623061da546Spatrick     }
2624061da546Spatrick   } break;
2625061da546Spatrick   }
2626061da546Spatrick 
2627061da546Spatrick   if (synthValue) {
2628061da546Spatrick     if (!result_sp->IsSynthetic()) {
2629061da546Spatrick       if (result_sp->GetSyntheticValue())
2630061da546Spatrick         result_sp = result_sp->GetSyntheticValue();
2631061da546Spatrick     }
2632061da546Spatrick   } else {
2633061da546Spatrick     if (result_sp->IsSynthetic()) {
2634061da546Spatrick       if (result_sp->GetNonSyntheticValue())
2635061da546Spatrick         result_sp = result_sp->GetNonSyntheticValue();
2636061da546Spatrick     }
2637061da546Spatrick   }
2638061da546Spatrick 
2639061da546Spatrick   return result_sp;
2640061da546Spatrick }
2641061da546Spatrick 
Dereference(Status & error)2642061da546Spatrick ValueObjectSP ValueObject::Dereference(Status &error) {
2643061da546Spatrick   if (m_deref_valobj)
2644061da546Spatrick     return m_deref_valobj->GetSP();
2645061da546Spatrick 
2646061da546Spatrick   const bool is_pointer_or_reference_type = IsPointerOrReferenceType();
2647061da546Spatrick   if (is_pointer_or_reference_type) {
2648061da546Spatrick     bool omit_empty_base_classes = true;
2649061da546Spatrick     bool ignore_array_bounds = false;
2650061da546Spatrick 
2651061da546Spatrick     std::string child_name_str;
2652061da546Spatrick     uint32_t child_byte_size = 0;
2653061da546Spatrick     int32_t child_byte_offset = 0;
2654061da546Spatrick     uint32_t child_bitfield_bit_size = 0;
2655061da546Spatrick     uint32_t child_bitfield_bit_offset = 0;
2656061da546Spatrick     bool child_is_base_class = false;
2657061da546Spatrick     bool child_is_deref_of_parent = false;
2658061da546Spatrick     const bool transparent_pointers = false;
2659061da546Spatrick     CompilerType compiler_type = GetCompilerType();
2660061da546Spatrick     CompilerType child_compiler_type;
2661dda28197Spatrick     uint64_t language_flags = 0;
2662061da546Spatrick 
2663061da546Spatrick     ExecutionContext exe_ctx(GetExecutionContextRef());
2664061da546Spatrick 
2665061da546Spatrick     child_compiler_type = compiler_type.GetChildCompilerTypeAtIndex(
2666061da546Spatrick         &exe_ctx, 0, transparent_pointers, omit_empty_base_classes,
2667061da546Spatrick         ignore_array_bounds, child_name_str, child_byte_size, child_byte_offset,
2668061da546Spatrick         child_bitfield_bit_size, child_bitfield_bit_offset, child_is_base_class,
2669061da546Spatrick         child_is_deref_of_parent, this, language_flags);
2670061da546Spatrick     if (child_compiler_type && child_byte_size) {
2671061da546Spatrick       ConstString child_name;
2672061da546Spatrick       if (!child_name_str.empty())
2673061da546Spatrick         child_name.SetCString(child_name_str.c_str());
2674061da546Spatrick 
2675061da546Spatrick       m_deref_valobj = new ValueObjectChild(
2676061da546Spatrick           *this, child_compiler_type, child_name, child_byte_size,
2677061da546Spatrick           child_byte_offset, child_bitfield_bit_size, child_bitfield_bit_offset,
2678061da546Spatrick           child_is_base_class, child_is_deref_of_parent, eAddressTypeInvalid,
2679061da546Spatrick           language_flags);
2680061da546Spatrick     }
2681dda28197Spatrick 
2682dda28197Spatrick     // In case of incomplete child compiler type, use the pointee type and try
2683dda28197Spatrick     // to recreate a new ValueObjectChild using it.
2684dda28197Spatrick     if (!m_deref_valobj) {
2685*f6aab3d8Srobert       // FIXME(#59012): C++ stdlib formatters break with incomplete types (e.g.
2686*f6aab3d8Srobert       // `std::vector<int> &`). Remove ObjC restriction once that's resolved.
2687*f6aab3d8Srobert       if (Language::LanguageIsObjC(GetPreferredDisplayLanguage()) &&
2688*f6aab3d8Srobert           HasSyntheticValue()) {
2689dda28197Spatrick         child_compiler_type = compiler_type.GetPointeeType();
2690dda28197Spatrick 
2691dda28197Spatrick         if (child_compiler_type) {
2692dda28197Spatrick           ConstString child_name;
2693dda28197Spatrick           if (!child_name_str.empty())
2694dda28197Spatrick             child_name.SetCString(child_name_str.c_str());
2695dda28197Spatrick 
2696dda28197Spatrick           m_deref_valobj = new ValueObjectChild(
2697dda28197Spatrick               *this, child_compiler_type, child_name, child_byte_size,
2698dda28197Spatrick               child_byte_offset, child_bitfield_bit_size,
2699dda28197Spatrick               child_bitfield_bit_offset, child_is_base_class,
2700dda28197Spatrick               child_is_deref_of_parent, eAddressTypeInvalid, language_flags);
2701dda28197Spatrick         }
2702dda28197Spatrick       }
2703dda28197Spatrick     }
2704dda28197Spatrick 
2705061da546Spatrick   } else if (HasSyntheticValue()) {
2706061da546Spatrick     m_deref_valobj =
2707061da546Spatrick         GetSyntheticValue()
2708061da546Spatrick             ->GetChildMemberWithName(ConstString("$$dereference$$"), true)
2709061da546Spatrick             .get();
2710dda28197Spatrick   } else if (IsSynthetic()) {
2711dda28197Spatrick     m_deref_valobj =
2712dda28197Spatrick         GetChildMemberWithName(ConstString("$$dereference$$"), true).get();
2713061da546Spatrick   }
2714061da546Spatrick 
2715061da546Spatrick   if (m_deref_valobj) {
2716061da546Spatrick     error.Clear();
2717061da546Spatrick     return m_deref_valobj->GetSP();
2718061da546Spatrick   } else {
2719061da546Spatrick     StreamString strm;
2720dda28197Spatrick     GetExpressionPath(strm);
2721061da546Spatrick 
2722061da546Spatrick     if (is_pointer_or_reference_type)
2723061da546Spatrick       error.SetErrorStringWithFormat("dereference failed: (%s) %s",
2724061da546Spatrick                                      GetTypeName().AsCString("<invalid type>"),
2725061da546Spatrick                                      strm.GetData());
2726061da546Spatrick     else
2727061da546Spatrick       error.SetErrorStringWithFormat("not a pointer or reference type: (%s) %s",
2728061da546Spatrick                                      GetTypeName().AsCString("<invalid type>"),
2729061da546Spatrick                                      strm.GetData());
2730061da546Spatrick     return ValueObjectSP();
2731061da546Spatrick   }
2732061da546Spatrick }
2733061da546Spatrick 
AddressOf(Status & error)2734061da546Spatrick ValueObjectSP ValueObject::AddressOf(Status &error) {
2735061da546Spatrick   if (m_addr_of_valobj_sp)
2736061da546Spatrick     return m_addr_of_valobj_sp;
2737061da546Spatrick 
2738061da546Spatrick   AddressType address_type = eAddressTypeInvalid;
2739061da546Spatrick   const bool scalar_is_load_address = false;
2740061da546Spatrick   addr_t addr = GetAddressOf(scalar_is_load_address, &address_type);
2741061da546Spatrick   error.Clear();
2742061da546Spatrick   if (addr != LLDB_INVALID_ADDRESS && address_type != eAddressTypeHost) {
2743061da546Spatrick     switch (address_type) {
2744061da546Spatrick     case eAddressTypeInvalid: {
2745061da546Spatrick       StreamString expr_path_strm;
2746dda28197Spatrick       GetExpressionPath(expr_path_strm);
2747061da546Spatrick       error.SetErrorStringWithFormat("'%s' is not in memory",
2748061da546Spatrick                                      expr_path_strm.GetData());
2749061da546Spatrick     } break;
2750061da546Spatrick 
2751061da546Spatrick     case eAddressTypeFile:
2752061da546Spatrick     case eAddressTypeLoad: {
2753061da546Spatrick       CompilerType compiler_type = GetCompilerType();
2754061da546Spatrick       if (compiler_type) {
2755061da546Spatrick         std::string name(1, '&');
2756061da546Spatrick         name.append(m_name.AsCString(""));
2757061da546Spatrick         ExecutionContext exe_ctx(GetExecutionContextRef());
2758061da546Spatrick         m_addr_of_valobj_sp = ValueObjectConstResult::Create(
2759061da546Spatrick             exe_ctx.GetBestExecutionContextScope(),
2760061da546Spatrick             compiler_type.GetPointerType(), ConstString(name.c_str()), addr,
2761061da546Spatrick             eAddressTypeInvalid, m_data.GetAddressByteSize());
2762061da546Spatrick       }
2763061da546Spatrick     } break;
2764061da546Spatrick     default:
2765061da546Spatrick       break;
2766061da546Spatrick     }
2767061da546Spatrick   } else {
2768061da546Spatrick     StreamString expr_path_strm;
2769dda28197Spatrick     GetExpressionPath(expr_path_strm);
2770061da546Spatrick     error.SetErrorStringWithFormat("'%s' doesn't have a valid address",
2771061da546Spatrick                                    expr_path_strm.GetData());
2772061da546Spatrick   }
2773061da546Spatrick 
2774061da546Spatrick   return m_addr_of_valobj_sp;
2775061da546Spatrick }
2776061da546Spatrick 
Cast(const CompilerType & compiler_type)2777061da546Spatrick ValueObjectSP ValueObject::Cast(const CompilerType &compiler_type) {
2778061da546Spatrick   return ValueObjectCast::Create(*this, GetName(), compiler_type);
2779061da546Spatrick }
2780061da546Spatrick 
Clone(ConstString new_name)2781061da546Spatrick lldb::ValueObjectSP ValueObject::Clone(ConstString new_name) {
2782061da546Spatrick   return ValueObjectCast::Create(*this, new_name, GetCompilerType());
2783061da546Spatrick }
2784061da546Spatrick 
CastPointerType(const char * name,CompilerType & compiler_type)2785061da546Spatrick ValueObjectSP ValueObject::CastPointerType(const char *name,
2786061da546Spatrick                                            CompilerType &compiler_type) {
2787061da546Spatrick   ValueObjectSP valobj_sp;
2788061da546Spatrick   AddressType address_type;
2789061da546Spatrick   addr_t ptr_value = GetPointerValue(&address_type);
2790061da546Spatrick 
2791061da546Spatrick   if (ptr_value != LLDB_INVALID_ADDRESS) {
2792061da546Spatrick     Address ptr_addr(ptr_value);
2793061da546Spatrick     ExecutionContext exe_ctx(GetExecutionContextRef());
2794061da546Spatrick     valobj_sp = ValueObjectMemory::Create(
2795061da546Spatrick         exe_ctx.GetBestExecutionContextScope(), name, ptr_addr, compiler_type);
2796061da546Spatrick   }
2797061da546Spatrick   return valobj_sp;
2798061da546Spatrick }
2799061da546Spatrick 
CastPointerType(const char * name,TypeSP & type_sp)2800061da546Spatrick ValueObjectSP ValueObject::CastPointerType(const char *name, TypeSP &type_sp) {
2801061da546Spatrick   ValueObjectSP valobj_sp;
2802061da546Spatrick   AddressType address_type;
2803061da546Spatrick   addr_t ptr_value = GetPointerValue(&address_type);
2804061da546Spatrick 
2805061da546Spatrick   if (ptr_value != LLDB_INVALID_ADDRESS) {
2806061da546Spatrick     Address ptr_addr(ptr_value);
2807061da546Spatrick     ExecutionContext exe_ctx(GetExecutionContextRef());
2808061da546Spatrick     valobj_sp = ValueObjectMemory::Create(
2809061da546Spatrick         exe_ctx.GetBestExecutionContextScope(), name, ptr_addr, type_sp);
2810061da546Spatrick   }
2811061da546Spatrick   return valobj_sp;
2812061da546Spatrick }
2813061da546Spatrick 
EvaluationPoint()2814be691f3bSpatrick ValueObject::EvaluationPoint::EvaluationPoint() : m_mod_id(), m_exe_ctx_ref() {}
2815061da546Spatrick 
EvaluationPoint(ExecutionContextScope * exe_scope,bool use_selected)2816061da546Spatrick ValueObject::EvaluationPoint::EvaluationPoint(ExecutionContextScope *exe_scope,
2817061da546Spatrick                                               bool use_selected)
2818*f6aab3d8Srobert     : m_mod_id(), m_exe_ctx_ref() {
2819061da546Spatrick   ExecutionContext exe_ctx(exe_scope);
2820061da546Spatrick   TargetSP target_sp(exe_ctx.GetTargetSP());
2821061da546Spatrick   if (target_sp) {
2822061da546Spatrick     m_exe_ctx_ref.SetTargetSP(target_sp);
2823061da546Spatrick     ProcessSP process_sp(exe_ctx.GetProcessSP());
2824061da546Spatrick     if (!process_sp)
2825061da546Spatrick       process_sp = target_sp->GetProcessSP();
2826061da546Spatrick 
2827061da546Spatrick     if (process_sp) {
2828061da546Spatrick       m_mod_id = process_sp->GetModID();
2829061da546Spatrick       m_exe_ctx_ref.SetProcessSP(process_sp);
2830061da546Spatrick 
2831061da546Spatrick       ThreadSP thread_sp(exe_ctx.GetThreadSP());
2832061da546Spatrick 
2833061da546Spatrick       if (!thread_sp) {
2834061da546Spatrick         if (use_selected)
2835061da546Spatrick           thread_sp = process_sp->GetThreadList().GetSelectedThread();
2836061da546Spatrick       }
2837061da546Spatrick 
2838061da546Spatrick       if (thread_sp) {
2839061da546Spatrick         m_exe_ctx_ref.SetThreadSP(thread_sp);
2840061da546Spatrick 
2841061da546Spatrick         StackFrameSP frame_sp(exe_ctx.GetFrameSP());
2842061da546Spatrick         if (!frame_sp) {
2843061da546Spatrick           if (use_selected)
2844061da546Spatrick             frame_sp = thread_sp->GetSelectedFrame();
2845061da546Spatrick         }
2846061da546Spatrick         if (frame_sp)
2847061da546Spatrick           m_exe_ctx_ref.SetFrameSP(frame_sp);
2848061da546Spatrick       }
2849061da546Spatrick     }
2850061da546Spatrick   }
2851061da546Spatrick }
2852061da546Spatrick 
EvaluationPoint(const ValueObject::EvaluationPoint & rhs)2853061da546Spatrick ValueObject::EvaluationPoint::EvaluationPoint(
2854061da546Spatrick     const ValueObject::EvaluationPoint &rhs)
2855*f6aab3d8Srobert     : m_mod_id(), m_exe_ctx_ref(rhs.m_exe_ctx_ref) {}
2856061da546Spatrick 
2857be691f3bSpatrick ValueObject::EvaluationPoint::~EvaluationPoint() = default;
2858061da546Spatrick 
2859061da546Spatrick // This function checks the EvaluationPoint against the current process state.
2860061da546Spatrick // If the current state matches the evaluation point, or the evaluation point
2861061da546Spatrick // is already invalid, then we return false, meaning "no change".  If the
2862061da546Spatrick // current state is different, we update our state, and return true meaning
2863061da546Spatrick // "yes, change".  If we did see a change, we also set m_needs_update to true,
2864061da546Spatrick // so future calls to NeedsUpdate will return true. exe_scope will be set to
2865061da546Spatrick // the current execution context scope.
2866061da546Spatrick 
SyncWithProcessState(bool accept_invalid_exe_ctx)2867061da546Spatrick bool ValueObject::EvaluationPoint::SyncWithProcessState(
2868061da546Spatrick     bool accept_invalid_exe_ctx) {
2869061da546Spatrick   // Start with the target, if it is NULL, then we're obviously not going to
2870061da546Spatrick   // get any further:
2871061da546Spatrick   const bool thread_and_frame_only_if_stopped = true;
2872061da546Spatrick   ExecutionContext exe_ctx(
2873061da546Spatrick       m_exe_ctx_ref.Lock(thread_and_frame_only_if_stopped));
2874061da546Spatrick 
2875061da546Spatrick   if (exe_ctx.GetTargetPtr() == nullptr)
2876061da546Spatrick     return false;
2877061da546Spatrick 
2878061da546Spatrick   // If we don't have a process nothing can change.
2879061da546Spatrick   Process *process = exe_ctx.GetProcessPtr();
2880061da546Spatrick   if (process == nullptr)
2881061da546Spatrick     return false;
2882061da546Spatrick 
2883061da546Spatrick   // If our stop id is the current stop ID, nothing has changed:
2884061da546Spatrick   ProcessModID current_mod_id = process->GetModID();
2885061da546Spatrick 
2886061da546Spatrick   // If the current stop id is 0, either we haven't run yet, or the process
2887061da546Spatrick   // state has been cleared. In either case, we aren't going to be able to sync
2888061da546Spatrick   // with the process state.
2889061da546Spatrick   if (current_mod_id.GetStopID() == 0)
2890061da546Spatrick     return false;
2891061da546Spatrick 
2892061da546Spatrick   bool changed = false;
2893061da546Spatrick   const bool was_valid = m_mod_id.IsValid();
2894061da546Spatrick   if (was_valid) {
2895061da546Spatrick     if (m_mod_id == current_mod_id) {
2896061da546Spatrick       // Everything is already up to date in this object, no need to update the
2897061da546Spatrick       // execution context scope.
2898061da546Spatrick       changed = false;
2899061da546Spatrick     } else {
2900061da546Spatrick       m_mod_id = current_mod_id;
2901061da546Spatrick       m_needs_update = true;
2902061da546Spatrick       changed = true;
2903061da546Spatrick     }
2904061da546Spatrick   }
2905061da546Spatrick 
2906061da546Spatrick   // Now re-look up the thread and frame in case the underlying objects have
2907061da546Spatrick   // gone away & been recreated. That way we'll be sure to return a valid
2908061da546Spatrick   // exe_scope. If we used to have a thread or a frame but can't find it
2909061da546Spatrick   // anymore, then mark ourselves as invalid.
2910061da546Spatrick 
2911061da546Spatrick   if (!accept_invalid_exe_ctx) {
2912061da546Spatrick     if (m_exe_ctx_ref.HasThreadRef()) {
2913061da546Spatrick       ThreadSP thread_sp(m_exe_ctx_ref.GetThreadSP());
2914061da546Spatrick       if (thread_sp) {
2915061da546Spatrick         if (m_exe_ctx_ref.HasFrameRef()) {
2916061da546Spatrick           StackFrameSP frame_sp(m_exe_ctx_ref.GetFrameSP());
2917061da546Spatrick           if (!frame_sp) {
2918061da546Spatrick             // We used to have a frame, but now it is gone
2919061da546Spatrick             SetInvalid();
2920061da546Spatrick             changed = was_valid;
2921061da546Spatrick           }
2922061da546Spatrick         }
2923061da546Spatrick       } else {
2924061da546Spatrick         // We used to have a thread, but now it is gone
2925061da546Spatrick         SetInvalid();
2926061da546Spatrick         changed = was_valid;
2927061da546Spatrick       }
2928061da546Spatrick     }
2929061da546Spatrick   }
2930061da546Spatrick 
2931061da546Spatrick   return changed;
2932061da546Spatrick }
2933061da546Spatrick 
SetUpdated()2934061da546Spatrick void ValueObject::EvaluationPoint::SetUpdated() {
2935061da546Spatrick   ProcessSP process_sp(m_exe_ctx_ref.GetProcessSP());
2936061da546Spatrick   if (process_sp)
2937061da546Spatrick     m_mod_id = process_sp->GetModID();
2938061da546Spatrick   m_needs_update = false;
2939061da546Spatrick }
2940061da546Spatrick 
ClearUserVisibleData(uint32_t clear_mask)2941061da546Spatrick void ValueObject::ClearUserVisibleData(uint32_t clear_mask) {
2942061da546Spatrick   if ((clear_mask & eClearUserVisibleDataItemsValue) ==
2943061da546Spatrick       eClearUserVisibleDataItemsValue)
2944061da546Spatrick     m_value_str.clear();
2945061da546Spatrick 
2946061da546Spatrick   if ((clear_mask & eClearUserVisibleDataItemsLocation) ==
2947061da546Spatrick       eClearUserVisibleDataItemsLocation)
2948061da546Spatrick     m_location_str.clear();
2949061da546Spatrick 
2950061da546Spatrick   if ((clear_mask & eClearUserVisibleDataItemsSummary) ==
2951061da546Spatrick       eClearUserVisibleDataItemsSummary)
2952061da546Spatrick     m_summary_str.clear();
2953061da546Spatrick 
2954061da546Spatrick   if ((clear_mask & eClearUserVisibleDataItemsDescription) ==
2955061da546Spatrick       eClearUserVisibleDataItemsDescription)
2956061da546Spatrick     m_object_desc_str.clear();
2957061da546Spatrick 
2958061da546Spatrick   if ((clear_mask & eClearUserVisibleDataItemsSyntheticChildren) ==
2959061da546Spatrick       eClearUserVisibleDataItemsSyntheticChildren) {
2960061da546Spatrick     if (m_synthetic_value)
2961061da546Spatrick       m_synthetic_value = nullptr;
2962061da546Spatrick   }
2963061da546Spatrick }
2964061da546Spatrick 
GetSymbolContextScope()2965061da546Spatrick SymbolContextScope *ValueObject::GetSymbolContextScope() {
2966061da546Spatrick   if (m_parent) {
2967061da546Spatrick     if (!m_parent->IsPointerOrReferenceType())
2968061da546Spatrick       return m_parent->GetSymbolContextScope();
2969061da546Spatrick   }
2970061da546Spatrick   return nullptr;
2971061da546Spatrick }
2972061da546Spatrick 
2973061da546Spatrick lldb::ValueObjectSP
CreateValueObjectFromExpression(llvm::StringRef name,llvm::StringRef expression,const ExecutionContext & exe_ctx)2974061da546Spatrick ValueObject::CreateValueObjectFromExpression(llvm::StringRef name,
2975061da546Spatrick                                              llvm::StringRef expression,
2976061da546Spatrick                                              const ExecutionContext &exe_ctx) {
2977061da546Spatrick   return CreateValueObjectFromExpression(name, expression, exe_ctx,
2978061da546Spatrick                                          EvaluateExpressionOptions());
2979061da546Spatrick }
2980061da546Spatrick 
CreateValueObjectFromExpression(llvm::StringRef name,llvm::StringRef expression,const ExecutionContext & exe_ctx,const EvaluateExpressionOptions & options)2981061da546Spatrick lldb::ValueObjectSP ValueObject::CreateValueObjectFromExpression(
2982061da546Spatrick     llvm::StringRef name, llvm::StringRef expression,
2983061da546Spatrick     const ExecutionContext &exe_ctx, const EvaluateExpressionOptions &options) {
2984061da546Spatrick   lldb::ValueObjectSP retval_sp;
2985061da546Spatrick   lldb::TargetSP target_sp(exe_ctx.GetTargetSP());
2986061da546Spatrick   if (!target_sp)
2987061da546Spatrick     return retval_sp;
2988061da546Spatrick   if (expression.empty())
2989061da546Spatrick     return retval_sp;
2990061da546Spatrick   target_sp->EvaluateExpression(expression, exe_ctx.GetFrameSP().get(),
2991061da546Spatrick                                 retval_sp, options);
2992061da546Spatrick   if (retval_sp && !name.empty())
2993061da546Spatrick     retval_sp->SetName(ConstString(name));
2994061da546Spatrick   return retval_sp;
2995061da546Spatrick }
2996061da546Spatrick 
CreateValueObjectFromAddress(llvm::StringRef name,uint64_t address,const ExecutionContext & exe_ctx,CompilerType type)2997061da546Spatrick lldb::ValueObjectSP ValueObject::CreateValueObjectFromAddress(
2998061da546Spatrick     llvm::StringRef name, uint64_t address, const ExecutionContext &exe_ctx,
2999061da546Spatrick     CompilerType type) {
3000061da546Spatrick   if (type) {
3001061da546Spatrick     CompilerType pointer_type(type.GetPointerType());
3002061da546Spatrick     if (pointer_type) {
3003061da546Spatrick       lldb::DataBufferSP buffer(
3004061da546Spatrick           new lldb_private::DataBufferHeap(&address, sizeof(lldb::addr_t)));
3005061da546Spatrick       lldb::ValueObjectSP ptr_result_valobj_sp(ValueObjectConstResult::Create(
3006061da546Spatrick           exe_ctx.GetBestExecutionContextScope(), pointer_type,
3007061da546Spatrick           ConstString(name), buffer, exe_ctx.GetByteOrder(),
3008061da546Spatrick           exe_ctx.GetAddressByteSize()));
3009061da546Spatrick       if (ptr_result_valobj_sp) {
3010061da546Spatrick         ptr_result_valobj_sp->GetValue().SetValueType(
3011be691f3bSpatrick             Value::ValueType::LoadAddress);
3012061da546Spatrick         Status err;
3013061da546Spatrick         ptr_result_valobj_sp = ptr_result_valobj_sp->Dereference(err);
3014061da546Spatrick         if (ptr_result_valobj_sp && !name.empty())
3015061da546Spatrick           ptr_result_valobj_sp->SetName(ConstString(name));
3016061da546Spatrick       }
3017061da546Spatrick       return ptr_result_valobj_sp;
3018061da546Spatrick     }
3019061da546Spatrick   }
3020061da546Spatrick   return lldb::ValueObjectSP();
3021061da546Spatrick }
3022061da546Spatrick 
CreateValueObjectFromData(llvm::StringRef name,const DataExtractor & data,const ExecutionContext & exe_ctx,CompilerType type)3023061da546Spatrick lldb::ValueObjectSP ValueObject::CreateValueObjectFromData(
3024061da546Spatrick     llvm::StringRef name, const DataExtractor &data,
3025061da546Spatrick     const ExecutionContext &exe_ctx, CompilerType type) {
3026061da546Spatrick   lldb::ValueObjectSP new_value_sp;
3027061da546Spatrick   new_value_sp = ValueObjectConstResult::Create(
3028061da546Spatrick       exe_ctx.GetBestExecutionContextScope(), type, ConstString(name), data,
3029061da546Spatrick       LLDB_INVALID_ADDRESS);
3030061da546Spatrick   new_value_sp->SetAddressTypeOfChildren(eAddressTypeLoad);
3031061da546Spatrick   if (new_value_sp && !name.empty())
3032061da546Spatrick     new_value_sp->SetName(ConstString(name));
3033061da546Spatrick   return new_value_sp;
3034061da546Spatrick }
3035061da546Spatrick 
GetModule()3036061da546Spatrick ModuleSP ValueObject::GetModule() {
3037061da546Spatrick   ValueObject *root(GetRoot());
3038061da546Spatrick   if (root != this)
3039061da546Spatrick     return root->GetModule();
3040061da546Spatrick   return lldb::ModuleSP();
3041061da546Spatrick }
3042061da546Spatrick 
GetRoot()3043061da546Spatrick ValueObject *ValueObject::GetRoot() {
3044061da546Spatrick   if (m_root)
3045061da546Spatrick     return m_root;
3046061da546Spatrick   return (m_root = FollowParentChain([](ValueObject *vo) -> bool {
3047061da546Spatrick             return (vo->m_parent != nullptr);
3048061da546Spatrick           }));
3049061da546Spatrick }
3050061da546Spatrick 
3051061da546Spatrick ValueObject *
FollowParentChain(std::function<bool (ValueObject *)> f)3052061da546Spatrick ValueObject::FollowParentChain(std::function<bool(ValueObject *)> f) {
3053061da546Spatrick   ValueObject *vo = this;
3054061da546Spatrick   while (vo) {
3055061da546Spatrick     if (!f(vo))
3056061da546Spatrick       break;
3057061da546Spatrick     vo = vo->m_parent;
3058061da546Spatrick   }
3059061da546Spatrick   return vo;
3060061da546Spatrick }
3061061da546Spatrick 
GetAddressTypeOfChildren()3062061da546Spatrick AddressType ValueObject::GetAddressTypeOfChildren() {
3063061da546Spatrick   if (m_address_type_of_ptr_or_ref_children == eAddressTypeInvalid) {
3064061da546Spatrick     ValueObject *root(GetRoot());
3065061da546Spatrick     if (root != this)
3066061da546Spatrick       return root->GetAddressTypeOfChildren();
3067061da546Spatrick   }
3068061da546Spatrick   return m_address_type_of_ptr_or_ref_children;
3069061da546Spatrick }
3070061da546Spatrick 
GetDynamicValueType()3071061da546Spatrick lldb::DynamicValueType ValueObject::GetDynamicValueType() {
3072061da546Spatrick   ValueObject *with_dv_info = this;
3073061da546Spatrick   while (with_dv_info) {
3074061da546Spatrick     if (with_dv_info->HasDynamicValueTypeInfo())
3075061da546Spatrick       return with_dv_info->GetDynamicValueTypeImpl();
3076061da546Spatrick     with_dv_info = with_dv_info->m_parent;
3077061da546Spatrick   }
3078061da546Spatrick   return lldb::eNoDynamicValues;
3079061da546Spatrick }
3080061da546Spatrick 
GetFormat() const3081061da546Spatrick lldb::Format ValueObject::GetFormat() const {
3082061da546Spatrick   const ValueObject *with_fmt_info = this;
3083061da546Spatrick   while (with_fmt_info) {
3084061da546Spatrick     if (with_fmt_info->m_format != lldb::eFormatDefault)
3085061da546Spatrick       return with_fmt_info->m_format;
3086061da546Spatrick     with_fmt_info = with_fmt_info->m_parent;
3087061da546Spatrick   }
3088061da546Spatrick   return m_format;
3089061da546Spatrick }
3090061da546Spatrick 
GetPreferredDisplayLanguage()3091061da546Spatrick lldb::LanguageType ValueObject::GetPreferredDisplayLanguage() {
3092061da546Spatrick   lldb::LanguageType type = m_preferred_display_language;
3093061da546Spatrick   if (m_preferred_display_language == lldb::eLanguageTypeUnknown) {
3094061da546Spatrick     if (GetRoot()) {
3095061da546Spatrick       if (GetRoot() == this) {
3096061da546Spatrick         if (StackFrameSP frame_sp = GetFrameSP()) {
3097061da546Spatrick           const SymbolContext &sc(
3098061da546Spatrick               frame_sp->GetSymbolContext(eSymbolContextCompUnit));
3099061da546Spatrick           if (CompileUnit *cu = sc.comp_unit)
3100061da546Spatrick             type = cu->GetLanguage();
3101061da546Spatrick         }
3102061da546Spatrick       } else {
3103061da546Spatrick         type = GetRoot()->GetPreferredDisplayLanguage();
3104061da546Spatrick       }
3105061da546Spatrick     }
3106061da546Spatrick   }
3107061da546Spatrick   return (m_preferred_display_language = type); // only compute it once
3108061da546Spatrick }
3109061da546Spatrick 
SetPreferredDisplayLanguageIfNeeded(lldb::LanguageType lt)3110061da546Spatrick void ValueObject::SetPreferredDisplayLanguageIfNeeded(lldb::LanguageType lt) {
3111061da546Spatrick   if (m_preferred_display_language == lldb::eLanguageTypeUnknown)
3112061da546Spatrick     SetPreferredDisplayLanguage(lt);
3113061da546Spatrick }
3114061da546Spatrick 
CanProvideValue()3115061da546Spatrick bool ValueObject::CanProvideValue() {
3116061da546Spatrick   // we need to support invalid types as providers of values because some bare-
3117061da546Spatrick   // board debugging scenarios have no notion of types, but still manage to
3118061da546Spatrick   // have raw numeric values for things like registers. sigh.
3119be691f3bSpatrick   CompilerType type = GetCompilerType();
3120061da546Spatrick   return (!type.IsValid()) || (0 != (type.GetTypeInfo() & eTypeHasValue));
3121061da546Spatrick }
3122061da546Spatrick 
3123be691f3bSpatrick 
3124061da546Spatrick 
Persist()3125061da546Spatrick ValueObjectSP ValueObject::Persist() {
3126061da546Spatrick   if (!UpdateValueIfNeeded())
3127061da546Spatrick     return nullptr;
3128061da546Spatrick 
3129061da546Spatrick   TargetSP target_sp(GetTargetSP());
3130061da546Spatrick   if (!target_sp)
3131061da546Spatrick     return nullptr;
3132061da546Spatrick 
3133061da546Spatrick   PersistentExpressionState *persistent_state =
3134061da546Spatrick       target_sp->GetPersistentExpressionStateForLanguage(
3135061da546Spatrick           GetPreferredDisplayLanguage());
3136061da546Spatrick 
3137061da546Spatrick   if (!persistent_state)
3138061da546Spatrick     return nullptr;
3139061da546Spatrick 
3140dda28197Spatrick   ConstString name = persistent_state->GetNextPersistentVariableName();
3141061da546Spatrick 
3142061da546Spatrick   ValueObjectSP const_result_sp =
3143061da546Spatrick       ValueObjectConstResult::Create(target_sp.get(), GetValue(), name);
3144061da546Spatrick 
3145dda28197Spatrick   ExpressionVariableSP persistent_var_sp =
3146061da546Spatrick       persistent_state->CreatePersistentVariable(const_result_sp);
3147dda28197Spatrick   persistent_var_sp->m_live_sp = persistent_var_sp->m_frozen_sp;
3148dda28197Spatrick   persistent_var_sp->m_flags |= ExpressionVariable::EVIsProgramReference;
3149061da546Spatrick 
3150dda28197Spatrick   return persistent_var_sp->GetValueObject();
3151061da546Spatrick }
3152