xref: /src/contrib/llvm-project/lldb/source/Core/ValueObject.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1cfca06d7SDimitry Andric //===-- ValueObject.cpp ---------------------------------------------------===//
2f034231aSEd Maste //
35f29bb8aSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45f29bb8aSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
55f29bb8aSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6f034231aSEd Maste //
7f034231aSEd Maste //===----------------------------------------------------------------------===//
8f034231aSEd Maste 
9f034231aSEd Maste #include "lldb/Core/ValueObject.h"
10f034231aSEd Maste 
1194994d37SDimitry Andric #include "lldb/Core/Address.h"
12344a3780SDimitry Andric #include "lldb/Core/Declaration.h"
13f034231aSEd Maste #include "lldb/Core/Module.h"
14f034231aSEd Maste #include "lldb/Core/ValueObjectCast.h"
15f034231aSEd Maste #include "lldb/Core/ValueObjectChild.h"
16f034231aSEd Maste #include "lldb/Core/ValueObjectConstResult.h"
17f034231aSEd Maste #include "lldb/Core/ValueObjectDynamicValue.h"
18f034231aSEd Maste #include "lldb/Core/ValueObjectMemory.h"
19f034231aSEd Maste #include "lldb/Core/ValueObjectSyntheticFilter.h"
20b1c73532SDimitry Andric #include "lldb/Core/ValueObjectVTable.h"
21f034231aSEd Maste #include "lldb/DataFormatters/DataVisualization.h"
2294994d37SDimitry Andric #include "lldb/DataFormatters/DumpValueObjectOptions.h"
2394994d37SDimitry Andric #include "lldb/DataFormatters/FormatManager.h"
24205afe67SEd Maste #include "lldb/DataFormatters/StringPrinter.h"
2594994d37SDimitry Andric #include "lldb/DataFormatters/TypeFormat.h"
2694994d37SDimitry Andric #include "lldb/DataFormatters/TypeSummary.h"
27f21a844fSEd Maste #include "lldb/DataFormatters/ValueObjectPrinter.h"
2894994d37SDimitry Andric #include "lldb/Expression/ExpressionVariable.h"
29706b4fc4SDimitry Andric #include "lldb/Host/Config.h"
30205afe67SEd Maste #include "lldb/Symbol/CompileUnit.h"
3114f1b3e8SDimitry Andric #include "lldb/Symbol/CompilerType.h"
3294994d37SDimitry Andric #include "lldb/Symbol/SymbolContext.h"
33f034231aSEd Maste #include "lldb/Symbol/Type.h"
345f29bb8aSDimitry Andric #include "lldb/Symbol/Variable.h"
35f034231aSEd Maste #include "lldb/Target/ExecutionContext.h"
36e81d9d49SDimitry Andric #include "lldb/Target/Language.h"
37f034231aSEd Maste #include "lldb/Target/LanguageRuntime.h"
38f034231aSEd Maste #include "lldb/Target/Process.h"
3994994d37SDimitry Andric #include "lldb/Target/StackFrame.h"
40f034231aSEd Maste #include "lldb/Target/Target.h"
41f034231aSEd Maste #include "lldb/Target/Thread.h"
4294994d37SDimitry Andric #include "lldb/Target/ThreadList.h"
4394994d37SDimitry Andric #include "lldb/Utility/DataBuffer.h"
4474a628f7SDimitry Andric #include "lldb/Utility/DataBufferHeap.h"
4594994d37SDimitry Andric #include "lldb/Utility/Flags.h"
46145449b1SDimitry Andric #include "lldb/Utility/LLDBLog.h"
4774a628f7SDimitry Andric #include "lldb/Utility/Log.h"
4894994d37SDimitry Andric #include "lldb/Utility/Scalar.h"
4994994d37SDimitry Andric #include "lldb/Utility/Stream.h"
5074a628f7SDimitry Andric #include "lldb/Utility/StreamString.h"
5194994d37SDimitry Andric #include "lldb/lldb-private-types.h"
5274a628f7SDimitry Andric 
5394994d37SDimitry Andric #include "llvm/Support/Compiler.h"
5474a628f7SDimitry Andric 
5594994d37SDimitry Andric #include <algorithm>
5694994d37SDimitry Andric #include <cstdint>
5794994d37SDimitry Andric #include <cstdlib>
5894994d37SDimitry Andric #include <memory>
59e3b55780SDimitry Andric #include <optional>
6094994d37SDimitry Andric #include <tuple>
6174a628f7SDimitry Andric 
62344a3780SDimitry Andric #include <cassert>
63344a3780SDimitry Andric #include <cinttypes>
64344a3780SDimitry Andric #include <cstdio>
65344a3780SDimitry Andric #include <cstring>
66344a3780SDimitry Andric 
67344a3780SDimitry Andric #include <lldb/Core/ValueObject.h>
6874a628f7SDimitry Andric 
6974a628f7SDimitry Andric namespace lldb_private {
7074a628f7SDimitry Andric class ExecutionContextScope;
7174a628f7SDimitry Andric }
7274a628f7SDimitry Andric namespace lldb_private {
7374a628f7SDimitry Andric class SymbolContextScope;
7474a628f7SDimitry Andric }
75f034231aSEd Maste 
76f034231aSEd Maste using namespace lldb;
77f034231aSEd Maste using namespace lldb_private;
78f034231aSEd Maste 
79f034231aSEd Maste static user_id_t g_value_obj_uid = 0;
80f034231aSEd Maste 
81f034231aSEd Maste // ValueObject constructor
ValueObject(ValueObject & parent)8214f1b3e8SDimitry Andric ValueObject::ValueObject(ValueObject &parent)
83344a3780SDimitry Andric     : m_parent(&parent), m_update_point(parent.GetUpdatePoint()),
84344a3780SDimitry Andric       m_manager(parent.GetManager()), m_id(++g_value_obj_uid) {
85344a3780SDimitry Andric   m_flags.m_is_synthetic_children_generated =
86344a3780SDimitry Andric       parent.m_flags.m_is_synthetic_children_generated;
87706b4fc4SDimitry Andric   m_data.SetByteOrder(parent.GetDataExtractor().GetByteOrder());
88706b4fc4SDimitry Andric   m_data.SetAddressByteSize(parent.GetDataExtractor().GetAddressByteSize());
89f034231aSEd Maste   m_manager->ManageObject(this);
90f034231aSEd Maste }
91f034231aSEd Maste 
92f034231aSEd Maste // ValueObject constructor
ValueObject(ExecutionContextScope * exe_scope,ValueObjectManager & manager,AddressType child_ptr_or_ref_addr_type)93f034231aSEd Maste ValueObject::ValueObject(ExecutionContextScope *exe_scope,
94cfca06d7SDimitry Andric                          ValueObjectManager &manager,
9514f1b3e8SDimitry Andric                          AddressType child_ptr_or_ref_addr_type)
96344a3780SDimitry Andric     : m_update_point(exe_scope), m_manager(&manager),
97f034231aSEd Maste       m_address_type_of_ptr_or_ref_children(child_ptr_or_ref_addr_type),
98344a3780SDimitry Andric       m_id(++g_value_obj_uid) {
99706b4fc4SDimitry Andric   if (exe_scope) {
100706b4fc4SDimitry Andric     TargetSP target_sp(exe_scope->CalculateTarget());
101706b4fc4SDimitry Andric     if (target_sp) {
102706b4fc4SDimitry Andric       const ArchSpec &arch = target_sp->GetArchitecture();
103706b4fc4SDimitry Andric       m_data.SetByteOrder(arch.GetByteOrder());
104706b4fc4SDimitry Andric       m_data.SetAddressByteSize(arch.GetAddressByteSize());
105706b4fc4SDimitry Andric     }
106706b4fc4SDimitry Andric   }
107f034231aSEd Maste   m_manager->ManageObject(this);
108f034231aSEd Maste }
109f034231aSEd Maste 
110f034231aSEd Maste // Destructor
111344a3780SDimitry Andric ValueObject::~ValueObject() = default;
112f034231aSEd Maste 
UpdateValueIfNeeded(bool update_format)11314f1b3e8SDimitry Andric bool ValueObject::UpdateValueIfNeeded(bool update_format) {
114f034231aSEd Maste 
115f034231aSEd Maste   bool did_change_formats = false;
116f034231aSEd Maste 
117f034231aSEd Maste   if (update_format)
118f034231aSEd Maste     did_change_formats = UpdateFormatsIfNeeded();
119f034231aSEd Maste 
120f73363f1SDimitry Andric   // If this is a constant value, then our success is predicated on whether we
121f73363f1SDimitry Andric   // have an error or not
12214f1b3e8SDimitry Andric   if (GetIsConstant()) {
123f21a844fSEd Maste     // if you are constant, things might still have changed behind your back
12414f1b3e8SDimitry Andric     // (e.g. you are a frozen object and things have changed deeper than you
125f73363f1SDimitry Andric     // cared to freeze-dry yourself) in this case, your value has not changed,
126f73363f1SDimitry Andric     // but "computed" entries might have, so you might now have a different
127f73363f1SDimitry Andric     // summary, or a different object description. clear these so we will
128f73363f1SDimitry Andric     // recompute them
129f034231aSEd Maste     if (update_format && !did_change_formats)
13014f1b3e8SDimitry Andric       ClearUserVisibleData(eClearUserVisibleDataItemsSummary |
13114f1b3e8SDimitry Andric                            eClearUserVisibleDataItemsDescription);
132f034231aSEd Maste     return m_error.Success();
133f034231aSEd Maste   }
134f034231aSEd Maste 
135205afe67SEd Maste   bool first_update = IsChecksumEmpty();
136f034231aSEd Maste 
13714f1b3e8SDimitry Andric   if (NeedsUpdating()) {
138f034231aSEd Maste     m_update_point.SetUpdated();
139f034231aSEd Maste 
140f73363f1SDimitry Andric     // Save the old value using swap to avoid a string copy which also will
141f73363f1SDimitry Andric     // clear our m_value_str
14214f1b3e8SDimitry Andric     if (m_value_str.empty()) {
143344a3780SDimitry Andric       m_flags.m_old_value_valid = false;
14414f1b3e8SDimitry Andric     } else {
145344a3780SDimitry Andric       m_flags.m_old_value_valid = true;
146f034231aSEd Maste       m_old_value_str.swap(m_value_str);
147f034231aSEd Maste       ClearUserVisibleData(eClearUserVisibleDataItemsValue);
148f034231aSEd Maste     }
149f034231aSEd Maste 
150f034231aSEd Maste     ClearUserVisibleData();
151f034231aSEd Maste 
15214f1b3e8SDimitry Andric     if (IsInScope()) {
153f034231aSEd Maste       const bool value_was_valid = GetValueIsValid();
154f034231aSEd Maste       SetValueDidChange(false);
155f034231aSEd Maste 
156f034231aSEd Maste       m_error.Clear();
157f034231aSEd Maste 
158f034231aSEd Maste       // Call the pure virtual function to update the value
159205afe67SEd Maste 
160205afe67SEd Maste       bool need_compare_checksums = false;
161205afe67SEd Maste       llvm::SmallVector<uint8_t, 16> old_checksum;
162205afe67SEd Maste 
16314f1b3e8SDimitry Andric       if (!first_update && CanProvideValue()) {
164205afe67SEd Maste         need_compare_checksums = true;
165205afe67SEd Maste         old_checksum.resize(m_value_checksum.size());
16614f1b3e8SDimitry Andric         std::copy(m_value_checksum.begin(), m_value_checksum.end(),
16714f1b3e8SDimitry Andric                   old_checksum.begin());
168205afe67SEd Maste       }
169205afe67SEd Maste 
170f034231aSEd Maste       bool success = UpdateValue();
171f034231aSEd Maste 
172f034231aSEd Maste       SetValueIsValid(success);
173f034231aSEd Maste 
17414f1b3e8SDimitry Andric       if (success) {
175706b4fc4SDimitry Andric         UpdateChildrenAddressType();
176205afe67SEd Maste         const uint64_t max_checksum_size = 128;
17714f1b3e8SDimitry Andric         m_data.Checksum(m_value_checksum, max_checksum_size);
17814f1b3e8SDimitry Andric       } else {
179205afe67SEd Maste         need_compare_checksums = false;
180205afe67SEd Maste         m_value_checksum.clear();
181205afe67SEd Maste       }
182205afe67SEd Maste 
18314f1b3e8SDimitry Andric       assert(!need_compare_checksums ||
18414f1b3e8SDimitry Andric              (!old_checksum.empty() && !m_value_checksum.empty()));
185205afe67SEd Maste 
186f034231aSEd Maste       if (first_update)
187f034231aSEd Maste         SetValueDidChange(false);
188344a3780SDimitry Andric       else if (!m_flags.m_value_did_change && !success) {
189f73363f1SDimitry Andric         // The value wasn't gotten successfully, so we mark this as changed if
190f73363f1SDimitry Andric         // the value used to be valid and now isn't
191f034231aSEd Maste         SetValueDidChange(value_was_valid);
19214f1b3e8SDimitry Andric       } else if (need_compare_checksums) {
19314f1b3e8SDimitry Andric         SetValueDidChange(memcmp(&old_checksum[0], &m_value_checksum[0],
19414f1b3e8SDimitry Andric                                  m_value_checksum.size()));
195205afe67SEd Maste       }
196205afe67SEd Maste 
19714f1b3e8SDimitry Andric     } else {
198f034231aSEd Maste       m_error.SetErrorString("out of scope");
199f034231aSEd Maste     }
200f034231aSEd Maste   }
201f034231aSEd Maste   return m_error.Success();
202f034231aSEd Maste }
203f034231aSEd Maste 
UpdateFormatsIfNeeded()20414f1b3e8SDimitry Andric bool ValueObject::UpdateFormatsIfNeeded() {
205145449b1SDimitry Andric   Log *log = GetLog(LLDBLog::DataFormatters);
206ead24645SDimitry Andric   LLDB_LOGF(log,
207ead24645SDimitry Andric             "[%s %p] checking for FormatManager revisions. ValueObject "
20814f1b3e8SDimitry Andric             "rev: %d - Global rev: %d",
2090cac4ca3SEd Maste             GetName().GetCString(), static_cast<void *>(this),
210f034231aSEd Maste             m_last_format_mgr_revision,
211f034231aSEd Maste             DataVisualization::GetCurrentRevision());
212f034231aSEd Maste 
213f034231aSEd Maste   bool any_change = false;
214f034231aSEd Maste 
21514f1b3e8SDimitry Andric   if ((m_last_format_mgr_revision != DataVisualization::GetCurrentRevision())) {
2160cac4ca3SEd Maste     m_last_format_mgr_revision = DataVisualization::GetCurrentRevision();
2170cac4ca3SEd Maste     any_change = true;
2180cac4ca3SEd Maste 
219ac9a064cSDimitry Andric     SetValueFormat(DataVisualization::GetFormat(*this, GetDynamicValueType()));
22014f1b3e8SDimitry Andric     SetSummaryFormat(
22114f1b3e8SDimitry Andric         DataVisualization::GetSummaryFormat(*this, GetDynamicValueType()));
22214f1b3e8SDimitry Andric     SetSyntheticChildren(
22314f1b3e8SDimitry Andric         DataVisualization::GetSyntheticChildren(*this, GetDynamicValueType()));
224f034231aSEd Maste   }
225f034231aSEd Maste 
226f034231aSEd Maste   return any_change;
227f034231aSEd Maste }
228f034231aSEd Maste 
SetNeedsUpdate()22914f1b3e8SDimitry Andric void ValueObject::SetNeedsUpdate() {
230f034231aSEd Maste   m_update_point.SetNeedsUpdate();
23114f1b3e8SDimitry Andric   // We have to clear the value string here so ConstResult children will notice
232f73363f1SDimitry Andric   // if their values are changed by hand (i.e. with SetValueAsCString).
233f034231aSEd Maste   ClearUserVisibleData(eClearUserVisibleDataItemsValue);
234f034231aSEd Maste }
235f034231aSEd Maste 
ClearDynamicTypeInformation()23614f1b3e8SDimitry Andric void ValueObject::ClearDynamicTypeInformation() {
237344a3780SDimitry Andric   m_flags.m_children_count_valid = false;
238344a3780SDimitry Andric   m_flags.m_did_calculate_complete_objc_class_type = false;
239f034231aSEd Maste   m_last_format_mgr_revision = 0;
240e81d9d49SDimitry Andric   m_override_type = CompilerType();
241f034231aSEd Maste   SetValueFormat(lldb::TypeFormatImplSP());
242f034231aSEd Maste   SetSummaryFormat(lldb::TypeSummaryImplSP());
243f034231aSEd Maste   SetSyntheticChildren(lldb::SyntheticChildrenSP());
244f034231aSEd Maste }
245f034231aSEd Maste 
MaybeCalculateCompleteType()24614f1b3e8SDimitry Andric CompilerType ValueObject::MaybeCalculateCompleteType() {
247e81d9d49SDimitry Andric   CompilerType compiler_type(GetCompilerTypeImpl());
248f034231aSEd Maste 
249344a3780SDimitry Andric   if (m_flags.m_did_calculate_complete_objc_class_type) {
250f034231aSEd Maste     if (m_override_type.IsValid())
251f034231aSEd Maste       return m_override_type;
252f034231aSEd Maste     else
253e81d9d49SDimitry Andric       return compiler_type;
254f034231aSEd Maste   }
255f034231aSEd Maste 
256344a3780SDimitry Andric   m_flags.m_did_calculate_complete_objc_class_type = true;
257f034231aSEd Maste 
25814f1b3e8SDimitry Andric   ProcessSP process_sp(
25914f1b3e8SDimitry Andric       GetUpdatePoint().GetExecutionContextRef().GetProcessSP());
260f034231aSEd Maste 
2615f29bb8aSDimitry Andric   if (!process_sp)
2625f29bb8aSDimitry Andric     return compiler_type;
263f034231aSEd Maste 
2645f29bb8aSDimitry Andric   if (auto *runtime =
2655f29bb8aSDimitry Andric           process_sp->GetLanguageRuntime(GetObjectRuntimeLanguage())) {
266e3b55780SDimitry Andric     if (std::optional<CompilerType> complete_type =
2675f29bb8aSDimitry Andric             runtime->GetRuntimeType(compiler_type)) {
268145449b1SDimitry Andric       m_override_type = *complete_type;
269f034231aSEd Maste       if (m_override_type.IsValid())
270f034231aSEd Maste         return m_override_type;
271f034231aSEd Maste     }
272f034231aSEd Maste   }
273e81d9d49SDimitry Andric   return compiler_type;
274f034231aSEd Maste }
275f034231aSEd Maste 
276f034231aSEd Maste 
277f21a844fSEd Maste 
GetDataExtractor()27814f1b3e8SDimitry Andric DataExtractor &ValueObject::GetDataExtractor() {
279f034231aSEd Maste   UpdateValueIfNeeded(false);
280f034231aSEd Maste   return m_data;
281f034231aSEd Maste }
282f034231aSEd Maste 
GetError()283b76161e4SDimitry Andric const Status &ValueObject::GetError() {
284f034231aSEd Maste   UpdateValueIfNeeded(false);
285f034231aSEd Maste   return m_error;
286f034231aSEd Maste }
287f034231aSEd Maste 
GetLocationAsCStringImpl(const Value & value,const DataExtractor & data)28814f1b3e8SDimitry Andric const char *ValueObject::GetLocationAsCStringImpl(const Value &value,
28914f1b3e8SDimitry Andric                                                   const DataExtractor &data) {
29014f1b3e8SDimitry Andric   if (UpdateValueIfNeeded(false)) {
29114f1b3e8SDimitry Andric     if (m_location_str.empty()) {
292f034231aSEd Maste       StreamString sstr;
293f034231aSEd Maste 
294f034231aSEd Maste       Value::ValueType value_type = value.GetValueType();
295f034231aSEd Maste 
29614f1b3e8SDimitry Andric       switch (value_type) {
297344a3780SDimitry Andric       case Value::ValueType::Invalid:
298344a3780SDimitry Andric         m_location_str = "invalid";
299344a3780SDimitry Andric         break;
300344a3780SDimitry Andric       case Value::ValueType::Scalar:
301344a3780SDimitry Andric         if (value.GetContextType() == Value::ContextType::RegisterInfo) {
302f034231aSEd Maste           RegisterInfo *reg_info = value.GetRegisterInfo();
30314f1b3e8SDimitry Andric           if (reg_info) {
304f034231aSEd Maste             if (reg_info->name)
305f034231aSEd Maste               m_location_str = reg_info->name;
306f034231aSEd Maste             else if (reg_info->alt_name)
307f034231aSEd Maste               m_location_str = reg_info->alt_name;
308f034231aSEd Maste             if (m_location_str.empty())
30914f1b3e8SDimitry Andric               m_location_str = (reg_info->encoding == lldb::eEncodingVector)
31014f1b3e8SDimitry Andric                                    ? "vector"
31114f1b3e8SDimitry Andric                                    : "scalar";
312f034231aSEd Maste           }
313f034231aSEd Maste         }
314f034231aSEd Maste         if (m_location_str.empty())
315b60736ecSDimitry Andric           m_location_str = "scalar";
316f034231aSEd Maste         break;
317f034231aSEd Maste 
318344a3780SDimitry Andric       case Value::ValueType::LoadAddress:
319344a3780SDimitry Andric       case Value::ValueType::FileAddress:
320344a3780SDimitry Andric       case Value::ValueType::HostAddress: {
321f034231aSEd Maste         uint32_t addr_nibble_size = data.GetAddressByteSize() * 2;
32214f1b3e8SDimitry Andric         sstr.Printf("0x%*.*llx", addr_nibble_size, addr_nibble_size,
32314f1b3e8SDimitry Andric                     value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS));
324cfca06d7SDimitry Andric         m_location_str = std::string(sstr.GetString());
32514f1b3e8SDimitry Andric       } break;
326f034231aSEd Maste       }
327f034231aSEd Maste     }
328f034231aSEd Maste   }
329f034231aSEd Maste   return m_location_str.c_str();
330f034231aSEd Maste }
331f034231aSEd Maste 
ResolveValue(Scalar & scalar)33214f1b3e8SDimitry Andric bool ValueObject::ResolveValue(Scalar &scalar) {
33314f1b3e8SDimitry Andric   if (UpdateValueIfNeeded(
33414f1b3e8SDimitry Andric           false)) // make sure that you are up to date before returning anything
335f034231aSEd Maste   {
336f034231aSEd Maste     ExecutionContext exe_ctx(GetExecutionContextRef());
337f034231aSEd Maste     Value tmp_value(m_value);
338b1c73532SDimitry Andric     scalar = tmp_value.ResolveValue(&exe_ctx, GetModule().get());
33914f1b3e8SDimitry Andric     if (scalar.IsValid()) {
340f034231aSEd Maste       const uint32_t bitfield_bit_size = GetBitfieldBitSize();
341f034231aSEd Maste       if (bitfield_bit_size)
34214f1b3e8SDimitry Andric         return scalar.ExtractBitfield(bitfield_bit_size,
34314f1b3e8SDimitry Andric                                       GetBitfieldBitOffset());
344f034231aSEd Maste       return true;
345f034231aSEd Maste     }
346f034231aSEd Maste   }
347f034231aSEd Maste   return false;
348f034231aSEd Maste }
349f034231aSEd Maste 
IsLogicalTrue(Status & error)350b76161e4SDimitry Andric bool ValueObject::IsLogicalTrue(Status &error) {
35114f1b3e8SDimitry Andric   if (Language *language = Language::FindPlugin(GetObjectRuntimeLanguage())) {
352e81d9d49SDimitry Andric     LazyBool is_logical_true = language->IsLogicalTrue(*this, error);
35314f1b3e8SDimitry Andric     switch (is_logical_true) {
354e81d9d49SDimitry Andric     case eLazyBoolYes:
355e81d9d49SDimitry Andric     case eLazyBoolNo:
356e81d9d49SDimitry Andric       return (is_logical_true == true);
357e81d9d49SDimitry Andric     case eLazyBoolCalculate:
358e81d9d49SDimitry Andric       break;
359e81d9d49SDimitry Andric     }
360e81d9d49SDimitry Andric   }
361e81d9d49SDimitry Andric 
362e81d9d49SDimitry Andric   Scalar scalar_value;
363e81d9d49SDimitry Andric 
36414f1b3e8SDimitry Andric   if (!ResolveValue(scalar_value)) {
365e81d9d49SDimitry Andric     error.SetErrorString("failed to get a scalar result");
366e81d9d49SDimitry Andric     return false;
367e81d9d49SDimitry Andric   }
368e81d9d49SDimitry Andric 
369e81d9d49SDimitry Andric   bool ret;
37094994d37SDimitry Andric   ret = scalar_value.ULongLong(1) != 0;
371e81d9d49SDimitry Andric   error.Clear();
372e81d9d49SDimitry Andric   return ret;
373e81d9d49SDimitry Andric }
374e81d9d49SDimitry Andric 
GetChildAtIndex(uint32_t idx,bool can_create)375ac9a064cSDimitry Andric ValueObjectSP ValueObject::GetChildAtIndex(uint32_t idx, bool can_create) {
376f034231aSEd Maste   ValueObjectSP child_sp;
377f034231aSEd Maste   // We may need to update our value if we are dynamic
378f034231aSEd Maste   if (IsPossibleDynamicType())
379f034231aSEd Maste     UpdateValueIfNeeded(false);
380ac9a064cSDimitry Andric   if (idx < GetNumChildrenIgnoringErrors()) {
381f034231aSEd Maste     // Check if we have already made the child value object?
38214f1b3e8SDimitry Andric     if (can_create && !m_children.HasChildAtIndex(idx)) {
383f034231aSEd Maste       // No we haven't created the child at this index, so lets have our
384f034231aSEd Maste       // subclass do it and cache the result for quick future access.
385ac9a064cSDimitry Andric       m_children.SetChildAtIndex(idx, CreateChildAtIndex(idx));
386f034231aSEd Maste     }
387f034231aSEd Maste 
388f034231aSEd Maste     ValueObject *child = m_children.GetChildAtIndex(idx);
3895f29bb8aSDimitry Andric     if (child != nullptr)
390f034231aSEd Maste       return child->GetSP();
391f034231aSEd Maste   }
392f034231aSEd Maste   return child_sp;
393f034231aSEd Maste }
394f034231aSEd Maste 
395f034231aSEd Maste lldb::ValueObjectSP
GetChildAtNamePath(llvm::ArrayRef<llvm::StringRef> names)3967fa27ce4SDimitry Andric ValueObject::GetChildAtNamePath(llvm::ArrayRef<llvm::StringRef> names) {
397f21a844fSEd Maste   if (names.size() == 0)
398f21a844fSEd Maste     return GetSP();
399f21a844fSEd Maste   ValueObjectSP root(GetSP());
4007fa27ce4SDimitry Andric   for (llvm::StringRef name : names) {
4017fa27ce4SDimitry Andric     root = root->GetChildMemberWithName(name);
40214f1b3e8SDimitry Andric     if (!root) {
403f21a844fSEd Maste       return root;
404f21a844fSEd Maste     }
405f21a844fSEd Maste   }
406f21a844fSEd Maste   return root;
407f21a844fSEd Maste }
408f21a844fSEd Maste 
GetIndexOfChildWithName(llvm::StringRef name)4097fa27ce4SDimitry Andric size_t ValueObject::GetIndexOfChildWithName(llvm::StringRef name) {
410f034231aSEd Maste   bool omit_empty_base_classes = true;
4117fa27ce4SDimitry Andric   return GetCompilerType().GetIndexOfChildWithName(name,
41214f1b3e8SDimitry Andric                                                    omit_empty_base_classes);
413f034231aSEd Maste }
414f034231aSEd Maste 
GetChildMemberWithName(llvm::StringRef name,bool can_create)4157fa27ce4SDimitry Andric ValueObjectSP ValueObject::GetChildMemberWithName(llvm::StringRef name,
41614f1b3e8SDimitry Andric                                                   bool can_create) {
417cfca06d7SDimitry Andric   // We may need to update our value if we are dynamic.
418f034231aSEd Maste   if (IsPossibleDynamicType())
419f034231aSEd Maste     UpdateValueIfNeeded(false);
420f034231aSEd Maste 
421cfca06d7SDimitry Andric   // When getting a child by name, it could be buried inside some base classes
422cfca06d7SDimitry Andric   // (which really aren't part of the expression path), so we need a vector of
423cfca06d7SDimitry Andric   // indexes that can get us down to the correct child.
424f034231aSEd Maste   std::vector<uint32_t> child_indexes;
425f034231aSEd Maste   bool omit_empty_base_classes = true;
426706b4fc4SDimitry Andric 
427706b4fc4SDimitry Andric   if (!GetCompilerType().IsValid())
428706b4fc4SDimitry Andric     return ValueObjectSP();
429706b4fc4SDimitry Andric 
43014f1b3e8SDimitry Andric   const size_t num_child_indexes =
43114f1b3e8SDimitry Andric       GetCompilerType().GetIndexOfChildMemberWithName(
4327fa27ce4SDimitry Andric           name, omit_empty_base_classes, child_indexes);
433cfca06d7SDimitry Andric   if (num_child_indexes == 0)
434cfca06d7SDimitry Andric     return nullptr;
435f034231aSEd Maste 
436cfca06d7SDimitry Andric   ValueObjectSP child_sp = GetSP();
437cfca06d7SDimitry Andric   for (uint32_t idx : child_indexes)
438cfca06d7SDimitry Andric     if (child_sp)
439cfca06d7SDimitry Andric       child_sp = child_sp->GetChildAtIndex(idx, can_create);
440f034231aSEd Maste   return child_sp;
441f034231aSEd Maste }
442f034231aSEd Maste 
GetNumChildren(uint32_t max)443ac9a064cSDimitry Andric llvm::Expected<uint32_t> ValueObject::GetNumChildren(uint32_t max) {
444f034231aSEd Maste   UpdateValueIfNeeded();
445e81d9d49SDimitry Andric 
44614f1b3e8SDimitry Andric   if (max < UINT32_MAX) {
447344a3780SDimitry Andric     if (m_flags.m_children_count_valid) {
448e81d9d49SDimitry Andric       size_t children_count = m_children.GetChildrenCount();
449e81d9d49SDimitry Andric       return children_count <= max ? children_count : max;
45014f1b3e8SDimitry Andric     } else
451e81d9d49SDimitry Andric       return CalculateNumChildren(max);
452e81d9d49SDimitry Andric   }
453e81d9d49SDimitry Andric 
454344a3780SDimitry Andric   if (!m_flags.m_children_count_valid) {
455ac9a064cSDimitry Andric     auto num_children_or_err = CalculateNumChildren();
456ac9a064cSDimitry Andric     if (num_children_or_err)
457ac9a064cSDimitry Andric       SetNumChildren(*num_children_or_err);
458ac9a064cSDimitry Andric     else
459ac9a064cSDimitry Andric       return num_children_or_err;
460f034231aSEd Maste   }
461f034231aSEd Maste   return m_children.GetChildrenCount();
462f034231aSEd Maste }
463f034231aSEd Maste 
GetNumChildrenIgnoringErrors(uint32_t max)464ac9a064cSDimitry Andric uint32_t ValueObject::GetNumChildrenIgnoringErrors(uint32_t max) {
465ac9a064cSDimitry Andric   auto value_or_err = GetNumChildren(max);
466ac9a064cSDimitry Andric   if (value_or_err)
467ac9a064cSDimitry Andric     return *value_or_err;
468ac9a064cSDimitry Andric   LLDB_LOG_ERRORV(GetLog(LLDBLog::DataFormatters), value_or_err.takeError(),
469ac9a064cSDimitry Andric                   "{0}");
470ac9a064cSDimitry Andric   return 0;
471ac9a064cSDimitry Andric }
472ac9a064cSDimitry Andric 
MightHaveChildren()47314f1b3e8SDimitry Andric bool ValueObject::MightHaveChildren() {
474f034231aSEd Maste   bool has_children = false;
475f034231aSEd Maste   const uint32_t type_info = GetTypeInfo();
47614f1b3e8SDimitry Andric   if (type_info) {
47714f1b3e8SDimitry Andric     if (type_info & (eTypeHasChildren | eTypeIsPointer | eTypeIsReference))
478f034231aSEd Maste       has_children = true;
47914f1b3e8SDimitry Andric   } else {
480ac9a064cSDimitry Andric     has_children = GetNumChildrenIgnoringErrors() > 0;
481f034231aSEd Maste   }
482f034231aSEd Maste   return has_children;
483f034231aSEd Maste }
484f034231aSEd Maste 
485f034231aSEd Maste // Should only be called by ValueObject::GetNumChildren()
SetNumChildren(uint32_t num_children)486ac9a064cSDimitry Andric void ValueObject::SetNumChildren(uint32_t num_children) {
487344a3780SDimitry Andric   m_flags.m_children_count_valid = true;
488f034231aSEd Maste   m_children.SetChildrenCount(num_children);
489f034231aSEd Maste }
490f034231aSEd Maste 
CreateChildAtIndex(size_t idx)491ac9a064cSDimitry Andric ValueObject *ValueObject::CreateChildAtIndex(size_t idx) {
492f034231aSEd Maste   bool omit_empty_base_classes = true;
493ac9a064cSDimitry Andric   bool ignore_array_bounds = false;
494ac9a064cSDimitry Andric   std::string child_name;
495f034231aSEd Maste   uint32_t child_byte_size = 0;
496f034231aSEd Maste   int32_t child_byte_offset = 0;
497f034231aSEd Maste   uint32_t child_bitfield_bit_size = 0;
498f034231aSEd Maste   uint32_t child_bitfield_bit_offset = 0;
499f034231aSEd Maste   bool child_is_base_class = false;
500f034231aSEd Maste   bool child_is_deref_of_parent = false;
501e81d9d49SDimitry Andric   uint64_t language_flags = 0;
502ac9a064cSDimitry Andric   const bool transparent_pointers = true;
503f034231aSEd Maste 
504f034231aSEd Maste   ExecutionContext exe_ctx(GetExecutionContextRef());
505f034231aSEd Maste 
506ac9a064cSDimitry Andric   auto child_compiler_type_or_err =
507ac9a064cSDimitry Andric       GetCompilerType().GetChildCompilerTypeAtIndex(
50814f1b3e8SDimitry Andric           &exe_ctx, idx, transparent_pointers, omit_empty_base_classes,
509ac9a064cSDimitry Andric           ignore_array_bounds, child_name, child_byte_size, child_byte_offset,
510ac9a064cSDimitry Andric           child_bitfield_bit_size, child_bitfield_bit_offset,
511ac9a064cSDimitry Andric           child_is_base_class, child_is_deref_of_parent, this, language_flags);
512ac9a064cSDimitry Andric   if (!child_compiler_type_or_err || !child_compiler_type_or_err->IsValid()) {
513ac9a064cSDimitry Andric     LLDB_LOG_ERROR(GetLog(LLDBLog::Types),
514ac9a064cSDimitry Andric                    child_compiler_type_or_err.takeError(),
515ac9a064cSDimitry Andric                    "could not find child: {0}");
516ac9a064cSDimitry Andric     return nullptr;
517ac9a064cSDimitry Andric   }
518f034231aSEd Maste 
519ac9a064cSDimitry Andric   return new ValueObjectChild(
520ac9a064cSDimitry Andric       *this, *child_compiler_type_or_err, ConstString(child_name),
521ac9a064cSDimitry Andric       child_byte_size, child_byte_offset, child_bitfield_bit_size,
522ac9a064cSDimitry Andric       child_bitfield_bit_offset, child_is_base_class, child_is_deref_of_parent,
523ac9a064cSDimitry Andric       eAddressTypeInvalid, language_flags);
524ac9a064cSDimitry Andric }
525f034231aSEd Maste 
CreateSyntheticArrayMember(size_t idx)526ac9a064cSDimitry Andric ValueObject *ValueObject::CreateSyntheticArrayMember(size_t idx) {
527ac9a064cSDimitry Andric   bool omit_empty_base_classes = true;
528ac9a064cSDimitry Andric   bool ignore_array_bounds = true;
529ac9a064cSDimitry Andric   std::string child_name;
530ac9a064cSDimitry Andric   uint32_t child_byte_size = 0;
531ac9a064cSDimitry Andric   int32_t child_byte_offset = 0;
532ac9a064cSDimitry Andric   uint32_t child_bitfield_bit_size = 0;
533ac9a064cSDimitry Andric   uint32_t child_bitfield_bit_offset = 0;
534ac9a064cSDimitry Andric   bool child_is_base_class = false;
535ac9a064cSDimitry Andric   bool child_is_deref_of_parent = false;
536ac9a064cSDimitry Andric   uint64_t language_flags = 0;
537ac9a064cSDimitry Andric   const bool transparent_pointers = false;
538ac9a064cSDimitry Andric 
539ac9a064cSDimitry Andric   ExecutionContext exe_ctx(GetExecutionContextRef());
540ac9a064cSDimitry Andric 
541ac9a064cSDimitry Andric   auto child_compiler_type_or_err =
542ac9a064cSDimitry Andric       GetCompilerType().GetChildCompilerTypeAtIndex(
543ac9a064cSDimitry Andric           &exe_ctx, 0, transparent_pointers, omit_empty_base_classes,
544ac9a064cSDimitry Andric           ignore_array_bounds, child_name, child_byte_size, child_byte_offset,
545ac9a064cSDimitry Andric           child_bitfield_bit_size, child_bitfield_bit_offset,
546ac9a064cSDimitry Andric           child_is_base_class, child_is_deref_of_parent, this, language_flags);
547ac9a064cSDimitry Andric   if (!child_compiler_type_or_err) {
548ac9a064cSDimitry Andric     LLDB_LOG_ERROR(GetLog(LLDBLog::Types),
549ac9a064cSDimitry Andric                    child_compiler_type_or_err.takeError(),
550ac9a064cSDimitry Andric                    "could not find child: {0}");
551ac9a064cSDimitry Andric     return nullptr;
552ac9a064cSDimitry Andric   }
553ac9a064cSDimitry Andric 
554ac9a064cSDimitry Andric   if (child_compiler_type_or_err->IsValid()) {
555ac9a064cSDimitry Andric     child_byte_offset += child_byte_size * idx;
556ac9a064cSDimitry Andric 
557ac9a064cSDimitry Andric     return new ValueObjectChild(
558ac9a064cSDimitry Andric         *this, *child_compiler_type_or_err, ConstString(child_name),
559ac9a064cSDimitry Andric         child_byte_size, child_byte_offset, child_bitfield_bit_size,
560ac9a064cSDimitry Andric         child_bitfield_bit_offset, child_is_base_class,
561ac9a064cSDimitry Andric         child_is_deref_of_parent, eAddressTypeInvalid, language_flags);
562f034231aSEd Maste   }
563f034231aSEd Maste 
564cfca06d7SDimitry Andric   // In case of an incomplete type, try to use the ValueObject's
565cfca06d7SDimitry Andric   // synthetic value to create the child ValueObject.
566ac9a064cSDimitry Andric   if (ValueObjectSP synth_valobj_sp = GetSyntheticValue())
567ac9a064cSDimitry Andric     return synth_valobj_sp->GetChildAtIndex(idx, /*can_create=*/true).get();
568cfca06d7SDimitry Andric 
569ac9a064cSDimitry Andric   return nullptr;
570f034231aSEd Maste }
571f034231aSEd Maste 
GetSummaryAsCString(TypeSummaryImpl * summary_ptr,std::string & destination,lldb::LanguageType lang)57214f1b3e8SDimitry Andric bool ValueObject::GetSummaryAsCString(TypeSummaryImpl *summary_ptr,
573e81d9d49SDimitry Andric                                       std::string &destination,
57414f1b3e8SDimitry Andric                                       lldb::LanguageType lang) {
57514f1b3e8SDimitry Andric   return GetSummaryAsCString(summary_ptr, destination,
57614f1b3e8SDimitry Andric                              TypeSummaryOptions().SetLanguage(lang));
577205afe67SEd Maste }
578205afe67SEd Maste 
GetSummaryAsCString(TypeSummaryImpl * summary_ptr,std::string & destination,const TypeSummaryOptions & options)57914f1b3e8SDimitry Andric bool ValueObject::GetSummaryAsCString(TypeSummaryImpl *summary_ptr,
580205afe67SEd Maste                                       std::string &destination,
58114f1b3e8SDimitry Andric                                       const TypeSummaryOptions &options) {
582f034231aSEd Maste   destination.clear();
583f034231aSEd Maste 
584e3b55780SDimitry Andric   // If we have a forcefully completed type, don't try and show a summary from
585e3b55780SDimitry Andric   // a valid summary string or function because the type is not complete and
586e3b55780SDimitry Andric   // no member variables or member functions will be available.
587e3b55780SDimitry Andric   if (GetCompilerType().IsForcefullyCompleted()) {
588e3b55780SDimitry Andric       destination = "<incomplete type>";
589e3b55780SDimitry Andric       return true;
590e3b55780SDimitry Andric   }
591e3b55780SDimitry Andric 
592f73363f1SDimitry Andric   // ideally we would like to bail out if passing NULL, but if we do so we end
593f73363f1SDimitry Andric   // up not providing the summary for function pointers anymore
594344a3780SDimitry Andric   if (/*summary_ptr == NULL ||*/ m_flags.m_is_getting_summary)
595f034231aSEd Maste     return false;
596f034231aSEd Maste 
597344a3780SDimitry Andric   m_flags.m_is_getting_summary = true;
598f034231aSEd Maste 
599e81d9d49SDimitry Andric   TypeSummaryOptions actual_options(options);
600e81d9d49SDimitry Andric 
601e81d9d49SDimitry Andric   if (actual_options.GetLanguage() == lldb::eLanguageTypeUnknown)
602e81d9d49SDimitry Andric     actual_options.SetLanguage(GetPreferredDisplayLanguage());
603e81d9d49SDimitry Andric 
60414f1b3e8SDimitry Andric   // this is a hot path in code and we prefer to avoid setting this string all
605f73363f1SDimitry Andric   // too often also clearing out other information that we might care to see in
606f73363f1SDimitry Andric   // a crash log. might be useful in very specific situations though.
60714f1b3e8SDimitry Andric   /*Host::SetCrashDescriptionWithFormat("Trying to fetch a summary for %s %s.
60814f1b3e8SDimitry Andric    Summary provider's description is %s",
609f034231aSEd Maste    GetTypeName().GetCString(),
610f034231aSEd Maste    GetName().GetCString(),
611f034231aSEd Maste    summary_ptr->GetDescription().c_str());*/
612f034231aSEd Maste 
61314f1b3e8SDimitry Andric   if (UpdateValueIfNeeded(false) && summary_ptr) {
614f034231aSEd Maste     if (HasSyntheticValue())
61514f1b3e8SDimitry Andric       m_synthetic_value->UpdateValueIfNeeded(); // the summary might depend on
61614f1b3e8SDimitry Andric                                                 // the synthetic children being
61714f1b3e8SDimitry Andric                                                 // up-to-date (e.g. ${svar%#})
618e81d9d49SDimitry Andric     summary_ptr->FormatObject(this, destination, actual_options);
619f034231aSEd Maste   }
620344a3780SDimitry Andric   m_flags.m_is_getting_summary = false;
621f034231aSEd Maste   return !destination.empty();
622f034231aSEd Maste }
623f034231aSEd Maste 
GetSummaryAsCString(lldb::LanguageType lang)62414f1b3e8SDimitry Andric const char *ValueObject::GetSummaryAsCString(lldb::LanguageType lang) {
62514f1b3e8SDimitry Andric   if (UpdateValueIfNeeded(true) && m_summary_str.empty()) {
626e81d9d49SDimitry Andric     TypeSummaryOptions summary_options;
627e81d9d49SDimitry Andric     summary_options.SetLanguage(lang);
62814f1b3e8SDimitry Andric     GetSummaryAsCString(GetSummaryFormat().get(), m_summary_str,
629e81d9d49SDimitry Andric                         summary_options);
630f034231aSEd Maste   }
631f034231aSEd Maste   if (m_summary_str.empty())
6325f29bb8aSDimitry Andric     return nullptr;
633f034231aSEd Maste   return m_summary_str.c_str();
634f034231aSEd Maste }
635f034231aSEd Maste 
GetSummaryAsCString(std::string & destination,const TypeSummaryOptions & options)63614f1b3e8SDimitry Andric bool ValueObject::GetSummaryAsCString(std::string &destination,
63714f1b3e8SDimitry Andric                                       const TypeSummaryOptions &options) {
63814f1b3e8SDimitry Andric   return GetSummaryAsCString(GetSummaryFormat().get(), destination, options);
639205afe67SEd Maste }
640205afe67SEd Maste 
IsCStringContainer(bool check_pointer)64114f1b3e8SDimitry Andric bool ValueObject::IsCStringContainer(bool check_pointer) {
642e81d9d49SDimitry Andric   CompilerType pointee_or_element_compiler_type;
643e81d9d49SDimitry Andric   const Flags type_flags(GetTypeInfo(&pointee_or_element_compiler_type));
644205afe67SEd Maste   bool is_char_arr_ptr(type_flags.AnySet(eTypeIsArray | eTypeIsPointer) &&
645e81d9d49SDimitry Andric                        pointee_or_element_compiler_type.IsCharType());
646f034231aSEd Maste   if (!is_char_arr_ptr)
647f034231aSEd Maste     return false;
648f034231aSEd Maste   if (!check_pointer)
649f034231aSEd Maste     return true;
650205afe67SEd Maste   if (type_flags.Test(eTypeIsArray))
651f034231aSEd Maste     return true;
652f034231aSEd Maste   addr_t cstr_address = LLDB_INVALID_ADDRESS;
653f034231aSEd Maste   AddressType cstr_address_type = eAddressTypeInvalid;
654cfca06d7SDimitry Andric   cstr_address = GetPointerValue(&cstr_address_type);
655f034231aSEd Maste   return (cstr_address != LLDB_INVALID_ADDRESS);
656f034231aSEd Maste }
657f034231aSEd Maste 
GetPointeeData(DataExtractor & data,uint32_t item_idx,uint32_t item_count)65814f1b3e8SDimitry Andric size_t ValueObject::GetPointeeData(DataExtractor &data, uint32_t item_idx,
65914f1b3e8SDimitry Andric                                    uint32_t item_count) {
660e81d9d49SDimitry Andric   CompilerType pointee_or_element_compiler_type;
661e81d9d49SDimitry Andric   const uint32_t type_info = GetTypeInfo(&pointee_or_element_compiler_type);
662205afe67SEd Maste   const bool is_pointer_type = type_info & eTypeIsPointer;
663205afe67SEd Maste   const bool is_array_type = type_info & eTypeIsArray;
664f034231aSEd Maste   if (!(is_pointer_type || is_array_type))
665f034231aSEd Maste     return 0;
666f034231aSEd Maste 
667f034231aSEd Maste   if (item_count == 0)
668f034231aSEd Maste     return 0;
669f034231aSEd Maste 
67012bd4897SEd Maste   ExecutionContext exe_ctx(GetExecutionContextRef());
67112bd4897SEd Maste 
672e3b55780SDimitry Andric   std::optional<uint64_t> item_type_size =
67394994d37SDimitry Andric       pointee_or_element_compiler_type.GetByteSize(
67414f1b3e8SDimitry Andric           exe_ctx.GetBestExecutionContextScope());
67594994d37SDimitry Andric   if (!item_type_size)
67694994d37SDimitry Andric     return 0;
67794994d37SDimitry Andric   const uint64_t bytes = item_count * *item_type_size;
67894994d37SDimitry Andric   const uint64_t offset = item_idx * *item_type_size;
679f034231aSEd Maste 
680f034231aSEd Maste   if (item_idx == 0 && item_count == 1) // simply a deref
681f034231aSEd Maste   {
68214f1b3e8SDimitry Andric     if (is_pointer_type) {
683b76161e4SDimitry Andric       Status error;
684f034231aSEd Maste       ValueObjectSP pointee_sp = Dereference(error);
6855f29bb8aSDimitry Andric       if (error.Fail() || pointee_sp.get() == nullptr)
686f034231aSEd Maste         return 0;
6870cac4ca3SEd Maste       return pointee_sp->GetData(data, error);
68814f1b3e8SDimitry Andric     } else {
6897fa27ce4SDimitry Andric       ValueObjectSP child_sp = GetChildAtIndex(0);
6905f29bb8aSDimitry Andric       if (child_sp.get() == nullptr)
691f034231aSEd Maste         return 0;
692b76161e4SDimitry Andric       Status error;
6930cac4ca3SEd Maste       return child_sp->GetData(data, error);
694f034231aSEd Maste     }
695f034231aSEd Maste     return true;
69614f1b3e8SDimitry Andric   } else /* (items > 1) */
697f034231aSEd Maste   {
698b76161e4SDimitry Andric     Status error;
6995f29bb8aSDimitry Andric     lldb_private::DataBufferHeap *heap_buf_ptr = nullptr;
70014f1b3e8SDimitry Andric     lldb::DataBufferSP data_sp(heap_buf_ptr =
70114f1b3e8SDimitry Andric                                    new lldb_private::DataBufferHeap());
702f034231aSEd Maste 
703f034231aSEd Maste     AddressType addr_type;
70414f1b3e8SDimitry Andric     lldb::addr_t addr = is_pointer_type ? GetPointerValue(&addr_type)
70514f1b3e8SDimitry Andric                                         : GetAddressOf(true, &addr_type);
706f034231aSEd Maste 
70714f1b3e8SDimitry Andric     switch (addr_type) {
70814f1b3e8SDimitry Andric     case eAddressTypeFile: {
709f034231aSEd Maste       ModuleSP module_sp(GetModule());
71014f1b3e8SDimitry Andric       if (module_sp) {
711f034231aSEd Maste         addr = addr + offset;
712f034231aSEd Maste         Address so_addr;
713f034231aSEd Maste         module_sp->ResolveFileAddress(addr, so_addr);
714f034231aSEd Maste         ExecutionContext exe_ctx(GetExecutionContextRef());
715f034231aSEd Maste         Target *target = exe_ctx.GetTargetPtr();
71614f1b3e8SDimitry Andric         if (target) {
717f034231aSEd Maste           heap_buf_ptr->SetByteSize(bytes);
71814f1b3e8SDimitry Andric           size_t bytes_read = target->ReadMemory(
719344a3780SDimitry Andric               so_addr, heap_buf_ptr->GetBytes(), bytes, error, true);
72014f1b3e8SDimitry Andric           if (error.Success()) {
721f034231aSEd Maste             data.SetData(data_sp);
722f034231aSEd Maste             return bytes_read;
723f034231aSEd Maste           }
724f034231aSEd Maste         }
725f034231aSEd Maste       }
72614f1b3e8SDimitry Andric     } break;
72714f1b3e8SDimitry Andric     case eAddressTypeLoad: {
728f034231aSEd Maste       ExecutionContext exe_ctx(GetExecutionContextRef());
729f034231aSEd Maste       Process *process = exe_ctx.GetProcessPtr();
73014f1b3e8SDimitry Andric       if (process) {
731f034231aSEd Maste         heap_buf_ptr->SetByteSize(bytes);
73214f1b3e8SDimitry Andric         size_t bytes_read = process->ReadMemory(
73314f1b3e8SDimitry Andric             addr + offset, heap_buf_ptr->GetBytes(), bytes, error);
73414f1b3e8SDimitry Andric         if (error.Success() || bytes_read > 0) {
735f034231aSEd Maste           data.SetData(data_sp);
736f034231aSEd Maste           return bytes_read;
737f034231aSEd Maste         }
738f034231aSEd Maste       }
73914f1b3e8SDimitry Andric     } break;
74014f1b3e8SDimitry Andric     case eAddressTypeHost: {
74194994d37SDimitry Andric       auto max_bytes =
74214f1b3e8SDimitry Andric           GetCompilerType().GetByteSize(exe_ctx.GetBestExecutionContextScope());
74394994d37SDimitry Andric       if (max_bytes && *max_bytes > offset) {
74494994d37SDimitry Andric         size_t bytes_read = std::min<uint64_t>(*max_bytes - offset, bytes);
7455e95aa85SEd Maste         addr = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
746e81d9d49SDimitry Andric         if (addr == 0 || addr == LLDB_INVALID_ADDRESS)
7475e95aa85SEd Maste           break;
748f034231aSEd Maste         heap_buf_ptr->CopyData((uint8_t *)(addr + offset), bytes_read);
749f034231aSEd Maste         data.SetData(data_sp);
750f034231aSEd Maste         return bytes_read;
751f034231aSEd Maste       }
75214f1b3e8SDimitry Andric     } break;
753f034231aSEd Maste     case eAddressTypeInvalid:
754f034231aSEd Maste       break;
755f034231aSEd Maste     }
756f034231aSEd Maste   }
757f034231aSEd Maste   return 0;
758f034231aSEd Maste }
759f034231aSEd Maste 
GetData(DataExtractor & data,Status & error)760b76161e4SDimitry Andric uint64_t ValueObject::GetData(DataExtractor &data, Status &error) {
761f034231aSEd Maste   UpdateValueIfNeeded(false);
762f034231aSEd Maste   ExecutionContext exe_ctx(GetExecutionContextRef());
763ead24645SDimitry Andric   error = m_value.GetValueAsData(&exe_ctx, data, GetModule().get());
76414f1b3e8SDimitry Andric   if (error.Fail()) {
76514f1b3e8SDimitry Andric     if (m_data.GetByteSize()) {
766f034231aSEd Maste       data = m_data;
767e81d9d49SDimitry Andric       error.Clear();
768f034231aSEd Maste       return data.GetByteSize();
76914f1b3e8SDimitry Andric     } else {
770f034231aSEd Maste       return 0;
771f034231aSEd Maste     }
772f034231aSEd Maste   }
773f034231aSEd Maste   data.SetAddressByteSize(m_data.GetAddressByteSize());
774f034231aSEd Maste   data.SetByteOrder(m_data.GetByteOrder());
775f034231aSEd Maste   return data.GetByteSize();
776f034231aSEd Maste }
777f034231aSEd Maste 
SetData(DataExtractor & data,Status & error)778b76161e4SDimitry Andric bool ValueObject::SetData(DataExtractor &data, Status &error) {
779f034231aSEd Maste   error.Clear();
780f034231aSEd Maste   // Make sure our value is up to date first so that our location and location
781f034231aSEd Maste   // type is valid.
78214f1b3e8SDimitry Andric   if (!UpdateValueIfNeeded(false)) {
783f034231aSEd Maste     error.SetErrorString("unable to read value");
784f034231aSEd Maste     return false;
785f034231aSEd Maste   }
786f034231aSEd Maste 
787f034231aSEd Maste   uint64_t count = 0;
788e81d9d49SDimitry Andric   const Encoding encoding = GetCompilerType().GetEncoding(count);
789f034231aSEd Maste 
790145449b1SDimitry Andric   const size_t byte_size = GetByteSize().value_or(0);
791f034231aSEd Maste 
792f034231aSEd Maste   Value::ValueType value_type = m_value.GetValueType();
793f034231aSEd Maste 
79414f1b3e8SDimitry Andric   switch (value_type) {
795344a3780SDimitry Andric   case Value::ValueType::Invalid:
796344a3780SDimitry Andric     error.SetErrorString("invalid location");
797344a3780SDimitry Andric     return false;
798344a3780SDimitry Andric   case Value::ValueType::Scalar: {
799b76161e4SDimitry Andric     Status set_error =
80014f1b3e8SDimitry Andric         m_value.GetScalar().SetValueFromData(data, encoding, byte_size);
801f034231aSEd Maste 
80214f1b3e8SDimitry Andric     if (!set_error.Success()) {
80314f1b3e8SDimitry Andric       error.SetErrorStringWithFormat("unable to set scalar value: %s",
80414f1b3e8SDimitry Andric                                      set_error.AsCString());
805f034231aSEd Maste       return false;
806f034231aSEd Maste     }
80714f1b3e8SDimitry Andric   } break;
808344a3780SDimitry Andric   case Value::ValueType::LoadAddress: {
809f034231aSEd Maste     // If it is a load address, then the scalar value is the storage location
810f034231aSEd Maste     // of the data, and we have to shove this value down to that load location.
811f034231aSEd Maste     ExecutionContext exe_ctx(GetExecutionContextRef());
812f034231aSEd Maste     Process *process = exe_ctx.GetProcessPtr();
81314f1b3e8SDimitry Andric     if (process) {
814f034231aSEd Maste       addr_t target_addr = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
81514f1b3e8SDimitry Andric       size_t bytes_written = process->WriteMemory(
81614f1b3e8SDimitry Andric           target_addr, data.GetDataStart(), byte_size, error);
817f034231aSEd Maste       if (!error.Success())
818f034231aSEd Maste         return false;
81914f1b3e8SDimitry Andric       if (bytes_written != byte_size) {
820f034231aSEd Maste         error.SetErrorString("unable to write value to memory");
821f034231aSEd Maste         return false;
822f034231aSEd Maste       }
823f034231aSEd Maste     }
82414f1b3e8SDimitry Andric   } break;
825344a3780SDimitry Andric   case Value::ValueType::HostAddress: {
82614f1b3e8SDimitry Andric     // If it is a host address, then we stuff the scalar as a DataBuffer into
82714f1b3e8SDimitry Andric     // the Value's data.
828f034231aSEd Maste     DataBufferSP buffer_sp(new DataBufferHeap(byte_size, 0));
829f034231aSEd Maste     m_data.SetData(buffer_sp, 0);
83014f1b3e8SDimitry Andric     data.CopyByteOrderedData(0, byte_size,
831f034231aSEd Maste                              const_cast<uint8_t *>(m_data.GetDataStart()),
83214f1b3e8SDimitry Andric                              byte_size, m_data.GetByteOrder());
833f034231aSEd Maste     m_value.GetScalar() = (uintptr_t)m_data.GetDataStart();
83414f1b3e8SDimitry Andric   } break;
835344a3780SDimitry Andric   case Value::ValueType::FileAddress:
836f034231aSEd Maste     break;
837f034231aSEd Maste   }
838f034231aSEd Maste 
839f73363f1SDimitry Andric   // If we have reached this point, then we have successfully changed the
840f73363f1SDimitry Andric   // value.
841f034231aSEd Maste   SetNeedsUpdate();
842f034231aSEd Maste   return true;
843f034231aSEd Maste }
844f034231aSEd Maste 
CopyStringDataToBufferSP(const StreamString & source,lldb::WritableDataBufferSP & destination)84514f1b3e8SDimitry Andric static bool CopyStringDataToBufferSP(const StreamString &source,
846145449b1SDimitry Andric                                      lldb::WritableDataBufferSP &destination) {
847c0981da4SDimitry Andric   llvm::StringRef src = source.GetString();
848145449b1SDimitry Andric   src = src.rtrim('\0');
849c0981da4SDimitry Andric   destination = std::make_shared<DataBufferHeap>(src.size(), 0);
850c0981da4SDimitry Andric   memcpy(destination->GetBytes(), src.data(), src.size());
851205afe67SEd Maste   return true;
852205afe67SEd Maste }
853205afe67SEd Maste 
854e81d9d49SDimitry Andric std::pair<size_t, bool>
ReadPointedString(lldb::WritableDataBufferSP & buffer_sp,Status & error,bool honor_array)855145449b1SDimitry Andric ValueObject::ReadPointedString(lldb::WritableDataBufferSP &buffer_sp,
8564df029ccSDimitry Andric                                Status &error, bool honor_array) {
857e81d9d49SDimitry Andric   bool was_capped = false;
858205afe67SEd Maste   StreamString s;
859f034231aSEd Maste   ExecutionContext exe_ctx(GetExecutionContextRef());
860f034231aSEd Maste   Target *target = exe_ctx.GetTargetPtr();
861f034231aSEd Maste 
86214f1b3e8SDimitry Andric   if (!target) {
863f034231aSEd Maste     s << "<no target to read from>";
864f034231aSEd Maste     error.SetErrorString("no target to read from");
865205afe67SEd Maste     CopyStringDataToBufferSP(s, buffer_sp);
866e81d9d49SDimitry Andric     return {0, was_capped};
867f034231aSEd Maste   }
868f034231aSEd Maste 
8694df029ccSDimitry Andric   const auto max_length = target->GetMaximumSizeOfStringSummary();
870f034231aSEd Maste 
871f034231aSEd Maste   size_t bytes_read = 0;
872f034231aSEd Maste   size_t total_bytes_read = 0;
873f034231aSEd Maste 
874e81d9d49SDimitry Andric   CompilerType compiler_type = GetCompilerType();
875e81d9d49SDimitry Andric   CompilerType elem_or_pointee_compiler_type;
876e81d9d49SDimitry Andric   const Flags type_flags(GetTypeInfo(&elem_or_pointee_compiler_type));
877205afe67SEd Maste   if (type_flags.AnySet(eTypeIsArray | eTypeIsPointer) &&
87814f1b3e8SDimitry Andric       elem_or_pointee_compiler_type.IsCharType()) {
879f034231aSEd Maste     addr_t cstr_address = LLDB_INVALID_ADDRESS;
880f034231aSEd Maste     AddressType cstr_address_type = eAddressTypeInvalid;
881f034231aSEd Maste 
882f034231aSEd Maste     size_t cstr_len = 0;
883f034231aSEd Maste     bool capped_data = false;
88414f1b3e8SDimitry Andric     const bool is_array = type_flags.Test(eTypeIsArray);
88514f1b3e8SDimitry Andric     if (is_array) {
886f034231aSEd Maste       // We have an array
887f034231aSEd Maste       uint64_t array_size = 0;
888344a3780SDimitry Andric       if (compiler_type.IsArrayType(nullptr, &array_size)) {
889f034231aSEd Maste         cstr_len = array_size;
89014f1b3e8SDimitry Andric         if (cstr_len > max_length) {
891f034231aSEd Maste           capped_data = true;
892f034231aSEd Maste           cstr_len = max_length;
893f034231aSEd Maste         }
894f034231aSEd Maste       }
895f034231aSEd Maste       cstr_address = GetAddressOf(true, &cstr_address_type);
89614f1b3e8SDimitry Andric     } else {
897f034231aSEd Maste       // We have a pointer
898f034231aSEd Maste       cstr_address = GetPointerValue(&cstr_address_type);
899f034231aSEd Maste     }
900f034231aSEd Maste 
90114f1b3e8SDimitry Andric     if (cstr_address == 0 || cstr_address == LLDB_INVALID_ADDRESS) {
90214f1b3e8SDimitry Andric       if (cstr_address_type == eAddressTypeHost && is_array) {
90314f1b3e8SDimitry Andric         const char *cstr = GetDataExtractor().PeekCStr(0);
90414f1b3e8SDimitry Andric         if (cstr == nullptr) {
905f034231aSEd Maste           s << "<invalid address>";
906f034231aSEd Maste           error.SetErrorString("invalid address");
907205afe67SEd Maste           CopyStringDataToBufferSP(s, buffer_sp);
908e81d9d49SDimitry Andric           return {0, was_capped};
909f034231aSEd Maste         }
910c0981da4SDimitry Andric         s << llvm::StringRef(cstr, cstr_len);
911c0981da4SDimitry Andric         CopyStringDataToBufferSP(s, buffer_sp);
91214f1b3e8SDimitry Andric         return {cstr_len, was_capped};
91314f1b3e8SDimitry Andric       } else {
91414f1b3e8SDimitry Andric         s << "<invalid address>";
91514f1b3e8SDimitry Andric         error.SetErrorString("invalid address");
91614f1b3e8SDimitry Andric         CopyStringDataToBufferSP(s, buffer_sp);
91714f1b3e8SDimitry Andric         return {0, was_capped};
91814f1b3e8SDimitry Andric       }
91914f1b3e8SDimitry Andric     }
920f034231aSEd Maste 
921f034231aSEd Maste     Address cstr_so_addr(cstr_address);
922f034231aSEd Maste     DataExtractor data;
92314f1b3e8SDimitry Andric     if (cstr_len > 0 && honor_array) {
92414f1b3e8SDimitry Andric       // I am using GetPointeeData() here to abstract the fact that some
925f73363f1SDimitry Andric       // ValueObjects are actually frozen pointers in the host but the pointed-
926f73363f1SDimitry Andric       // to data lives in the debuggee, and GetPointeeData() automatically
927f73363f1SDimitry Andric       // takes care of this
928f034231aSEd Maste       GetPointeeData(data, 0, cstr_len);
929f034231aSEd Maste 
93014f1b3e8SDimitry Andric       if ((bytes_read = data.GetByteSize()) > 0) {
931f034231aSEd Maste         total_bytes_read = bytes_read;
932205afe67SEd Maste         for (size_t offset = 0; offset < bytes_read; offset++)
933205afe67SEd Maste           s.Printf("%c", *data.PeekData(offset, 1));
934f034231aSEd Maste         if (capped_data)
935e81d9d49SDimitry Andric           was_capped = true;
936f034231aSEd Maste       }
93714f1b3e8SDimitry Andric     } else {
938f034231aSEd Maste       cstr_len = max_length;
939f034231aSEd Maste       const size_t k_max_buf_size = 64;
940f034231aSEd Maste 
941f034231aSEd Maste       size_t offset = 0;
942f034231aSEd Maste 
943f034231aSEd Maste       int cstr_len_displayed = -1;
944f034231aSEd Maste       bool capped_cstr = false;
94514f1b3e8SDimitry Andric       // I am using GetPointeeData() here to abstract the fact that some
946f73363f1SDimitry Andric       // ValueObjects are actually frozen pointers in the host but the pointed-
947f73363f1SDimitry Andric       // to data lives in the debuggee, and GetPointeeData() automatically
948f73363f1SDimitry Andric       // takes care of this
94914f1b3e8SDimitry Andric       while ((bytes_read = GetPointeeData(data, offset, k_max_buf_size)) > 0) {
950f034231aSEd Maste         total_bytes_read += bytes_read;
951f034231aSEd Maste         const char *cstr = data.PeekCStr(0);
952e81d9d49SDimitry Andric         size_t len = strnlen(cstr, k_max_buf_size);
953f034231aSEd Maste         if (cstr_len_displayed < 0)
954f034231aSEd Maste           cstr_len_displayed = len;
955f034231aSEd Maste 
956f034231aSEd Maste         if (len == 0)
957f034231aSEd Maste           break;
958f034231aSEd Maste         cstr_len_displayed += len;
959f034231aSEd Maste         if (len > bytes_read)
960f034231aSEd Maste           len = bytes_read;
961f034231aSEd Maste         if (len > cstr_len)
962f034231aSEd Maste           len = cstr_len;
963f034231aSEd Maste 
964205afe67SEd Maste         for (size_t offset = 0; offset < bytes_read; offset++)
965205afe67SEd Maste           s.Printf("%c", *data.PeekData(offset, 1));
966f034231aSEd Maste 
967f034231aSEd Maste         if (len < k_max_buf_size)
968f034231aSEd Maste           break;
969f034231aSEd Maste 
97014f1b3e8SDimitry Andric         if (len >= cstr_len) {
971f034231aSEd Maste           capped_cstr = true;
972f034231aSEd Maste           break;
973f034231aSEd Maste         }
974f034231aSEd Maste 
975f034231aSEd Maste         cstr_len -= len;
976f034231aSEd Maste         offset += len;
977f034231aSEd Maste       }
978f034231aSEd Maste 
97914f1b3e8SDimitry Andric       if (cstr_len_displayed >= 0) {
980f034231aSEd Maste         if (capped_cstr)
981e81d9d49SDimitry Andric           was_capped = true;
982f034231aSEd Maste       }
983f034231aSEd Maste     }
98414f1b3e8SDimitry Andric   } else {
985f034231aSEd Maste     error.SetErrorString("not a string object");
986f034231aSEd Maste     s << "<not a string object>";
987f034231aSEd Maste   }
988205afe67SEd Maste   CopyStringDataToBufferSP(s, buffer_sp);
989e81d9d49SDimitry Andric   return {total_bytes_read, was_capped};
990f034231aSEd Maste }
991f034231aSEd Maste 
GetObjectDescription()992ac9a064cSDimitry Andric llvm::Expected<std::string> ValueObject::GetObjectDescription() {
993f034231aSEd Maste   if (!UpdateValueIfNeeded(true))
994ac9a064cSDimitry Andric     return llvm::createStringError("could not update value");
995f034231aSEd Maste 
9965f29bb8aSDimitry Andric   // Return cached value.
997f034231aSEd Maste   if (!m_object_desc_str.empty())
998ac9a064cSDimitry Andric     return m_object_desc_str;
999f034231aSEd Maste 
1000f034231aSEd Maste   ExecutionContext exe_ctx(GetExecutionContextRef());
1001f034231aSEd Maste   Process *process = exe_ctx.GetProcessPtr();
10025f29bb8aSDimitry Andric   if (!process)
1003ac9a064cSDimitry Andric     return llvm::createStringError("no process");
1004f034231aSEd Maste 
10055f29bb8aSDimitry Andric   // Returns the object description produced by one language runtime.
1006ac9a064cSDimitry Andric   auto get_object_description =
1007ac9a064cSDimitry Andric       [&](LanguageType language) -> llvm::Expected<std::string> {
10085f29bb8aSDimitry Andric     if (LanguageRuntime *runtime = process->GetLanguageRuntime(language)) {
1009f034231aSEd Maste       StreamString s;
1010ac9a064cSDimitry Andric       if (llvm::Error error = runtime->GetObjectDescription(s, *this))
1011ac9a064cSDimitry Andric         return error;
1012ac9a064cSDimitry Andric       m_object_desc_str = s.GetString();
1013ac9a064cSDimitry Andric       return m_object_desc_str;
1014f034231aSEd Maste     }
1015ac9a064cSDimitry Andric     return llvm::createStringError("no native language runtime");
10165f29bb8aSDimitry Andric   };
10175f29bb8aSDimitry Andric 
10185f29bb8aSDimitry Andric   // Try the native language runtime first.
10195f29bb8aSDimitry Andric   LanguageType native_language = GetObjectRuntimeLanguage();
1020ac9a064cSDimitry Andric   llvm::Expected<std::string> desc = get_object_description(native_language);
1021ac9a064cSDimitry Andric   if (desc)
10225f29bb8aSDimitry Andric     return desc;
10235f29bb8aSDimitry Andric 
10245f29bb8aSDimitry Andric   // Try the Objective-C language runtime. This fallback is necessary
10255f29bb8aSDimitry Andric   // for Objective-C++ and mixed Objective-C / C++ programs.
1026ac9a064cSDimitry Andric   if (Language::LanguageIsCFamily(native_language)) {
1027ac9a064cSDimitry Andric     // We're going to try again, so let's drop the first error.
1028ac9a064cSDimitry Andric     llvm::consumeError(desc.takeError());
10295f29bb8aSDimitry Andric     return get_object_description(eLanguageTypeObjC);
1030ac9a064cSDimitry Andric   }
1031ac9a064cSDimitry Andric   return desc;
10325f29bb8aSDimitry Andric }
1033f034231aSEd Maste 
GetValueAsCString(const lldb_private::TypeFormatImpl & format,std::string & destination)103414f1b3e8SDimitry Andric bool ValueObject::GetValueAsCString(const lldb_private::TypeFormatImpl &format,
103514f1b3e8SDimitry Andric                                     std::string &destination) {
1036866dcdacSEd Maste   if (UpdateValueIfNeeded(false))
1037866dcdacSEd Maste     return format.FormatObject(this, destination);
1038866dcdacSEd Maste   else
1039866dcdacSEd Maste     return false;
1040866dcdacSEd Maste }
1041866dcdacSEd Maste 
GetValueAsCString(lldb::Format format,std::string & destination)104214f1b3e8SDimitry Andric bool ValueObject::GetValueAsCString(lldb::Format format,
104314f1b3e8SDimitry Andric                                     std::string &destination) {
1044866dcdacSEd Maste   return GetValueAsCString(TypeFormatImpl_Format(format), destination);
1045f034231aSEd Maste }
1046f034231aSEd Maste 
GetValueAsCString()104714f1b3e8SDimitry Andric const char *ValueObject::GetValueAsCString() {
104814f1b3e8SDimitry Andric   if (UpdateValueIfNeeded(true)) {
1049866dcdacSEd Maste     lldb::TypeFormatImplSP format_sp;
1050f034231aSEd Maste     lldb::Format my_format = GetFormat();
105114f1b3e8SDimitry Andric     if (my_format == lldb::eFormatDefault) {
1052f034231aSEd Maste       if (m_type_format_sp)
1053866dcdacSEd Maste         format_sp = m_type_format_sp;
105414f1b3e8SDimitry Andric       else {
1055344a3780SDimitry Andric         if (m_flags.m_is_bitfield_for_scalar)
1056f034231aSEd Maste           my_format = eFormatUnsigned;
105714f1b3e8SDimitry Andric         else {
1058344a3780SDimitry Andric           if (m_value.GetContextType() == Value::ContextType::RegisterInfo) {
1059f034231aSEd Maste             const RegisterInfo *reg_info = m_value.GetRegisterInfo();
1060f034231aSEd Maste             if (reg_info)
1061f034231aSEd Maste               my_format = reg_info->format;
106214f1b3e8SDimitry Andric           } else {
1063e81d9d49SDimitry Andric             my_format = GetValue().GetCompilerType().GetFormat();
1064f034231aSEd Maste           }
1065f034231aSEd Maste         }
1066f034231aSEd Maste       }
1067f034231aSEd Maste     }
106814f1b3e8SDimitry Andric     if (my_format != m_last_format || m_value_str.empty()) {
1069f034231aSEd Maste       m_last_format = my_format;
1070866dcdacSEd Maste       if (!format_sp)
10715f29bb8aSDimitry Andric         format_sp = std::make_shared<TypeFormatImpl_Format>(my_format);
107214f1b3e8SDimitry Andric       if (GetValueAsCString(*format_sp.get(), m_value_str)) {
1073344a3780SDimitry Andric         if (!m_flags.m_value_did_change && m_flags.m_old_value_valid) {
1074f73363f1SDimitry Andric           // The value was gotten successfully, so we consider the value as
1075f73363f1SDimitry Andric           // changed if the value string differs
1076f034231aSEd Maste           SetValueDidChange(m_old_value_str != m_value_str);
1077f034231aSEd Maste         }
1078f034231aSEd Maste       }
1079f034231aSEd Maste     }
1080f034231aSEd Maste   }
1081f034231aSEd Maste   if (m_value_str.empty())
10825f29bb8aSDimitry Andric     return nullptr;
1083f034231aSEd Maste   return m_value_str.c_str();
1084f034231aSEd Maste }
1085f034231aSEd Maste 
1086f73363f1SDimitry Andric // if > 8bytes, 0 is returned. this method should mostly be used to read
1087f73363f1SDimitry Andric // address values out of pointers
GetValueAsUnsigned(uint64_t fail_value,bool * success)108814f1b3e8SDimitry Andric uint64_t ValueObject::GetValueAsUnsigned(uint64_t fail_value, bool *success) {
1089f034231aSEd Maste   // If our byte size is zero this is an aggregate type that has children
109014f1b3e8SDimitry Andric   if (CanProvideValue()) {
1091f034231aSEd Maste     Scalar scalar;
109214f1b3e8SDimitry Andric     if (ResolveValue(scalar)) {
1093f034231aSEd Maste       if (success)
1094f034231aSEd Maste         *success = true;
1095cfca06d7SDimitry Andric       scalar.MakeUnsigned();
1096f034231aSEd Maste       return scalar.ULongLong(fail_value);
1097f034231aSEd Maste     }
1098f034231aSEd Maste     // fallthrough, otherwise...
1099f034231aSEd Maste   }
1100f034231aSEd Maste 
1101f034231aSEd Maste   if (success)
1102f034231aSEd Maste     *success = false;
1103f034231aSEd Maste   return fail_value;
1104f034231aSEd Maste }
1105f034231aSEd Maste 
GetValueAsSigned(int64_t fail_value,bool * success)110614f1b3e8SDimitry Andric int64_t ValueObject::GetValueAsSigned(int64_t fail_value, bool *success) {
1107f21a844fSEd Maste   // If our byte size is zero this is an aggregate type that has children
110814f1b3e8SDimitry Andric   if (CanProvideValue()) {
1109f21a844fSEd Maste     Scalar scalar;
111014f1b3e8SDimitry Andric     if (ResolveValue(scalar)) {
1111f21a844fSEd Maste       if (success)
1112f21a844fSEd Maste         *success = true;
1113cfca06d7SDimitry Andric       scalar.MakeSigned();
1114f21a844fSEd Maste       return scalar.SLongLong(fail_value);
1115f21a844fSEd Maste     }
1116f21a844fSEd Maste     // fallthrough, otherwise...
1117f21a844fSEd Maste   }
1118f21a844fSEd Maste 
1119f21a844fSEd Maste   if (success)
1120f21a844fSEd Maste     *success = false;
1121f21a844fSEd Maste   return fail_value;
1122f21a844fSEd Maste }
1123f21a844fSEd Maste 
GetValueAsAPSInt()1124ac9a064cSDimitry Andric llvm::Expected<llvm::APSInt> ValueObject::GetValueAsAPSInt() {
1125ac9a064cSDimitry Andric   // Make sure the type can be converted to an APSInt.
1126ac9a064cSDimitry Andric   if (!GetCompilerType().IsInteger() &&
1127ac9a064cSDimitry Andric       !GetCompilerType().IsScopedEnumerationType() &&
1128ac9a064cSDimitry Andric       !GetCompilerType().IsEnumerationType() &&
1129ac9a064cSDimitry Andric       !GetCompilerType().IsPointerType() &&
1130ac9a064cSDimitry Andric       !GetCompilerType().IsNullPtrType() &&
1131ac9a064cSDimitry Andric       !GetCompilerType().IsReferenceType() && !GetCompilerType().IsBoolean())
1132ac9a064cSDimitry Andric     return llvm::make_error<llvm::StringError>(
1133ac9a064cSDimitry Andric         "type cannot be converted to APSInt", llvm::inconvertibleErrorCode());
1134ac9a064cSDimitry Andric 
1135ac9a064cSDimitry Andric   if (CanProvideValue()) {
1136ac9a064cSDimitry Andric     Scalar scalar;
1137ac9a064cSDimitry Andric     if (ResolveValue(scalar))
1138ac9a064cSDimitry Andric       return scalar.GetAPSInt();
1139ac9a064cSDimitry Andric   }
1140ac9a064cSDimitry Andric 
1141ac9a064cSDimitry Andric   return llvm::make_error<llvm::StringError>(
1142ac9a064cSDimitry Andric       "error occurred; unable to convert to APSInt",
1143ac9a064cSDimitry Andric       llvm::inconvertibleErrorCode());
1144ac9a064cSDimitry Andric }
1145ac9a064cSDimitry Andric 
GetValueAsAPFloat()1146ac9a064cSDimitry Andric llvm::Expected<llvm::APFloat> ValueObject::GetValueAsAPFloat() {
1147ac9a064cSDimitry Andric   if (!GetCompilerType().IsFloat())
1148ac9a064cSDimitry Andric     return llvm::make_error<llvm::StringError>(
1149ac9a064cSDimitry Andric         "type cannot be converted to APFloat", llvm::inconvertibleErrorCode());
1150ac9a064cSDimitry Andric 
1151ac9a064cSDimitry Andric   if (CanProvideValue()) {
1152ac9a064cSDimitry Andric     Scalar scalar;
1153ac9a064cSDimitry Andric     if (ResolveValue(scalar))
1154ac9a064cSDimitry Andric       return scalar.GetAPFloat();
1155ac9a064cSDimitry Andric   }
1156ac9a064cSDimitry Andric 
1157ac9a064cSDimitry Andric   return llvm::make_error<llvm::StringError>(
1158ac9a064cSDimitry Andric       "error occurred; unable to convert to APFloat",
1159ac9a064cSDimitry Andric       llvm::inconvertibleErrorCode());
1160ac9a064cSDimitry Andric }
1161ac9a064cSDimitry Andric 
GetValueAsBool()1162ac9a064cSDimitry Andric llvm::Expected<bool> ValueObject::GetValueAsBool() {
1163ac9a064cSDimitry Andric   CompilerType val_type = GetCompilerType();
1164ac9a064cSDimitry Andric   if (val_type.IsInteger() || val_type.IsUnscopedEnumerationType() ||
1165ac9a064cSDimitry Andric       val_type.IsPointerType()) {
1166ac9a064cSDimitry Andric     auto value_or_err = GetValueAsAPSInt();
1167ac9a064cSDimitry Andric     if (value_or_err)
1168ac9a064cSDimitry Andric       return value_or_err->getBoolValue();
1169ac9a064cSDimitry Andric   }
1170ac9a064cSDimitry Andric   if (val_type.IsFloat()) {
1171ac9a064cSDimitry Andric     auto value_or_err = GetValueAsAPFloat();
1172ac9a064cSDimitry Andric     if (value_or_err)
1173ac9a064cSDimitry Andric       return value_or_err->isNonZero();
1174ac9a064cSDimitry Andric   }
1175ac9a064cSDimitry Andric   if (val_type.IsArrayType())
1176ac9a064cSDimitry Andric     return GetAddressOf() != 0;
1177ac9a064cSDimitry Andric 
1178ac9a064cSDimitry Andric   return llvm::make_error<llvm::StringError>("type cannot be converted to bool",
1179ac9a064cSDimitry Andric                                              llvm::inconvertibleErrorCode());
1180ac9a064cSDimitry Andric }
1181ac9a064cSDimitry Andric 
SetValueFromInteger(const llvm::APInt & value,Status & error)1182ac9a064cSDimitry Andric void ValueObject::SetValueFromInteger(const llvm::APInt &value, Status &error) {
1183ac9a064cSDimitry Andric   // Verify the current object is an integer object
1184ac9a064cSDimitry Andric   CompilerType val_type = GetCompilerType();
1185ac9a064cSDimitry Andric   if (!val_type.IsInteger() && !val_type.IsUnscopedEnumerationType() &&
1186ac9a064cSDimitry Andric       !val_type.IsFloat() && !val_type.IsPointerType() &&
1187ac9a064cSDimitry Andric       !val_type.IsScalarType()) {
1188ac9a064cSDimitry Andric     error.SetErrorString("current value object is not an integer objet");
1189ac9a064cSDimitry Andric     return;
1190ac9a064cSDimitry Andric   }
1191ac9a064cSDimitry Andric 
1192ac9a064cSDimitry Andric   // Verify the current object is not actually associated with any program
1193ac9a064cSDimitry Andric   // variable.
1194ac9a064cSDimitry Andric   if (GetVariable()) {
1195ac9a064cSDimitry Andric     error.SetErrorString("current value object is not a temporary object");
1196ac9a064cSDimitry Andric     return;
1197ac9a064cSDimitry Andric   }
1198ac9a064cSDimitry Andric 
1199ac9a064cSDimitry Andric   // Verify the proposed new value is the right size.
1200ac9a064cSDimitry Andric   lldb::TargetSP target = GetTargetSP();
1201ac9a064cSDimitry Andric   uint64_t byte_size = 0;
1202ac9a064cSDimitry Andric   if (auto temp = GetCompilerType().GetByteSize(target.get()))
1203ac9a064cSDimitry Andric     byte_size = temp.value();
1204ac9a064cSDimitry Andric   if (value.getBitWidth() != byte_size * CHAR_BIT) {
1205ac9a064cSDimitry Andric     error.SetErrorString(
1206ac9a064cSDimitry Andric         "illegal argument: new value should be of the same size");
1207ac9a064cSDimitry Andric     return;
1208ac9a064cSDimitry Andric   }
1209ac9a064cSDimitry Andric 
1210ac9a064cSDimitry Andric   lldb::DataExtractorSP data_sp;
1211ac9a064cSDimitry Andric   data_sp->SetData(value.getRawData(), byte_size,
1212ac9a064cSDimitry Andric                    target->GetArchitecture().GetByteOrder());
1213ac9a064cSDimitry Andric   data_sp->SetAddressByteSize(
1214ac9a064cSDimitry Andric       static_cast<uint8_t>(target->GetArchitecture().GetAddressByteSize()));
1215ac9a064cSDimitry Andric   SetData(*data_sp, error);
1216ac9a064cSDimitry Andric }
1217ac9a064cSDimitry Andric 
SetValueFromInteger(lldb::ValueObjectSP new_val_sp,Status & error)1218ac9a064cSDimitry Andric void ValueObject::SetValueFromInteger(lldb::ValueObjectSP new_val_sp,
1219ac9a064cSDimitry Andric                                       Status &error) {
1220ac9a064cSDimitry Andric   // Verify the current object is an integer object
1221ac9a064cSDimitry Andric   CompilerType val_type = GetCompilerType();
1222ac9a064cSDimitry Andric   if (!val_type.IsInteger() && !val_type.IsUnscopedEnumerationType() &&
1223ac9a064cSDimitry Andric       !val_type.IsFloat() && !val_type.IsPointerType() &&
1224ac9a064cSDimitry Andric       !val_type.IsScalarType()) {
1225ac9a064cSDimitry Andric     error.SetErrorString("current value object is not an integer objet");
1226ac9a064cSDimitry Andric     return;
1227ac9a064cSDimitry Andric   }
1228ac9a064cSDimitry Andric 
1229ac9a064cSDimitry Andric   // Verify the current object is not actually associated with any program
1230ac9a064cSDimitry Andric   // variable.
1231ac9a064cSDimitry Andric   if (GetVariable()) {
1232ac9a064cSDimitry Andric     error.SetErrorString("current value object is not a temporary object");
1233ac9a064cSDimitry Andric     return;
1234ac9a064cSDimitry Andric   }
1235ac9a064cSDimitry Andric 
1236ac9a064cSDimitry Andric   // Verify the proposed new value is the right type.
1237ac9a064cSDimitry Andric   CompilerType new_val_type = new_val_sp->GetCompilerType();
1238ac9a064cSDimitry Andric   if (!new_val_type.IsInteger() && !new_val_type.IsFloat() &&
1239ac9a064cSDimitry Andric       !new_val_type.IsPointerType()) {
1240ac9a064cSDimitry Andric     error.SetErrorString(
1241ac9a064cSDimitry Andric         "illegal argument: new value should be of the same size");
1242ac9a064cSDimitry Andric     return;
1243ac9a064cSDimitry Andric   }
1244ac9a064cSDimitry Andric 
1245ac9a064cSDimitry Andric   if (new_val_type.IsInteger()) {
1246ac9a064cSDimitry Andric     auto value_or_err = new_val_sp->GetValueAsAPSInt();
1247ac9a064cSDimitry Andric     if (value_or_err)
1248ac9a064cSDimitry Andric       SetValueFromInteger(*value_or_err, error);
1249ac9a064cSDimitry Andric     else
1250ac9a064cSDimitry Andric       error.SetErrorString("error getting APSInt from new_val_sp");
1251ac9a064cSDimitry Andric   } else if (new_val_type.IsFloat()) {
1252ac9a064cSDimitry Andric     auto value_or_err = new_val_sp->GetValueAsAPFloat();
1253ac9a064cSDimitry Andric     if (value_or_err)
1254ac9a064cSDimitry Andric       SetValueFromInteger(value_or_err->bitcastToAPInt(), error);
1255ac9a064cSDimitry Andric     else
1256ac9a064cSDimitry Andric       error.SetErrorString("error getting APFloat from new_val_sp");
1257ac9a064cSDimitry Andric   } else if (new_val_type.IsPointerType()) {
1258ac9a064cSDimitry Andric     bool success = true;
1259ac9a064cSDimitry Andric     uint64_t int_val = new_val_sp->GetValueAsUnsigned(0, &success);
1260ac9a064cSDimitry Andric     if (success) {
1261ac9a064cSDimitry Andric       lldb::TargetSP target = GetTargetSP();
1262ac9a064cSDimitry Andric       uint64_t num_bits = 0;
1263ac9a064cSDimitry Andric       if (auto temp = new_val_sp->GetCompilerType().GetBitSize(target.get()))
1264ac9a064cSDimitry Andric         num_bits = temp.value();
1265ac9a064cSDimitry Andric       SetValueFromInteger(llvm::APInt(num_bits, int_val), error);
1266ac9a064cSDimitry Andric     } else
1267ac9a064cSDimitry Andric       error.SetErrorString("error converting new_val_sp to integer");
1268ac9a064cSDimitry Andric   }
1269ac9a064cSDimitry Andric }
1270ac9a064cSDimitry Andric 
127114f1b3e8SDimitry Andric // if any more "special cases" are added to
1272f73363f1SDimitry Andric // ValueObject::DumpPrintableRepresentation() please keep this call up to date
1273f73363f1SDimitry Andric // by returning true for your new special cases. We will eventually move to
1274f73363f1SDimitry Andric // checking this call result before trying to display special cases
HasSpecialPrintableRepresentation(ValueObjectRepresentationStyle val_obj_display,Format custom_format)127514f1b3e8SDimitry Andric bool ValueObject::HasSpecialPrintableRepresentation(
127614f1b3e8SDimitry Andric     ValueObjectRepresentationStyle val_obj_display, Format custom_format) {
1277f034231aSEd Maste   Flags flags(GetTypeInfo());
127814f1b3e8SDimitry Andric   if (flags.AnySet(eTypeIsArray | eTypeIsPointer) &&
127914f1b3e8SDimitry Andric       val_obj_display == ValueObject::eValueObjectRepresentationStyleValue) {
1280f034231aSEd Maste     if (IsCStringContainer(true) &&
128114f1b3e8SDimitry Andric         (custom_format == eFormatCString || custom_format == eFormatCharArray ||
128214f1b3e8SDimitry Andric          custom_format == eFormatChar || custom_format == eFormatVectorOfChar))
1283f034231aSEd Maste       return true;
1284f034231aSEd Maste 
128514f1b3e8SDimitry Andric     if (flags.Test(eTypeIsArray)) {
1286f034231aSEd Maste       if ((custom_format == eFormatBytes) ||
1287f034231aSEd Maste           (custom_format == eFormatBytesWithASCII))
1288f034231aSEd Maste         return true;
1289f034231aSEd Maste 
1290f034231aSEd Maste       if ((custom_format == eFormatVectorOfChar) ||
1291f034231aSEd Maste           (custom_format == eFormatVectorOfFloat32) ||
1292f034231aSEd Maste           (custom_format == eFormatVectorOfFloat64) ||
1293f034231aSEd Maste           (custom_format == eFormatVectorOfSInt16) ||
1294f034231aSEd Maste           (custom_format == eFormatVectorOfSInt32) ||
1295f034231aSEd Maste           (custom_format == eFormatVectorOfSInt64) ||
1296f034231aSEd Maste           (custom_format == eFormatVectorOfSInt8) ||
1297f034231aSEd Maste           (custom_format == eFormatVectorOfUInt128) ||
1298f034231aSEd Maste           (custom_format == eFormatVectorOfUInt16) ||
1299f034231aSEd Maste           (custom_format == eFormatVectorOfUInt32) ||
1300f034231aSEd Maste           (custom_format == eFormatVectorOfUInt64) ||
1301f034231aSEd Maste           (custom_format == eFormatVectorOfUInt8))
1302f034231aSEd Maste         return true;
1303f034231aSEd Maste     }
1304f034231aSEd Maste   }
1305f034231aSEd Maste   return false;
1306f034231aSEd Maste }
1307f034231aSEd Maste 
DumpPrintableRepresentation(Stream & s,ValueObjectRepresentationStyle val_obj_display,Format custom_format,PrintableRepresentationSpecialCases special,bool do_dump_error)130814f1b3e8SDimitry Andric bool ValueObject::DumpPrintableRepresentation(
130914f1b3e8SDimitry Andric     Stream &s, ValueObjectRepresentationStyle val_obj_display,
131014f1b3e8SDimitry Andric     Format custom_format, PrintableRepresentationSpecialCases special,
131114f1b3e8SDimitry Andric     bool do_dump_error) {
1312f034231aSEd Maste 
13137fa27ce4SDimitry Andric   // If the ValueObject has an error, we might end up dumping the type, which
13147fa27ce4SDimitry Andric   // is useful, but if we don't even have a type, then don't examine the object
13157fa27ce4SDimitry Andric   // further as that's not meaningful, only the error is.
13167fa27ce4SDimitry Andric   if (m_error.Fail() && !GetCompilerType().IsValid()) {
13177fa27ce4SDimitry Andric     if (do_dump_error)
13187fa27ce4SDimitry Andric       s.Printf("<%s>", m_error.AsCString());
13197fa27ce4SDimitry Andric     return false;
13207fa27ce4SDimitry Andric   }
13217fa27ce4SDimitry Andric 
1322f034231aSEd Maste   Flags flags(GetTypeInfo());
1323f034231aSEd Maste 
132414f1b3e8SDimitry Andric   bool allow_special =
132514f1b3e8SDimitry Andric       (special == ValueObject::PrintableRepresentationSpecialCases::eAllow);
132614f1b3e8SDimitry Andric   const bool only_special = false;
1327f034231aSEd Maste 
132814f1b3e8SDimitry Andric   if (allow_special) {
132914f1b3e8SDimitry Andric     if (flags.AnySet(eTypeIsArray | eTypeIsPointer) &&
133014f1b3e8SDimitry Andric         val_obj_display == ValueObject::eValueObjectRepresentationStyleValue) {
133114f1b3e8SDimitry Andric       // when being asked to get a printable display an array or pointer type
1332f73363f1SDimitry Andric       // directly, try to "do the right thing"
1333f034231aSEd Maste 
1334f034231aSEd Maste       if (IsCStringContainer(true) &&
1335f034231aSEd Maste           (custom_format == eFormatCString ||
133614f1b3e8SDimitry Andric            custom_format == eFormatCharArray || custom_format == eFormatChar ||
133714f1b3e8SDimitry Andric            custom_format ==
133814f1b3e8SDimitry Andric                eFormatVectorOfChar)) // print char[] & char* directly
1339f034231aSEd Maste       {
1340b76161e4SDimitry Andric         Status error;
1341145449b1SDimitry Andric         lldb::WritableDataBufferSP buffer_sp;
13424df029ccSDimitry Andric         std::pair<size_t, bool> read_string =
13434df029ccSDimitry Andric             ReadPointedString(buffer_sp, error,
13444df029ccSDimitry Andric                               (custom_format == eFormatVectorOfChar) ||
1345f034231aSEd Maste                                   (custom_format == eFormatCharArray));
134614f1b3e8SDimitry Andric         lldb_private::formatters::StringPrinter::
134714f1b3e8SDimitry Andric             ReadBufferAndDumpToStreamOptions options(*this);
134814f1b3e8SDimitry Andric         options.SetData(DataExtractor(
134914f1b3e8SDimitry Andric             buffer_sp, lldb::eByteOrderInvalid,
135014f1b3e8SDimitry Andric             8)); // none of this matters for a string - pass some defaults
1351205afe67SEd Maste         options.SetStream(&s);
13525f29bb8aSDimitry Andric         options.SetPrefixToken(nullptr);
1353205afe67SEd Maste         options.SetQuote('"');
1354205afe67SEd Maste         options.SetSourceSize(buffer_sp->GetByteSize());
1355e81d9d49SDimitry Andric         options.SetIsTruncated(read_string.second);
1356c0981da4SDimitry Andric         options.SetBinaryZeroIsTerminator(custom_format != eFormatVectorOfChar);
135714f1b3e8SDimitry Andric         formatters::StringPrinter::ReadBufferAndDumpToStream<
135814f1b3e8SDimitry Andric             lldb_private::formatters::StringPrinter::StringElementType::ASCII>(
135914f1b3e8SDimitry Andric             options);
1360f034231aSEd Maste         return !error.Fail();
1361f034231aSEd Maste       }
1362f034231aSEd Maste 
1363f034231aSEd Maste       if (custom_format == eFormatEnum)
1364f034231aSEd Maste         return false;
1365f034231aSEd Maste 
1366f73363f1SDimitry Andric       // this only works for arrays, because I have no way to know when the
1367f73363f1SDimitry Andric       // pointed memory ends, and no special \0 end of data marker
136814f1b3e8SDimitry Andric       if (flags.Test(eTypeIsArray)) {
1369f034231aSEd Maste         if ((custom_format == eFormatBytes) ||
137014f1b3e8SDimitry Andric             (custom_format == eFormatBytesWithASCII)) {
1371ac9a064cSDimitry Andric           const size_t count = GetNumChildrenIgnoringErrors();
1372f034231aSEd Maste 
1373f034231aSEd Maste           s << '[';
137414f1b3e8SDimitry Andric           for (size_t low = 0; low < count; low++) {
1375f034231aSEd Maste 
1376f034231aSEd Maste             if (low)
1377f034231aSEd Maste               s << ',';
1378f034231aSEd Maste 
13797fa27ce4SDimitry Andric             ValueObjectSP child = GetChildAtIndex(low);
138014f1b3e8SDimitry Andric             if (!child.get()) {
1381f034231aSEd Maste               s << "<invalid child>";
1382f034231aSEd Maste               continue;
1383f034231aSEd Maste             }
138414f1b3e8SDimitry Andric             child->DumpPrintableRepresentation(
138514f1b3e8SDimitry Andric                 s, ValueObject::eValueObjectRepresentationStyleValue,
138614f1b3e8SDimitry Andric                 custom_format);
1387f034231aSEd Maste           }
1388f034231aSEd Maste 
1389f034231aSEd Maste           s << ']';
1390f034231aSEd Maste 
1391f034231aSEd Maste           return true;
1392f034231aSEd Maste         }
1393f034231aSEd Maste 
1394f034231aSEd Maste         if ((custom_format == eFormatVectorOfChar) ||
1395f034231aSEd Maste             (custom_format == eFormatVectorOfFloat32) ||
1396f034231aSEd Maste             (custom_format == eFormatVectorOfFloat64) ||
1397f034231aSEd Maste             (custom_format == eFormatVectorOfSInt16) ||
1398f034231aSEd Maste             (custom_format == eFormatVectorOfSInt32) ||
1399f034231aSEd Maste             (custom_format == eFormatVectorOfSInt64) ||
1400f034231aSEd Maste             (custom_format == eFormatVectorOfSInt8) ||
1401f034231aSEd Maste             (custom_format == eFormatVectorOfUInt128) ||
1402f034231aSEd Maste             (custom_format == eFormatVectorOfUInt16) ||
1403f034231aSEd Maste             (custom_format == eFormatVectorOfUInt32) ||
1404f034231aSEd Maste             (custom_format == eFormatVectorOfUInt64) ||
140514f1b3e8SDimitry Andric             (custom_format == eFormatVectorOfUInt8)) // arrays of bytes, bytes
140614f1b3e8SDimitry Andric                                                      // with ASCII or any vector
140714f1b3e8SDimitry Andric                                                      // format should be printed
140814f1b3e8SDimitry Andric                                                      // directly
1409f034231aSEd Maste         {
1410ac9a064cSDimitry Andric           const size_t count = GetNumChildrenIgnoringErrors();
1411f034231aSEd Maste 
1412f034231aSEd Maste           Format format = FormatManager::GetSingleItemFormat(custom_format);
1413f034231aSEd Maste 
1414f034231aSEd Maste           s << '[';
141514f1b3e8SDimitry Andric           for (size_t low = 0; low < count; low++) {
1416f034231aSEd Maste 
1417f034231aSEd Maste             if (low)
1418f034231aSEd Maste               s << ',';
1419f034231aSEd Maste 
14207fa27ce4SDimitry Andric             ValueObjectSP child = GetChildAtIndex(low);
142114f1b3e8SDimitry Andric             if (!child.get()) {
1422f034231aSEd Maste               s << "<invalid child>";
1423f034231aSEd Maste               continue;
1424f034231aSEd Maste             }
142514f1b3e8SDimitry Andric             child->DumpPrintableRepresentation(
142614f1b3e8SDimitry Andric                 s, ValueObject::eValueObjectRepresentationStyleValue, format);
1427f034231aSEd Maste           }
1428f034231aSEd Maste 
1429f034231aSEd Maste           s << ']';
1430f034231aSEd Maste 
1431f034231aSEd Maste           return true;
1432f034231aSEd Maste         }
1433f034231aSEd Maste       }
1434f034231aSEd Maste 
1435f034231aSEd Maste       if ((custom_format == eFormatBoolean) ||
143614f1b3e8SDimitry Andric           (custom_format == eFormatBinary) || (custom_format == eFormatChar) ||
1437f034231aSEd Maste           (custom_format == eFormatCharPrintable) ||
1438f034231aSEd Maste           (custom_format == eFormatComplexFloat) ||
143914f1b3e8SDimitry Andric           (custom_format == eFormatDecimal) || (custom_format == eFormatHex) ||
1440f034231aSEd Maste           (custom_format == eFormatHexUppercase) ||
144114f1b3e8SDimitry Andric           (custom_format == eFormatFloat) || (custom_format == eFormatOctal) ||
1442f034231aSEd Maste           (custom_format == eFormatOSType) ||
1443f034231aSEd Maste           (custom_format == eFormatUnicode16) ||
1444f034231aSEd Maste           (custom_format == eFormatUnicode32) ||
1445f034231aSEd Maste           (custom_format == eFormatUnsigned) ||
1446f034231aSEd Maste           (custom_format == eFormatPointer) ||
1447f034231aSEd Maste           (custom_format == eFormatComplexInteger) ||
1448f034231aSEd Maste           (custom_format == eFormatComplex) ||
1449f034231aSEd Maste           (custom_format == eFormatDefault)) // use the [] operator
1450f034231aSEd Maste         return false;
1451f034231aSEd Maste     }
1452f034231aSEd Maste   }
1453f034231aSEd Maste 
1454f034231aSEd Maste   if (only_special)
1455f034231aSEd Maste     return false;
1456f034231aSEd Maste 
1457f034231aSEd Maste   bool var_success = false;
1458f034231aSEd Maste 
1459f034231aSEd Maste   {
146014f1b3e8SDimitry Andric     llvm::StringRef str;
1461f034231aSEd Maste 
146214f1b3e8SDimitry Andric     // this is a local stream that we are using to ensure that the data pointed
1463f73363f1SDimitry Andric     // to by cstr survives long enough for us to copy it to its destination -
1464f73363f1SDimitry Andric     // it is necessary to have this temporary storage area for cases where our
146514f1b3e8SDimitry Andric     // desired output is not backed by some other longer-term storage
1466f034231aSEd Maste     StreamString strm;
1467f034231aSEd Maste 
1468f034231aSEd Maste     if (custom_format != eFormatInvalid)
1469f034231aSEd Maste       SetFormat(custom_format);
1470f034231aSEd Maste 
147114f1b3e8SDimitry Andric     switch (val_obj_display) {
1472f034231aSEd Maste     case eValueObjectRepresentationStyleValue:
147314f1b3e8SDimitry Andric       str = GetValueAsCString();
1474f034231aSEd Maste       break;
1475f034231aSEd Maste 
1476f034231aSEd Maste     case eValueObjectRepresentationStyleSummary:
147714f1b3e8SDimitry Andric       str = GetSummaryAsCString();
1478f034231aSEd Maste       break;
1479f034231aSEd Maste 
1480ac9a064cSDimitry Andric     case eValueObjectRepresentationStyleLanguageSpecific: {
1481ac9a064cSDimitry Andric       llvm::Expected<std::string> desc = GetObjectDescription();
1482ac9a064cSDimitry Andric       if (!desc) {
1483ac9a064cSDimitry Andric         strm << "error: " << toString(desc.takeError());
1484ac9a064cSDimitry Andric         str = strm.GetString();
1485ac9a064cSDimitry Andric       } else {
1486ac9a064cSDimitry Andric         strm << *desc;
1487ac9a064cSDimitry Andric         str = strm.GetString();
1488ac9a064cSDimitry Andric       }
1489ac9a064cSDimitry Andric     } break;
1490f034231aSEd Maste 
1491f034231aSEd Maste     case eValueObjectRepresentationStyleLocation:
149214f1b3e8SDimitry Andric       str = GetLocationAsCString();
1493f034231aSEd Maste       break;
1494f034231aSEd Maste 
1495f034231aSEd Maste     case eValueObjectRepresentationStyleChildrenCount:
1496ac9a064cSDimitry Andric       strm.Printf("%" PRIu64 "", (uint64_t)GetNumChildrenIgnoringErrors());
149714f1b3e8SDimitry Andric       str = strm.GetString();
1498f034231aSEd Maste       break;
1499f034231aSEd Maste 
1500f034231aSEd Maste     case eValueObjectRepresentationStyleType:
150114f1b3e8SDimitry Andric       str = GetTypeName().GetStringRef();
1502f034231aSEd Maste       break;
1503f034231aSEd Maste 
1504f034231aSEd Maste     case eValueObjectRepresentationStyleName:
150514f1b3e8SDimitry Andric       str = GetName().GetStringRef();
1506f034231aSEd Maste       break;
1507f034231aSEd Maste 
1508f034231aSEd Maste     case eValueObjectRepresentationStyleExpressionPath:
1509cfca06d7SDimitry Andric       GetExpressionPath(strm);
151014f1b3e8SDimitry Andric       str = strm.GetString();
1511f034231aSEd Maste       break;
1512f034231aSEd Maste     }
1513f034231aSEd Maste 
1514ac9a064cSDimitry Andric     // If the requested display style produced no output, try falling back to
1515ac9a064cSDimitry Andric     // alternative presentations.
151614f1b3e8SDimitry Andric     if (str.empty()) {
1517f034231aSEd Maste       if (val_obj_display == eValueObjectRepresentationStyleValue)
151814f1b3e8SDimitry Andric         str = GetSummaryAsCString();
151914f1b3e8SDimitry Andric       else if (val_obj_display == eValueObjectRepresentationStyleSummary) {
152014f1b3e8SDimitry Andric         if (!CanProvideValue()) {
152114f1b3e8SDimitry Andric           strm.Printf("%s @ %s", GetTypeName().AsCString(),
152214f1b3e8SDimitry Andric                       GetLocationAsCString());
152314f1b3e8SDimitry Andric           str = strm.GetString();
152414f1b3e8SDimitry Andric         } else
152514f1b3e8SDimitry Andric           str = GetValueAsCString();
1526f034231aSEd Maste       }
1527f034231aSEd Maste     }
1528f034231aSEd Maste 
152914f1b3e8SDimitry Andric     if (!str.empty())
153014f1b3e8SDimitry Andric       s << str;
153114f1b3e8SDimitry Andric     else {
15327fa27ce4SDimitry Andric       // We checked for errors at the start, but do it again here in case
15337fa27ce4SDimitry Andric       // realizing the value for dumping produced an error.
153414f1b3e8SDimitry Andric       if (m_error.Fail()) {
1535866dcdacSEd Maste         if (do_dump_error)
1536f034231aSEd Maste           s.Printf("<%s>", m_error.AsCString());
1537866dcdacSEd Maste         else
1538866dcdacSEd Maste           return false;
153914f1b3e8SDimitry Andric       } else if (val_obj_display == eValueObjectRepresentationStyleSummary)
1540f034231aSEd Maste         s.PutCString("<no summary available>");
1541f034231aSEd Maste       else if (val_obj_display == eValueObjectRepresentationStyleValue)
1542f034231aSEd Maste         s.PutCString("<no value available>");
154314f1b3e8SDimitry Andric       else if (val_obj_display ==
154414f1b3e8SDimitry Andric                eValueObjectRepresentationStyleLanguageSpecific)
154514f1b3e8SDimitry Andric         s.PutCString("<not a valid Objective-C object>"); // edit this if we
154614f1b3e8SDimitry Andric                                                           // have other runtimes
154714f1b3e8SDimitry Andric                                                           // that support a
154814f1b3e8SDimitry Andric                                                           // description
1549f034231aSEd Maste       else
1550f034231aSEd Maste         s.PutCString("<no printable representation>");
1551f034231aSEd Maste     }
1552f034231aSEd Maste 
1553f73363f1SDimitry Andric     // we should only return false here if we could not do *anything* even if
1554f73363f1SDimitry Andric     // we have an error message as output, that's a success from our callers'
1555f73363f1SDimitry Andric     // perspective, so return true
1556f034231aSEd Maste     var_success = true;
1557f034231aSEd Maste 
1558f034231aSEd Maste     if (custom_format != eFormatInvalid)
1559f034231aSEd Maste       SetFormat(eFormatDefault);
1560f034231aSEd Maste   }
1561f034231aSEd Maste 
1562f034231aSEd Maste   return var_success;
1563f034231aSEd Maste }
1564f034231aSEd Maste 
GetAddressOf(bool scalar_is_load_address,AddressType * address_type)156514f1b3e8SDimitry Andric addr_t ValueObject::GetAddressOf(bool scalar_is_load_address,
156614f1b3e8SDimitry Andric                                  AddressType *address_type) {
1567f3fbd1c0SDimitry Andric   // Can't take address of a bitfield
1568f3fbd1c0SDimitry Andric   if (IsBitfield())
1569f3fbd1c0SDimitry Andric     return LLDB_INVALID_ADDRESS;
1570f3fbd1c0SDimitry Andric 
1571f034231aSEd Maste   if (!UpdateValueIfNeeded(false))
1572f034231aSEd Maste     return LLDB_INVALID_ADDRESS;
1573f034231aSEd Maste 
157414f1b3e8SDimitry Andric   switch (m_value.GetValueType()) {
1575344a3780SDimitry Andric   case Value::ValueType::Invalid:
1576344a3780SDimitry Andric     return LLDB_INVALID_ADDRESS;
1577344a3780SDimitry Andric   case Value::ValueType::Scalar:
157814f1b3e8SDimitry Andric     if (scalar_is_load_address) {
1579f034231aSEd Maste       if (address_type)
1580f034231aSEd Maste         *address_type = eAddressTypeLoad;
1581f034231aSEd Maste       return m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
1582f034231aSEd Maste     }
1583f034231aSEd Maste     break;
1584f034231aSEd Maste 
1585344a3780SDimitry Andric   case Value::ValueType::LoadAddress:
1586344a3780SDimitry Andric   case Value::ValueType::FileAddress: {
1587f034231aSEd Maste     if (address_type)
1588f034231aSEd Maste       *address_type = m_value.GetValueAddressType();
1589f034231aSEd Maste     return m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
159014f1b3e8SDimitry Andric   } break;
1591344a3780SDimitry Andric   case Value::ValueType::HostAddress: {
15925e95aa85SEd Maste     if (address_type)
15935e95aa85SEd Maste       *address_type = m_value.GetValueAddressType();
15945e95aa85SEd Maste     return LLDB_INVALID_ADDRESS;
159514f1b3e8SDimitry Andric   } break;
1596f034231aSEd Maste   }
1597f034231aSEd Maste   if (address_type)
1598f034231aSEd Maste     *address_type = eAddressTypeInvalid;
1599f034231aSEd Maste   return LLDB_INVALID_ADDRESS;
1600f034231aSEd Maste }
1601f034231aSEd Maste 
GetPointerValue(AddressType * address_type)160214f1b3e8SDimitry Andric addr_t ValueObject::GetPointerValue(AddressType *address_type) {
1603f034231aSEd Maste   addr_t address = LLDB_INVALID_ADDRESS;
1604f034231aSEd Maste   if (address_type)
1605f034231aSEd Maste     *address_type = eAddressTypeInvalid;
1606f034231aSEd Maste 
1607f034231aSEd Maste   if (!UpdateValueIfNeeded(false))
1608f034231aSEd Maste     return address;
1609f034231aSEd Maste 
161014f1b3e8SDimitry Andric   switch (m_value.GetValueType()) {
1611344a3780SDimitry Andric   case Value::ValueType::Invalid:
1612344a3780SDimitry Andric     return LLDB_INVALID_ADDRESS;
1613344a3780SDimitry Andric   case Value::ValueType::Scalar:
1614f034231aSEd Maste     address = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
1615f034231aSEd Maste     break;
1616f034231aSEd Maste 
1617344a3780SDimitry Andric   case Value::ValueType::HostAddress:
1618344a3780SDimitry Andric   case Value::ValueType::LoadAddress:
1619344a3780SDimitry Andric   case Value::ValueType::FileAddress: {
1620f034231aSEd Maste     lldb::offset_t data_offset = 0;
1621cfca06d7SDimitry Andric     address = m_data.GetAddress(&data_offset);
162214f1b3e8SDimitry Andric   } break;
1623f034231aSEd Maste   }
1624f034231aSEd Maste 
1625f034231aSEd Maste   if (address_type)
1626f034231aSEd Maste     *address_type = GetAddressTypeOfChildren();
1627f034231aSEd Maste 
1628f034231aSEd Maste   return address;
1629f034231aSEd Maste }
1630f034231aSEd Maste 
SetValueFromCString(const char * value_str,Status & error)1631b76161e4SDimitry Andric bool ValueObject::SetValueFromCString(const char *value_str, Status &error) {
1632f034231aSEd Maste   error.Clear();
1633f034231aSEd Maste   // Make sure our value is up to date first so that our location and location
1634f034231aSEd Maste   // type is valid.
163514f1b3e8SDimitry Andric   if (!UpdateValueIfNeeded(false)) {
1636f034231aSEd Maste     error.SetErrorString("unable to read value");
1637f034231aSEd Maste     return false;
1638f034231aSEd Maste   }
1639f034231aSEd Maste 
1640f034231aSEd Maste   uint64_t count = 0;
1641e81d9d49SDimitry Andric   const Encoding encoding = GetCompilerType().GetEncoding(count);
1642f034231aSEd Maste 
1643145449b1SDimitry Andric   const size_t byte_size = GetByteSize().value_or(0);
1644f034231aSEd Maste 
1645f034231aSEd Maste   Value::ValueType value_type = m_value.GetValueType();
1646f034231aSEd Maste 
1647344a3780SDimitry Andric   if (value_type == Value::ValueType::Scalar) {
1648f034231aSEd Maste     // If the value is already a scalar, then let the scalar change itself:
1649f034231aSEd Maste     m_value.GetScalar().SetValueFromCString(value_str, encoding, byte_size);
165014f1b3e8SDimitry Andric   } else if (byte_size <= 16) {
1651f034231aSEd Maste     // If the value fits in a scalar, then make a new scalar and again let the
165214f1b3e8SDimitry Andric     // scalar code do the conversion, then figure out where to put the new
165314f1b3e8SDimitry Andric     // value.
1654f034231aSEd Maste     Scalar new_scalar;
1655f034231aSEd Maste     error = new_scalar.SetValueFromCString(value_str, encoding, byte_size);
165614f1b3e8SDimitry Andric     if (error.Success()) {
165714f1b3e8SDimitry Andric       switch (value_type) {
1658344a3780SDimitry Andric       case Value::ValueType::LoadAddress: {
165914f1b3e8SDimitry Andric         // If it is a load address, then the scalar value is the storage
1660f73363f1SDimitry Andric         // location of the data, and we have to shove this value down to that
1661f73363f1SDimitry Andric         // load location.
1662f034231aSEd Maste         ExecutionContext exe_ctx(GetExecutionContextRef());
1663f034231aSEd Maste         Process *process = exe_ctx.GetProcessPtr();
166414f1b3e8SDimitry Andric         if (process) {
166514f1b3e8SDimitry Andric           addr_t target_addr =
166614f1b3e8SDimitry Andric               m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
166714f1b3e8SDimitry Andric           size_t bytes_written = process->WriteScalarToMemory(
166814f1b3e8SDimitry Andric               target_addr, new_scalar, byte_size, error);
1669f034231aSEd Maste           if (!error.Success())
1670f034231aSEd Maste             return false;
167114f1b3e8SDimitry Andric           if (bytes_written != byte_size) {
1672f034231aSEd Maste             error.SetErrorString("unable to write value to memory");
1673f034231aSEd Maste             return false;
1674f034231aSEd Maste           }
1675f034231aSEd Maste         }
167614f1b3e8SDimitry Andric       } break;
1677344a3780SDimitry Andric       case Value::ValueType::HostAddress: {
167814f1b3e8SDimitry Andric         // If it is a host address, then we stuff the scalar as a DataBuffer
167914f1b3e8SDimitry Andric         // into the Value's data.
1680f034231aSEd Maste         DataExtractor new_data;
1681f034231aSEd Maste         new_data.SetByteOrder(m_data.GetByteOrder());
1682f034231aSEd Maste 
1683f034231aSEd Maste         DataBufferSP buffer_sp(new DataBufferHeap(byte_size, 0));
1684f034231aSEd Maste         m_data.SetData(buffer_sp, 0);
1685f034231aSEd Maste         bool success = new_scalar.GetData(new_data);
168614f1b3e8SDimitry Andric         if (success) {
168714f1b3e8SDimitry Andric           new_data.CopyByteOrderedData(
168814f1b3e8SDimitry Andric               0, byte_size, const_cast<uint8_t *>(m_data.GetDataStart()),
168914f1b3e8SDimitry Andric               byte_size, m_data.GetByteOrder());
1690f034231aSEd Maste         }
1691f034231aSEd Maste         m_value.GetScalar() = (uintptr_t)m_data.GetDataStart();
1692f034231aSEd Maste 
169314f1b3e8SDimitry Andric       } break;
1694344a3780SDimitry Andric       case Value::ValueType::Invalid:
1695344a3780SDimitry Andric         error.SetErrorString("invalid location");
1696344a3780SDimitry Andric         return false;
1697344a3780SDimitry Andric       case Value::ValueType::FileAddress:
1698344a3780SDimitry Andric       case Value::ValueType::Scalar:
1699f034231aSEd Maste         break;
1700f034231aSEd Maste       }
170114f1b3e8SDimitry Andric     } else {
1702f034231aSEd Maste       return false;
1703f034231aSEd Maste     }
170414f1b3e8SDimitry Andric   } else {
1705f034231aSEd Maste     // We don't support setting things bigger than a scalar at present.
1706f034231aSEd Maste     error.SetErrorString("unable to write aggregate data type");
1707f034231aSEd Maste     return false;
1708f034231aSEd Maste   }
1709f034231aSEd Maste 
1710f73363f1SDimitry Andric   // If we have reached this point, then we have successfully changed the
1711f73363f1SDimitry Andric   // value.
1712f034231aSEd Maste   SetNeedsUpdate();
1713f034231aSEd Maste   return true;
1714f034231aSEd Maste }
1715f034231aSEd Maste 
GetDeclaration(Declaration & decl)171614f1b3e8SDimitry Andric bool ValueObject::GetDeclaration(Declaration &decl) {
1717f034231aSEd Maste   decl.Clear();
1718f034231aSEd Maste   return false;
1719f034231aSEd Maste }
1720f034231aSEd Maste 
AddSyntheticChild(ConstString key,ValueObject * valobj)17215f29bb8aSDimitry Andric void ValueObject::AddSyntheticChild(ConstString key,
172214f1b3e8SDimitry Andric                                     ValueObject *valobj) {
1723f034231aSEd Maste   m_synthetic_children[key] = valobj;
1724f034231aSEd Maste }
1725f034231aSEd Maste 
GetSyntheticChild(ConstString key) const17265f29bb8aSDimitry Andric ValueObjectSP ValueObject::GetSyntheticChild(ConstString key) const {
1727f034231aSEd Maste   ValueObjectSP synthetic_child_sp;
172814f1b3e8SDimitry Andric   std::map<ConstString, ValueObject *>::const_iterator pos =
172914f1b3e8SDimitry Andric       m_synthetic_children.find(key);
1730f034231aSEd Maste   if (pos != m_synthetic_children.end())
1731f034231aSEd Maste     synthetic_child_sp = pos->second->GetSP();
1732f034231aSEd Maste   return synthetic_child_sp;
1733f034231aSEd Maste }
1734f034231aSEd Maste 
IsPossibleDynamicType()173514f1b3e8SDimitry Andric bool ValueObject::IsPossibleDynamicType() {
1736f034231aSEd Maste   ExecutionContext exe_ctx(GetExecutionContextRef());
1737f034231aSEd Maste   Process *process = exe_ctx.GetProcessPtr();
1738f034231aSEd Maste   if (process)
1739f034231aSEd Maste     return process->IsPossibleDynamicValue(*this);
1740f034231aSEd Maste   else
17415f29bb8aSDimitry Andric     return GetCompilerType().IsPossibleDynamicType(nullptr, true, true);
1742f034231aSEd Maste }
1743f034231aSEd Maste 
IsRuntimeSupportValue()174414f1b3e8SDimitry Andric bool ValueObject::IsRuntimeSupportValue() {
17455e95aa85SEd Maste   Process *process(GetProcessSP().get());
17465f29bb8aSDimitry Andric   if (!process)
17475e95aa85SEd Maste     return false;
17485f29bb8aSDimitry Andric 
1749344a3780SDimitry Andric   // We trust that the compiler did the right thing and marked runtime support
17505f29bb8aSDimitry Andric   // values as artificial.
17515f29bb8aSDimitry Andric   if (!GetVariable() || !GetVariable()->IsArtificial())
17525f29bb8aSDimitry Andric     return false;
17535f29bb8aSDimitry Andric 
1754ead24645SDimitry Andric   if (auto *runtime = process->GetLanguageRuntime(GetVariable()->GetLanguage()))
1755cfca06d7SDimitry Andric     if (runtime->IsAllowedRuntimeValue(GetName()))
17565f29bb8aSDimitry Andric       return false;
17575f29bb8aSDimitry Andric 
17585f29bb8aSDimitry Andric   return true;
17595e95aa85SEd Maste }
17605e95aa85SEd Maste 
IsNilReference()176114f1b3e8SDimitry Andric bool ValueObject::IsNilReference() {
176214f1b3e8SDimitry Andric   if (Language *language = Language::FindPlugin(GetObjectRuntimeLanguage())) {
1763e81d9d49SDimitry Andric     return language->IsNilReference(*this);
1764e81d9d49SDimitry Andric   }
1765f034231aSEd Maste   return false;
1766e81d9d49SDimitry Andric }
1767e81d9d49SDimitry Andric 
IsUninitializedReference()176814f1b3e8SDimitry Andric bool ValueObject::IsUninitializedReference() {
176914f1b3e8SDimitry Andric   if (Language *language = Language::FindPlugin(GetObjectRuntimeLanguage())) {
1770e81d9d49SDimitry Andric     return language->IsUninitializedReference(*this);
1771e81d9d49SDimitry Andric   }
1772e81d9d49SDimitry Andric   return false;
1773f034231aSEd Maste }
1774f034231aSEd Maste 
1775f73363f1SDimitry Andric // This allows you to create an array member using and index that doesn't not
1776f73363f1SDimitry Andric // fall in the normal bounds of the array. Many times structure can be defined
1777f73363f1SDimitry Andric // as: struct Collection {
1778f034231aSEd Maste //     uint32_t item_count;
1779f034231aSEd Maste //     Item item_array[0];
1780f034231aSEd Maste // };
1781f73363f1SDimitry Andric // The size of the "item_array" is 1, but many times in practice there are more
1782f73363f1SDimitry Andric // items in "item_array".
1783f034231aSEd Maste 
GetSyntheticArrayMember(size_t index,bool can_create)178414f1b3e8SDimitry Andric ValueObjectSP ValueObject::GetSyntheticArrayMember(size_t index,
178514f1b3e8SDimitry Andric                                                    bool can_create) {
1786ac9a064cSDimitry Andric   ValueObjectSP synthetic_child_sp;
1787ac9a064cSDimitry Andric   if (IsPointerType() || IsArrayType()) {
1788b60736ecSDimitry Andric     std::string index_str = llvm::formatv("[{0}]", index);
1789f034231aSEd Maste     ConstString index_const_str(index_str);
1790f73363f1SDimitry Andric     // Check if we have already created a synthetic array member in this valid
1791f73363f1SDimitry Andric     // object. If we have we will re-use it.
1792ac9a064cSDimitry Andric     synthetic_child_sp = GetSyntheticChild(index_const_str);
1793ac9a064cSDimitry Andric     if (!synthetic_child_sp) {
1794ac9a064cSDimitry Andric       ValueObject *synthetic_child;
1795f73363f1SDimitry Andric       // We haven't made a synthetic array member for INDEX yet, so lets make
1796f73363f1SDimitry Andric       // one and cache it for any future reference.
1797ac9a064cSDimitry Andric       synthetic_child = CreateSyntheticArrayMember(index);
1798f034231aSEd Maste 
1799ac9a064cSDimitry Andric       // Cache the value if we got one back...
1800ac9a064cSDimitry Andric       if (synthetic_child) {
1801f034231aSEd Maste         AddSyntheticChild(index_const_str, synthetic_child);
1802ac9a064cSDimitry Andric         synthetic_child_sp = synthetic_child->GetSP();
1803f034231aSEd Maste         synthetic_child_sp->SetName(ConstString(index_str));
1804344a3780SDimitry Andric         synthetic_child_sp->m_flags.m_is_array_item_for_pointer = true;
1805ac9a064cSDimitry Andric       }
1806ac9a064cSDimitry Andric     }
1807ac9a064cSDimitry Andric   }
1808f034231aSEd Maste   return synthetic_child_sp;
1809f034231aSEd Maste }
1810f034231aSEd Maste 
GetSyntheticBitFieldChild(uint32_t from,uint32_t to,bool can_create)181114f1b3e8SDimitry Andric ValueObjectSP ValueObject::GetSyntheticBitFieldChild(uint32_t from, uint32_t to,
181214f1b3e8SDimitry Andric                                                      bool can_create) {
1813ac9a064cSDimitry Andric   ValueObjectSP synthetic_child_sp;
1814ac9a064cSDimitry Andric   if (IsScalarType()) {
1815b60736ecSDimitry Andric     std::string index_str = llvm::formatv("[{0}-{1}]", from, to);
1816f034231aSEd Maste     ConstString index_const_str(index_str);
1817f73363f1SDimitry Andric     // Check if we have already created a synthetic array member in this valid
1818f73363f1SDimitry Andric     // object. If we have we will re-use it.
1819ac9a064cSDimitry Andric     synthetic_child_sp = GetSyntheticChild(index_const_str);
1820ac9a064cSDimitry Andric     if (!synthetic_child_sp) {
1821f3fbd1c0SDimitry Andric       uint32_t bit_field_size = to - from + 1;
1822f3fbd1c0SDimitry Andric       uint32_t bit_field_offset = from;
1823f3fbd1c0SDimitry Andric       if (GetDataExtractor().GetByteOrder() == eByteOrderBig)
182414f1b3e8SDimitry Andric         bit_field_offset =
1825145449b1SDimitry Andric             GetByteSize().value_or(0) * 8 - bit_field_size - bit_field_offset;
1826f73363f1SDimitry Andric       // We haven't made a synthetic array member for INDEX yet, so lets make
1827f73363f1SDimitry Andric       // one and cache it for any future reference.
182814f1b3e8SDimitry Andric       ValueObjectChild *synthetic_child = new ValueObjectChild(
1829ac9a064cSDimitry Andric           *this, GetCompilerType(), index_const_str, GetByteSize().value_or(0),
1830ac9a064cSDimitry Andric           0, bit_field_size, bit_field_offset, false, false,
1831ac9a064cSDimitry Andric           eAddressTypeInvalid, 0);
1832f034231aSEd Maste 
1833ac9a064cSDimitry Andric       // Cache the value if we got one back...
1834ac9a064cSDimitry Andric       if (synthetic_child) {
1835f034231aSEd Maste         AddSyntheticChild(index_const_str, synthetic_child);
1836ac9a064cSDimitry Andric         synthetic_child_sp = synthetic_child->GetSP();
1837f034231aSEd Maste         synthetic_child_sp->SetName(ConstString(index_str));
1838344a3780SDimitry Andric         synthetic_child_sp->m_flags.m_is_bitfield_for_scalar = true;
1839ac9a064cSDimitry Andric       }
1840ac9a064cSDimitry Andric     }
1841ac9a064cSDimitry Andric   }
1842f034231aSEd Maste   return synthetic_child_sp;
1843f034231aSEd Maste }
1844f034231aSEd Maste 
GetSyntheticChildAtOffset(uint32_t offset,const CompilerType & type,bool can_create,ConstString name_const_str)184514f1b3e8SDimitry Andric ValueObjectSP ValueObject::GetSyntheticChildAtOffset(
184614f1b3e8SDimitry Andric     uint32_t offset, const CompilerType &type, bool can_create,
184714f1b3e8SDimitry Andric     ConstString name_const_str) {
1848f034231aSEd Maste 
1849f034231aSEd Maste   ValueObjectSP synthetic_child_sp;
1850f034231aSEd Maste 
1851ac9a064cSDimitry Andric   if (name_const_str.IsEmpty()) {
1852b60736ecSDimitry Andric     name_const_str.SetString("@" + std::to_string(offset));
1853ac9a064cSDimitry Andric   }
1854f034231aSEd Maste 
1855f73363f1SDimitry Andric   // Check if we have already created a synthetic array member in this valid
1856f73363f1SDimitry Andric   // object. If we have we will re-use it.
1857f034231aSEd Maste   synthetic_child_sp = GetSyntheticChild(name_const_str);
1858f034231aSEd Maste 
1859f034231aSEd Maste   if (synthetic_child_sp.get())
1860f034231aSEd Maste     return synthetic_child_sp;
1861f034231aSEd Maste 
1862f034231aSEd Maste   if (!can_create)
1863ac9a064cSDimitry Andric     return {};
1864f034231aSEd Maste 
186512bd4897SEd Maste   ExecutionContext exe_ctx(GetExecutionContextRef());
1866e3b55780SDimitry Andric   std::optional<uint64_t> size =
186794994d37SDimitry Andric       type.GetByteSize(exe_ctx.GetBestExecutionContextScope());
186894994d37SDimitry Andric   if (!size)
1869ac9a064cSDimitry Andric     return {};
187094994d37SDimitry Andric   ValueObjectChild *synthetic_child =
187194994d37SDimitry Andric       new ValueObjectChild(*this, type, name_const_str, *size, offset, 0, 0,
187214f1b3e8SDimitry Andric                            false, false, eAddressTypeInvalid, 0);
187314f1b3e8SDimitry Andric   if (synthetic_child) {
1874f034231aSEd Maste     AddSyntheticChild(name_const_str, synthetic_child);
1875f034231aSEd Maste     synthetic_child_sp = synthetic_child->GetSP();
1876f034231aSEd Maste     synthetic_child_sp->SetName(name_const_str);
1877344a3780SDimitry Andric     synthetic_child_sp->m_flags.m_is_child_at_offset = true;
1878f034231aSEd Maste   }
1879f034231aSEd Maste   return synthetic_child_sp;
1880f034231aSEd Maste }
1881f034231aSEd Maste 
GetSyntheticBase(uint32_t offset,const CompilerType & type,bool can_create,ConstString name_const_str)188214f1b3e8SDimitry Andric ValueObjectSP ValueObject::GetSyntheticBase(uint32_t offset,
1883f3fbd1c0SDimitry Andric                                             const CompilerType &type,
1884f3fbd1c0SDimitry Andric                                             bool can_create,
188514f1b3e8SDimitry Andric                                             ConstString name_const_str) {
18860cac4ca3SEd Maste   ValueObjectSP synthetic_child_sp;
18870cac4ca3SEd Maste 
188814f1b3e8SDimitry Andric   if (name_const_str.IsEmpty()) {
1889f3fbd1c0SDimitry Andric     char name_str[128];
189014f1b3e8SDimitry Andric     snprintf(name_str, sizeof(name_str), "base%s@%i",
189114f1b3e8SDimitry Andric              type.GetTypeName().AsCString("<unknown>"), offset);
1892f3fbd1c0SDimitry Andric     name_const_str.SetCString(name_str);
1893f3fbd1c0SDimitry Andric   }
18940cac4ca3SEd Maste 
1895f73363f1SDimitry Andric   // Check if we have already created a synthetic array member in this valid
1896f73363f1SDimitry Andric   // object. If we have we will re-use it.
18970cac4ca3SEd Maste   synthetic_child_sp = GetSyntheticChild(name_const_str);
18980cac4ca3SEd Maste 
18990cac4ca3SEd Maste   if (synthetic_child_sp.get())
19000cac4ca3SEd Maste     return synthetic_child_sp;
19010cac4ca3SEd Maste 
19020cac4ca3SEd Maste   if (!can_create)
1903ac9a064cSDimitry Andric     return {};
19040cac4ca3SEd Maste 
19050cac4ca3SEd Maste   const bool is_base_class = true;
19060cac4ca3SEd Maste 
190712bd4897SEd Maste   ExecutionContext exe_ctx(GetExecutionContextRef());
1908e3b55780SDimitry Andric   std::optional<uint64_t> size =
190994994d37SDimitry Andric       type.GetByteSize(exe_ctx.GetBestExecutionContextScope());
191094994d37SDimitry Andric   if (!size)
1911ac9a064cSDimitry Andric     return {};
191294994d37SDimitry Andric   ValueObjectChild *synthetic_child =
191394994d37SDimitry Andric       new ValueObjectChild(*this, type, name_const_str, *size, offset, 0, 0,
191414f1b3e8SDimitry Andric                            is_base_class, false, eAddressTypeInvalid, 0);
191514f1b3e8SDimitry Andric   if (synthetic_child) {
19160cac4ca3SEd Maste     AddSyntheticChild(name_const_str, synthetic_child);
19170cac4ca3SEd Maste     synthetic_child_sp = synthetic_child->GetSP();
19180cac4ca3SEd Maste     synthetic_child_sp->SetName(name_const_str);
19190cac4ca3SEd Maste   }
19200cac4ca3SEd Maste   return synthetic_child_sp;
19210cac4ca3SEd Maste }
19220cac4ca3SEd Maste 
1923f73363f1SDimitry Andric // your expression path needs to have a leading . or -> (unless it somehow
1924f73363f1SDimitry Andric // "looks like" an array, in which case it has a leading [ symbol). while the [
1925f73363f1SDimitry Andric // is meaningful and should be shown to the user, . and -> are just parser
1926f73363f1SDimitry Andric // design, but by no means added information for the user.. strip them off
SkipLeadingExpressionPathSeparators(const char * expression)192714f1b3e8SDimitry Andric static const char *SkipLeadingExpressionPathSeparators(const char *expression) {
1928f034231aSEd Maste   if (!expression || !expression[0])
1929f034231aSEd Maste     return expression;
1930f034231aSEd Maste   if (expression[0] == '.')
1931f034231aSEd Maste     return expression + 1;
1932f034231aSEd Maste   if (expression[0] == '-' && expression[1] == '>')
1933f034231aSEd Maste     return expression + 2;
1934f034231aSEd Maste   return expression;
1935f034231aSEd Maste }
1936f034231aSEd Maste 
1937f034231aSEd Maste ValueObjectSP
GetSyntheticExpressionPathChild(const char * expression,bool can_create)193814f1b3e8SDimitry Andric ValueObject::GetSyntheticExpressionPathChild(const char *expression,
193914f1b3e8SDimitry Andric                                              bool can_create) {
1940ac9a064cSDimitry Andric   ValueObjectSP synthetic_child_sp;
1941f034231aSEd Maste   ConstString name_const_string(expression);
1942f73363f1SDimitry Andric   // Check if we have already created a synthetic array member in this valid
1943f73363f1SDimitry Andric   // object. If we have we will re-use it.
1944ac9a064cSDimitry Andric   synthetic_child_sp = GetSyntheticChild(name_const_string);
1945ac9a064cSDimitry Andric   if (!synthetic_child_sp) {
1946f73363f1SDimitry Andric     // We haven't made a synthetic array member for expression yet, so lets
1947f73363f1SDimitry Andric     // make one and cache it for any future reference.
1948ac9a064cSDimitry Andric     synthetic_child_sp = GetValueForExpressionPath(
1949ac9a064cSDimitry Andric         expression, nullptr, nullptr,
1950ac9a064cSDimitry Andric         GetValueForExpressionPathOptions().SetSyntheticChildrenTraversal(
1951ac9a064cSDimitry Andric             GetValueForExpressionPathOptions::SyntheticChildrenTraversal::
1952ac9a064cSDimitry Andric                 None));
1953f034231aSEd Maste 
1954ac9a064cSDimitry Andric     // Cache the value if we got one back...
1955ac9a064cSDimitry Andric     if (synthetic_child_sp.get()) {
195614f1b3e8SDimitry Andric       // FIXME: this causes a "real" child to end up with its name changed to
195714f1b3e8SDimitry Andric       // the contents of expression
1958ac9a064cSDimitry Andric       AddSyntheticChild(name_const_string, synthetic_child_sp.get());
1959ac9a064cSDimitry Andric       synthetic_child_sp->SetName(
196014f1b3e8SDimitry Andric           ConstString(SkipLeadingExpressionPathSeparators(expression)));
1961ac9a064cSDimitry Andric     }
1962ac9a064cSDimitry Andric   }
1963ac9a064cSDimitry Andric   return synthetic_child_sp;
1964f034231aSEd Maste }
1965f034231aSEd Maste 
CalculateSyntheticValue()1966cfca06d7SDimitry Andric void ValueObject::CalculateSyntheticValue() {
1967f034231aSEd Maste   TargetSP target_sp(GetTargetSP());
196894994d37SDimitry Andric   if (target_sp && !target_sp->GetEnableSyntheticValue()) {
19695f29bb8aSDimitry Andric     m_synthetic_value = nullptr;
1970f034231aSEd Maste     return;
1971f034231aSEd Maste   }
1972f034231aSEd Maste 
1973f034231aSEd Maste   lldb::SyntheticChildrenSP current_synth_sp(m_synthetic_children_sp);
1974f034231aSEd Maste 
1975f034231aSEd Maste   if (!UpdateFormatsIfNeeded() && m_synthetic_value)
1976f034231aSEd Maste     return;
1977f034231aSEd Maste 
19785f29bb8aSDimitry Andric   if (m_synthetic_children_sp.get() == nullptr)
1979f034231aSEd Maste     return;
1980f034231aSEd Maste 
1981f034231aSEd Maste   if (current_synth_sp == m_synthetic_children_sp && m_synthetic_value)
1982f034231aSEd Maste     return;
1983f034231aSEd Maste 
1984f034231aSEd Maste   m_synthetic_value = new ValueObjectSynthetic(*this, m_synthetic_children_sp);
1985f034231aSEd Maste }
1986f034231aSEd Maste 
CalculateDynamicValue(DynamicValueType use_dynamic)198714f1b3e8SDimitry Andric void ValueObject::CalculateDynamicValue(DynamicValueType use_dynamic) {
1988f034231aSEd Maste   if (use_dynamic == eNoDynamicValues)
1989f034231aSEd Maste     return;
1990f034231aSEd Maste 
199114f1b3e8SDimitry Andric   if (!m_dynamic_value && !IsDynamic()) {
1992f034231aSEd Maste     ExecutionContext exe_ctx(GetExecutionContextRef());
1993f034231aSEd Maste     Process *process = exe_ctx.GetProcessPtr();
199414f1b3e8SDimitry Andric     if (process && process->IsPossibleDynamicValue(*this)) {
1995f034231aSEd Maste       ClearDynamicTypeInformation();
1996f034231aSEd Maste       m_dynamic_value = new ValueObjectDynamicValue(*this, use_dynamic);
1997f034231aSEd Maste     }
1998f034231aSEd Maste   }
1999f034231aSEd Maste }
2000f034231aSEd Maste 
GetDynamicValue(DynamicValueType use_dynamic)200114f1b3e8SDimitry Andric ValueObjectSP ValueObject::GetDynamicValue(DynamicValueType use_dynamic) {
2002f034231aSEd Maste   if (use_dynamic == eNoDynamicValues)
2003f034231aSEd Maste     return ValueObjectSP();
2004f034231aSEd Maste 
20055f29bb8aSDimitry Andric   if (!IsDynamic() && m_dynamic_value == nullptr) {
2006f034231aSEd Maste     CalculateDynamicValue(use_dynamic);
2007f034231aSEd Maste   }
20087fa27ce4SDimitry Andric   if (m_dynamic_value && m_dynamic_value->GetError().Success())
2009f034231aSEd Maste     return m_dynamic_value->GetSP();
2010f034231aSEd Maste   else
2011f034231aSEd Maste     return ValueObjectSP();
2012f034231aSEd Maste }
2013f034231aSEd Maste 
GetSyntheticValue()2014cfca06d7SDimitry Andric ValueObjectSP ValueObject::GetSyntheticValue() {
2015cfca06d7SDimitry Andric   CalculateSyntheticValue();
2016f034231aSEd Maste 
2017f034231aSEd Maste   if (m_synthetic_value)
2018f034231aSEd Maste     return m_synthetic_value->GetSP();
2019f034231aSEd Maste   else
2020f034231aSEd Maste     return ValueObjectSP();
2021f034231aSEd Maste }
2022f034231aSEd Maste 
HasSyntheticValue()202314f1b3e8SDimitry Andric bool ValueObject::HasSyntheticValue() {
2024f034231aSEd Maste   UpdateFormatsIfNeeded();
2025f034231aSEd Maste 
20265f29bb8aSDimitry Andric   if (m_synthetic_children_sp.get() == nullptr)
2027f034231aSEd Maste     return false;
2028f034231aSEd Maste 
2029cfca06d7SDimitry Andric   CalculateSyntheticValue();
2030f034231aSEd Maste 
203194994d37SDimitry Andric   return m_synthetic_value != nullptr;
2032f034231aSEd Maste }
2033f034231aSEd Maste 
GetNonBaseClassParent()203414f1b3e8SDimitry Andric ValueObject *ValueObject::GetNonBaseClassParent() {
203514f1b3e8SDimitry Andric   if (GetParent()) {
2036f034231aSEd Maste     if (GetParent()->IsBaseClass())
2037f034231aSEd Maste       return GetParent()->GetNonBaseClassParent();
2038f034231aSEd Maste     else
2039f034231aSEd Maste       return GetParent();
2040f034231aSEd Maste   }
20415f29bb8aSDimitry Andric   return nullptr;
2042f034231aSEd Maste }
2043f034231aSEd Maste 
IsBaseClass(uint32_t & depth)204414f1b3e8SDimitry Andric bool ValueObject::IsBaseClass(uint32_t &depth) {
204514f1b3e8SDimitry Andric   if (!IsBaseClass()) {
20460cac4ca3SEd Maste     depth = 0;
20470cac4ca3SEd Maste     return false;
20480cac4ca3SEd Maste   }
204914f1b3e8SDimitry Andric   if (GetParent()) {
20500cac4ca3SEd Maste     GetParent()->IsBaseClass(depth);
20510cac4ca3SEd Maste     depth = depth + 1;
20520cac4ca3SEd Maste     return true;
20530cac4ca3SEd Maste   }
20540cac4ca3SEd Maste   // TODO: a base of no parent? weird..
20550cac4ca3SEd Maste   depth = 1;
20560cac4ca3SEd Maste   return true;
20570cac4ca3SEd Maste }
20580cac4ca3SEd Maste 
GetExpressionPath(Stream & s,GetExpressionPathFormat epformat)2059cfca06d7SDimitry Andric void ValueObject::GetExpressionPath(Stream &s,
206014f1b3e8SDimitry Andric                                     GetExpressionPathFormat epformat) {
206114f1b3e8SDimitry Andric   // synthetic children do not actually "exist" as part of the hierarchy, and
2062f73363f1SDimitry Andric   // sometimes they are consed up in ways that don't make sense from an
2063f73363f1SDimitry Andric   // underlying language/API standpoint. So, use a special code path here to
2064f73363f1SDimitry Andric   // return something that can hopefully be used in expression
2065344a3780SDimitry Andric   if (m_flags.m_is_synthetic_children_generated) {
2066205afe67SEd Maste     UpdateValueIfNeeded();
2067205afe67SEd Maste 
2068344a3780SDimitry Andric     if (m_value.GetValueType() == Value::ValueType::LoadAddress) {
206914f1b3e8SDimitry Andric       if (IsPointerOrReferenceType()) {
207014f1b3e8SDimitry Andric         s.Printf("((%s)0x%" PRIx64 ")", GetTypeName().AsCString("void"),
2071205afe67SEd Maste                  GetValueAsUnsigned(0));
2072205afe67SEd Maste         return;
207314f1b3e8SDimitry Andric       } else {
207414f1b3e8SDimitry Andric         uint64_t load_addr =
207514f1b3e8SDimitry Andric             m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
207614f1b3e8SDimitry Andric         if (load_addr != LLDB_INVALID_ADDRESS) {
207714f1b3e8SDimitry Andric           s.Printf("(*( (%s *)0x%" PRIx64 "))", GetTypeName().AsCString("void"),
2078205afe67SEd Maste                    load_addr);
2079205afe67SEd Maste           return;
2080205afe67SEd Maste         }
2081205afe67SEd Maste       }
2082205afe67SEd Maste     }
2083205afe67SEd Maste 
208414f1b3e8SDimitry Andric     if (CanProvideValue()) {
208514f1b3e8SDimitry Andric       s.Printf("((%s)%s)", GetTypeName().AsCString("void"),
2086205afe67SEd Maste                GetValueAsCString());
2087205afe67SEd Maste       return;
2088205afe67SEd Maste     }
2089205afe67SEd Maste 
2090205afe67SEd Maste     return;
2091205afe67SEd Maste   }
2092205afe67SEd Maste 
2093f034231aSEd Maste   const bool is_deref_of_parent = IsDereferenceOfParent();
2094f034231aSEd Maste 
209514f1b3e8SDimitry Andric   if (is_deref_of_parent &&
209614f1b3e8SDimitry Andric       epformat == eGetExpressionPathFormatDereferencePointers) {
209714f1b3e8SDimitry Andric     // this is the original format of GetExpressionPath() producing code like
2098f73363f1SDimitry Andric     // *(a_ptr).memberName, which is entirely fine, until you put this into
209914f1b3e8SDimitry Andric     // StackFrame::GetValueForVariableExpressionPath() which prefers to see
2100f73363f1SDimitry Andric     // a_ptr->memberName. the eHonorPointers mode is meant to produce strings
2101f73363f1SDimitry Andric     // in this latter format
2102f034231aSEd Maste     s.PutCString("*(");
2103f034231aSEd Maste   }
2104f034231aSEd Maste 
2105f034231aSEd Maste   ValueObject *parent = GetParent();
2106f034231aSEd Maste 
2107f034231aSEd Maste   if (parent)
2108cfca06d7SDimitry Andric     parent->GetExpressionPath(s, epformat);
2109f034231aSEd Maste 
2110f73363f1SDimitry Andric   // if we are a deref_of_parent just because we are synthetic array members
2111f73363f1SDimitry Andric   // made up to allow ptr[%d] syntax to work in variable printing, then add our
2112f73363f1SDimitry Andric   // name ([%d]) to the expression path
2113344a3780SDimitry Andric   if (m_flags.m_is_array_item_for_pointer &&
211414f1b3e8SDimitry Andric       epformat == eGetExpressionPathFormatHonorPointers)
2115cfca06d7SDimitry Andric     s.PutCString(m_name.GetStringRef());
2116f034231aSEd Maste 
211714f1b3e8SDimitry Andric   if (!IsBaseClass()) {
211814f1b3e8SDimitry Andric     if (!is_deref_of_parent) {
2119f034231aSEd Maste       ValueObject *non_base_class_parent = GetNonBaseClassParent();
212014f1b3e8SDimitry Andric       if (non_base_class_parent &&
212114f1b3e8SDimitry Andric           !non_base_class_parent->GetName().IsEmpty()) {
212214f1b3e8SDimitry Andric         CompilerType non_base_class_parent_compiler_type =
212314f1b3e8SDimitry Andric             non_base_class_parent->GetCompilerType();
212414f1b3e8SDimitry Andric         if (non_base_class_parent_compiler_type) {
212514f1b3e8SDimitry Andric           if (parent && parent->IsDereferenceOfParent() &&
212614f1b3e8SDimitry Andric               epformat == eGetExpressionPathFormatHonorPointers) {
2127f034231aSEd Maste             s.PutCString("->");
212814f1b3e8SDimitry Andric           } else {
212914f1b3e8SDimitry Andric             const uint32_t non_base_class_parent_type_info =
213014f1b3e8SDimitry Andric                 non_base_class_parent_compiler_type.GetTypeInfo();
2131f034231aSEd Maste 
213214f1b3e8SDimitry Andric             if (non_base_class_parent_type_info & eTypeIsPointer) {
2133f034231aSEd Maste               s.PutCString("->");
213414f1b3e8SDimitry Andric             } else if ((non_base_class_parent_type_info & eTypeHasChildren) &&
213514f1b3e8SDimitry Andric                        !(non_base_class_parent_type_info & eTypeIsArray)) {
2136f034231aSEd Maste               s.PutChar('.');
2137f034231aSEd Maste             }
2138f034231aSEd Maste           }
2139f034231aSEd Maste         }
2140f034231aSEd Maste       }
2141f034231aSEd Maste 
2142f034231aSEd Maste       const char *name = GetName().GetCString();
2143cfca06d7SDimitry Andric       if (name)
2144f034231aSEd Maste         s.PutCString(name);
2145f034231aSEd Maste     }
2146f034231aSEd Maste   }
2147f034231aSEd Maste 
214814f1b3e8SDimitry Andric   if (is_deref_of_parent &&
214914f1b3e8SDimitry Andric       epformat == eGetExpressionPathFormatDereferencePointers) {
2150f034231aSEd Maste     s.PutChar(')');
2151f034231aSEd Maste   }
2152f034231aSEd Maste }
2153f034231aSEd Maste 
GetValueForExpressionPath(llvm::StringRef expression,ExpressionPathScanEndReason * reason_to_stop,ExpressionPathEndResultType * final_value_type,const GetValueForExpressionPathOptions & options,ExpressionPathAftermath * final_task_on_target)215414f1b3e8SDimitry Andric ValueObjectSP ValueObject::GetValueForExpressionPath(
215514f1b3e8SDimitry Andric     llvm::StringRef expression, ExpressionPathScanEndReason *reason_to_stop,
2156f034231aSEd Maste     ExpressionPathEndResultType *final_value_type,
2157f034231aSEd Maste     const GetValueForExpressionPathOptions &options,
215814f1b3e8SDimitry Andric     ExpressionPathAftermath *final_task_on_target) {
2159f034231aSEd Maste 
2160ac9a064cSDimitry Andric   ExpressionPathScanEndReason dummy_reason_to_stop =
2161ac9a064cSDimitry Andric       ValueObject::eExpressionPathScanEndReasonUnknown;
2162ac9a064cSDimitry Andric   ExpressionPathEndResultType dummy_final_value_type =
2163ac9a064cSDimitry Andric       ValueObject::eExpressionPathEndResultTypeInvalid;
2164ac9a064cSDimitry Andric   ExpressionPathAftermath dummy_final_task_on_target =
2165ac9a064cSDimitry Andric       ValueObject::eExpressionPathAftermathNothing;
2166f034231aSEd Maste 
2167ac9a064cSDimitry Andric   ValueObjectSP ret_val = GetValueForExpressionPath_Impl(
2168ac9a064cSDimitry Andric       expression, reason_to_stop ? reason_to_stop : &dummy_reason_to_stop,
2169ac9a064cSDimitry Andric       final_value_type ? final_value_type : &dummy_final_value_type, options,
2170ac9a064cSDimitry Andric       final_task_on_target ? final_task_on_target
2171ac9a064cSDimitry Andric                            : &dummy_final_task_on_target);
2172f034231aSEd Maste 
2173ac9a064cSDimitry Andric   if (!final_task_on_target ||
2174ac9a064cSDimitry Andric       *final_task_on_target == ValueObject::eExpressionPathAftermathNothing)
2175ac9a064cSDimitry Andric     return ret_val;
2176f034231aSEd Maste 
2177ac9a064cSDimitry Andric   if (ret_val.get() &&
2178ac9a064cSDimitry Andric       ((final_value_type ? *final_value_type : dummy_final_value_type) ==
2179ac9a064cSDimitry Andric        eExpressionPathEndResultTypePlain)) // I can only deref and takeaddress
2180ac9a064cSDimitry Andric                                            // of plain objects
2181ac9a064cSDimitry Andric   {
2182ac9a064cSDimitry Andric     if ((final_task_on_target ? *final_task_on_target
2183ac9a064cSDimitry Andric                               : dummy_final_task_on_target) ==
2184ac9a064cSDimitry Andric         ValueObject::eExpressionPathAftermathDereference) {
2185b76161e4SDimitry Andric       Status error;
2186ac9a064cSDimitry Andric       ValueObjectSP final_value = ret_val->Dereference(error);
2187ac9a064cSDimitry Andric       if (error.Fail() || !final_value.get()) {
2188f034231aSEd Maste         if (reason_to_stop)
2189ac9a064cSDimitry Andric           *reason_to_stop =
2190ac9a064cSDimitry Andric               ValueObject::eExpressionPathScanEndReasonDereferencingFailed;
2191f034231aSEd Maste         if (final_value_type)
2192ac9a064cSDimitry Andric           *final_value_type = ValueObject::eExpressionPathEndResultTypeInvalid;
2193f034231aSEd Maste         return ValueObjectSP();
2194ac9a064cSDimitry Andric       } else {
2195ac9a064cSDimitry Andric         if (final_task_on_target)
2196ac9a064cSDimitry Andric           *final_task_on_target = ValueObject::eExpressionPathAftermathNothing;
2197ac9a064cSDimitry Andric         return final_value;
2198ac9a064cSDimitry Andric       }
2199ac9a064cSDimitry Andric     }
2200ac9a064cSDimitry Andric     if (*final_task_on_target ==
2201ac9a064cSDimitry Andric         ValueObject::eExpressionPathAftermathTakeAddress) {
2202ac9a064cSDimitry Andric       Status error;
2203ac9a064cSDimitry Andric       ValueObjectSP final_value = ret_val->AddressOf(error);
2204ac9a064cSDimitry Andric       if (error.Fail() || !final_value.get()) {
2205ac9a064cSDimitry Andric         if (reason_to_stop)
2206ac9a064cSDimitry Andric           *reason_to_stop =
2207ac9a064cSDimitry Andric               ValueObject::eExpressionPathScanEndReasonTakingAddressFailed;
2208ac9a064cSDimitry Andric         if (final_value_type)
2209ac9a064cSDimitry Andric           *final_value_type = ValueObject::eExpressionPathEndResultTypeInvalid;
2210ac9a064cSDimitry Andric         return ValueObjectSP();
2211ac9a064cSDimitry Andric       } else {
2212ac9a064cSDimitry Andric         if (final_task_on_target)
2213ac9a064cSDimitry Andric           *final_task_on_target = ValueObject::eExpressionPathAftermathNothing;
2214ac9a064cSDimitry Andric         return final_value;
2215ac9a064cSDimitry Andric       }
2216ac9a064cSDimitry Andric     }
2217ac9a064cSDimitry Andric   }
2218ac9a064cSDimitry Andric   return ret_val; // final_task_on_target will still have its original value, so
2219ac9a064cSDimitry Andric                   // you know I did not do it
2220f034231aSEd Maste }
2221f034231aSEd Maste 
GetValueForExpressionPath_Impl(llvm::StringRef expression,ExpressionPathScanEndReason * reason_to_stop,ExpressionPathEndResultType * final_result,const GetValueForExpressionPathOptions & options,ExpressionPathAftermath * what_next)222214f1b3e8SDimitry Andric ValueObjectSP ValueObject::GetValueForExpressionPath_Impl(
222314f1b3e8SDimitry Andric     llvm::StringRef expression, ExpressionPathScanEndReason *reason_to_stop,
2224f034231aSEd Maste     ExpressionPathEndResultType *final_result,
2225f034231aSEd Maste     const GetValueForExpressionPathOptions &options,
222614f1b3e8SDimitry Andric     ExpressionPathAftermath *what_next) {
2227f034231aSEd Maste   ValueObjectSP root = GetSP();
2228f034231aSEd Maste 
222914f1b3e8SDimitry Andric   if (!root)
223014f1b3e8SDimitry Andric     return nullptr;
2231f034231aSEd Maste 
223214f1b3e8SDimitry Andric   llvm::StringRef remainder = expression;
2233f034231aSEd Maste 
223414f1b3e8SDimitry Andric   while (true) {
223514f1b3e8SDimitry Andric     llvm::StringRef temp_expression = remainder;
2236f034231aSEd Maste 
2237e81d9d49SDimitry Andric     CompilerType root_compiler_type = root->GetCompilerType();
2238e81d9d49SDimitry Andric     CompilerType pointee_compiler_type;
2239e81d9d49SDimitry Andric     Flags pointee_compiler_type_info;
2240f034231aSEd Maste 
224114f1b3e8SDimitry Andric     Flags root_compiler_type_info(
224214f1b3e8SDimitry Andric         root_compiler_type.GetTypeInfo(&pointee_compiler_type));
2243e81d9d49SDimitry Andric     if (pointee_compiler_type)
2244e81d9d49SDimitry Andric       pointee_compiler_type_info.Reset(pointee_compiler_type.GetTypeInfo());
2245f034231aSEd Maste 
224614f1b3e8SDimitry Andric     if (temp_expression.empty()) {
2247f034231aSEd Maste       *reason_to_stop = ValueObject::eExpressionPathScanEndReasonEndOfString;
2248f034231aSEd Maste       return root;
2249f034231aSEd Maste     }
2250f034231aSEd Maste 
225114f1b3e8SDimitry Andric     switch (temp_expression.front()) {
225214f1b3e8SDimitry Andric     case '-': {
225314f1b3e8SDimitry Andric       temp_expression = temp_expression.drop_front();
2254f034231aSEd Maste       if (options.m_check_dot_vs_arrow_syntax &&
225514f1b3e8SDimitry Andric           root_compiler_type_info.Test(eTypeIsPointer)) // if you are trying to
225614f1b3e8SDimitry Andric                                                         // use -> on a
225714f1b3e8SDimitry Andric                                                         // non-pointer and I
225814f1b3e8SDimitry Andric                                                         // must catch the error
2259f034231aSEd Maste       {
226014f1b3e8SDimitry Andric         *reason_to_stop =
226114f1b3e8SDimitry Andric             ValueObject::eExpressionPathScanEndReasonArrowInsteadOfDot;
2262f034231aSEd Maste         *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
2263f034231aSEd Maste         return ValueObjectSP();
2264f034231aSEd Maste       }
226514f1b3e8SDimitry Andric       if (root_compiler_type_info.Test(eTypeIsObjC) && // if yo are trying to
226614f1b3e8SDimitry Andric                                                        // extract an ObjC IVar
226714f1b3e8SDimitry Andric                                                        // when this is forbidden
2268e81d9d49SDimitry Andric           root_compiler_type_info.Test(eTypeIsPointer) &&
226914f1b3e8SDimitry Andric           options.m_no_fragile_ivar) {
227014f1b3e8SDimitry Andric         *reason_to_stop =
227114f1b3e8SDimitry Andric             ValueObject::eExpressionPathScanEndReasonFragileIVarNotAllowed;
2272f034231aSEd Maste         *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
2273f034231aSEd Maste         return ValueObjectSP();
2274f034231aSEd Maste       }
2275312c0ed1SDimitry Andric       if (!temp_expression.starts_with(">")) {
227614f1b3e8SDimitry Andric         *reason_to_stop =
227714f1b3e8SDimitry Andric             ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol;
2278f034231aSEd Maste         *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
2279f034231aSEd Maste         return ValueObjectSP();
2280f034231aSEd Maste       }
2281f034231aSEd Maste     }
2282e3b55780SDimitry Andric       [[fallthrough]];
2283f034231aSEd Maste     case '.': // or fallthrough from ->
2284f034231aSEd Maste     {
228514f1b3e8SDimitry Andric       if (options.m_check_dot_vs_arrow_syntax &&
228614f1b3e8SDimitry Andric           temp_expression.front() == '.' &&
228714f1b3e8SDimitry Andric           root_compiler_type_info.Test(eTypeIsPointer)) // if you are trying to
228814f1b3e8SDimitry Andric                                                         // use . on a pointer
228914f1b3e8SDimitry Andric                                                         // and I must catch the
229014f1b3e8SDimitry Andric                                                         // error
2291f034231aSEd Maste       {
229214f1b3e8SDimitry Andric         *reason_to_stop =
229314f1b3e8SDimitry Andric             ValueObject::eExpressionPathScanEndReasonDotInsteadOfArrow;
2294f034231aSEd Maste         *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
229514f1b3e8SDimitry Andric         return nullptr;
2296f034231aSEd Maste       }
229714f1b3e8SDimitry Andric       temp_expression = temp_expression.drop_front(); // skip . or >
229814f1b3e8SDimitry Andric 
229914f1b3e8SDimitry Andric       size_t next_sep_pos = temp_expression.find_first_of("-.[", 1);
230014f1b3e8SDimitry Andric       if (next_sep_pos == llvm::StringRef::npos) // if no other separator just
230114f1b3e8SDimitry Andric                                                  // expand this last layer
2302f034231aSEd Maste       {
2303b1c73532SDimitry Andric         llvm::StringRef child_name = temp_expression;
230414f1b3e8SDimitry Andric         ValueObjectSP child_valobj_sp =
23057fa27ce4SDimitry Andric             root->GetChildMemberWithName(child_name);
2306f034231aSEd Maste 
2307f034231aSEd Maste         if (child_valobj_sp.get()) // we know we are done, so just return
2308f034231aSEd Maste         {
230914f1b3e8SDimitry Andric           *reason_to_stop =
231014f1b3e8SDimitry Andric               ValueObject::eExpressionPathScanEndReasonEndOfString;
2311f034231aSEd Maste           *final_result = ValueObject::eExpressionPathEndResultTypePlain;
2312f034231aSEd Maste           return child_valobj_sp;
231314f1b3e8SDimitry Andric         } else {
231414f1b3e8SDimitry Andric           switch (options.m_synthetic_children_traversal) {
231514f1b3e8SDimitry Andric           case GetValueForExpressionPathOptions::SyntheticChildrenTraversal::
231614f1b3e8SDimitry Andric               None:
23175e95aa85SEd Maste             break;
231814f1b3e8SDimitry Andric           case GetValueForExpressionPathOptions::SyntheticChildrenTraversal::
231914f1b3e8SDimitry Andric               FromSynthetic:
232014f1b3e8SDimitry Andric             if (root->IsSynthetic()) {
23215e95aa85SEd Maste               child_valobj_sp = root->GetNonSyntheticValue();
23225e95aa85SEd Maste               if (child_valobj_sp.get())
232314f1b3e8SDimitry Andric                 child_valobj_sp =
23247fa27ce4SDimitry Andric                     child_valobj_sp->GetChildMemberWithName(child_name);
2325f034231aSEd Maste             }
23265e95aa85SEd Maste             break;
232714f1b3e8SDimitry Andric           case GetValueForExpressionPathOptions::SyntheticChildrenTraversal::
232814f1b3e8SDimitry Andric               ToSynthetic:
232914f1b3e8SDimitry Andric             if (!root->IsSynthetic()) {
2330f034231aSEd Maste               child_valobj_sp = root->GetSyntheticValue();
2331f034231aSEd Maste               if (child_valobj_sp.get())
233214f1b3e8SDimitry Andric                 child_valobj_sp =
23337fa27ce4SDimitry Andric                     child_valobj_sp->GetChildMemberWithName(child_name);
2334f034231aSEd Maste             }
23355e95aa85SEd Maste             break;
233614f1b3e8SDimitry Andric           case GetValueForExpressionPathOptions::SyntheticChildrenTraversal::
233714f1b3e8SDimitry Andric               Both:
233814f1b3e8SDimitry Andric             if (root->IsSynthetic()) {
23395e95aa85SEd Maste               child_valobj_sp = root->GetNonSyntheticValue();
23405e95aa85SEd Maste               if (child_valobj_sp.get())
234114f1b3e8SDimitry Andric                 child_valobj_sp =
23427fa27ce4SDimitry Andric                     child_valobj_sp->GetChildMemberWithName(child_name);
234314f1b3e8SDimitry Andric             } else {
23445e95aa85SEd Maste               child_valobj_sp = root->GetSyntheticValue();
23455e95aa85SEd Maste               if (child_valobj_sp.get())
234614f1b3e8SDimitry Andric                 child_valobj_sp =
23477fa27ce4SDimitry Andric                     child_valobj_sp->GetChildMemberWithName(child_name);
23485e95aa85SEd Maste             }
23495e95aa85SEd Maste             break;
23505e95aa85SEd Maste           }
23515e95aa85SEd Maste         }
2352f034231aSEd Maste 
235314f1b3e8SDimitry Andric         // if we are here and options.m_no_synthetic_children is true,
2354f73363f1SDimitry Andric         // child_valobj_sp is going to be a NULL SP, so we hit the "else"
2355f73363f1SDimitry Andric         // branch, and return an error
2356f034231aSEd Maste         if (child_valobj_sp.get()) // if it worked, just return
2357f034231aSEd Maste         {
235814f1b3e8SDimitry Andric           *reason_to_stop =
235914f1b3e8SDimitry Andric               ValueObject::eExpressionPathScanEndReasonEndOfString;
2360f034231aSEd Maste           *final_result = ValueObject::eExpressionPathEndResultTypePlain;
2361f034231aSEd Maste           return child_valobj_sp;
236214f1b3e8SDimitry Andric         } else {
236314f1b3e8SDimitry Andric           *reason_to_stop =
236414f1b3e8SDimitry Andric               ValueObject::eExpressionPathScanEndReasonNoSuchChild;
2365f034231aSEd Maste           *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
236614f1b3e8SDimitry Andric           return nullptr;
2367f034231aSEd Maste         }
236814f1b3e8SDimitry Andric       } else // other layers do expand
2369f034231aSEd Maste       {
237014f1b3e8SDimitry Andric         llvm::StringRef next_separator = temp_expression.substr(next_sep_pos);
2371b1c73532SDimitry Andric         llvm::StringRef child_name = temp_expression.slice(0, next_sep_pos);
237214f1b3e8SDimitry Andric 
237314f1b3e8SDimitry Andric         ValueObjectSP child_valobj_sp =
23747fa27ce4SDimitry Andric             root->GetChildMemberWithName(child_name);
2375f034231aSEd Maste         if (child_valobj_sp.get()) // store the new root and move on
2376f034231aSEd Maste         {
2377f034231aSEd Maste           root = child_valobj_sp;
237814f1b3e8SDimitry Andric           remainder = next_separator;
2379f034231aSEd Maste           *final_result = ValueObject::eExpressionPathEndResultTypePlain;
2380f034231aSEd Maste           continue;
238114f1b3e8SDimitry Andric         } else {
238214f1b3e8SDimitry Andric           switch (options.m_synthetic_children_traversal) {
238314f1b3e8SDimitry Andric           case GetValueForExpressionPathOptions::SyntheticChildrenTraversal::
238414f1b3e8SDimitry Andric               None:
23855e95aa85SEd Maste             break;
238614f1b3e8SDimitry Andric           case GetValueForExpressionPathOptions::SyntheticChildrenTraversal::
238714f1b3e8SDimitry Andric               FromSynthetic:
238814f1b3e8SDimitry Andric             if (root->IsSynthetic()) {
23895e95aa85SEd Maste               child_valobj_sp = root->GetNonSyntheticValue();
23905e95aa85SEd Maste               if (child_valobj_sp.get())
239114f1b3e8SDimitry Andric                 child_valobj_sp =
23927fa27ce4SDimitry Andric                     child_valobj_sp->GetChildMemberWithName(child_name);
2393f034231aSEd Maste             }
23945e95aa85SEd Maste             break;
239514f1b3e8SDimitry Andric           case GetValueForExpressionPathOptions::SyntheticChildrenTraversal::
239614f1b3e8SDimitry Andric               ToSynthetic:
239714f1b3e8SDimitry Andric             if (!root->IsSynthetic()) {
23985e95aa85SEd Maste               child_valobj_sp = root->GetSyntheticValue();
23995e95aa85SEd Maste               if (child_valobj_sp.get())
240014f1b3e8SDimitry Andric                 child_valobj_sp =
24017fa27ce4SDimitry Andric                     child_valobj_sp->GetChildMemberWithName(child_name);
24025e95aa85SEd Maste             }
24035e95aa85SEd Maste             break;
240414f1b3e8SDimitry Andric           case GetValueForExpressionPathOptions::SyntheticChildrenTraversal::
240514f1b3e8SDimitry Andric               Both:
240614f1b3e8SDimitry Andric             if (root->IsSynthetic()) {
24075e95aa85SEd Maste               child_valobj_sp = root->GetNonSyntheticValue();
24085e95aa85SEd Maste               if (child_valobj_sp.get())
240914f1b3e8SDimitry Andric                 child_valobj_sp =
24107fa27ce4SDimitry Andric                     child_valobj_sp->GetChildMemberWithName(child_name);
241114f1b3e8SDimitry Andric             } else {
24125e95aa85SEd Maste               child_valobj_sp = root->GetSyntheticValue();
24135e95aa85SEd Maste               if (child_valobj_sp.get())
241414f1b3e8SDimitry Andric                 child_valobj_sp =
24157fa27ce4SDimitry Andric                     child_valobj_sp->GetChildMemberWithName(child_name);
24165e95aa85SEd Maste             }
24175e95aa85SEd Maste             break;
24185e95aa85SEd Maste           }
24195e95aa85SEd Maste         }
2420f034231aSEd Maste 
242114f1b3e8SDimitry Andric         // if we are here and options.m_no_synthetic_children is true,
2422f73363f1SDimitry Andric         // child_valobj_sp is going to be a NULL SP, so we hit the "else"
2423f73363f1SDimitry Andric         // branch, and return an error
2424f034231aSEd Maste         if (child_valobj_sp.get()) // if it worked, move on
2425f034231aSEd Maste         {
2426f034231aSEd Maste           root = child_valobj_sp;
242714f1b3e8SDimitry Andric           remainder = next_separator;
2428f034231aSEd Maste           *final_result = ValueObject::eExpressionPathEndResultTypePlain;
2429f034231aSEd Maste           continue;
243014f1b3e8SDimitry Andric         } else {
243114f1b3e8SDimitry Andric           *reason_to_stop =
243214f1b3e8SDimitry Andric               ValueObject::eExpressionPathScanEndReasonNoSuchChild;
2433f034231aSEd Maste           *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
243414f1b3e8SDimitry Andric           return nullptr;
2435f034231aSEd Maste         }
2436f034231aSEd Maste       }
2437f034231aSEd Maste       break;
2438f034231aSEd Maste     }
243914f1b3e8SDimitry Andric     case '[': {
244014f1b3e8SDimitry Andric       if (!root_compiler_type_info.Test(eTypeIsArray) &&
244114f1b3e8SDimitry Andric           !root_compiler_type_info.Test(eTypeIsPointer) &&
244214f1b3e8SDimitry Andric           !root_compiler_type_info.Test(
244314f1b3e8SDimitry Andric               eTypeIsVector)) // if this is not a T[] nor a T*
2444f034231aSEd Maste       {
244514f1b3e8SDimitry Andric         if (!root_compiler_type_info.Test(
244614f1b3e8SDimitry Andric                 eTypeIsScalar)) // if this is not even a scalar...
2447f034231aSEd Maste         {
244814f1b3e8SDimitry Andric           if (options.m_synthetic_children_traversal ==
244914f1b3e8SDimitry Andric               GetValueForExpressionPathOptions::SyntheticChildrenTraversal::
245014f1b3e8SDimitry Andric                   None) // ...only chance left is synthetic
2451f034231aSEd Maste           {
245214f1b3e8SDimitry Andric             *reason_to_stop =
245314f1b3e8SDimitry Andric                 ValueObject::eExpressionPathScanEndReasonRangeOperatorInvalid;
245414f1b3e8SDimitry Andric             *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
245514f1b3e8SDimitry Andric             return ValueObjectSP();
245614f1b3e8SDimitry Andric           }
245714f1b3e8SDimitry Andric         } else if (!options.m_allow_bitfields_syntax) // if this is a scalar,
245814f1b3e8SDimitry Andric                                                       // check that we can
245914f1b3e8SDimitry Andric                                                       // expand bitfields
2460f034231aSEd Maste         {
246114f1b3e8SDimitry Andric           *reason_to_stop =
246214f1b3e8SDimitry Andric               ValueObject::eExpressionPathScanEndReasonRangeOperatorNotAllowed;
2463f034231aSEd Maste           *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
2464f034231aSEd Maste           return ValueObjectSP();
2465f034231aSEd Maste         }
2466f034231aSEd Maste       }
246714f1b3e8SDimitry Andric       if (temp_expression[1] ==
246814f1b3e8SDimitry Andric           ']') // if this is an unbounded range it only works for arrays
2469f034231aSEd Maste       {
247014f1b3e8SDimitry Andric         if (!root_compiler_type_info.Test(eTypeIsArray)) {
247114f1b3e8SDimitry Andric           *reason_to_stop =
247214f1b3e8SDimitry Andric               ValueObject::eExpressionPathScanEndReasonEmptyRangeNotAllowed;
2473f034231aSEd Maste           *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
247414f1b3e8SDimitry Andric           return nullptr;
247514f1b3e8SDimitry Andric         } else // even if something follows, we cannot expand unbounded ranges,
247614f1b3e8SDimitry Andric                // just let the caller do it
2477f034231aSEd Maste         {
247814f1b3e8SDimitry Andric           *reason_to_stop =
247914f1b3e8SDimitry Andric               ValueObject::eExpressionPathScanEndReasonArrayRangeOperatorMet;
248014f1b3e8SDimitry Andric           *final_result =
248114f1b3e8SDimitry Andric               ValueObject::eExpressionPathEndResultTypeUnboundedRange;
2482f034231aSEd Maste           return root;
2483f034231aSEd Maste         }
2484f034231aSEd Maste       }
248514f1b3e8SDimitry Andric 
248614f1b3e8SDimitry Andric       size_t close_bracket_position = temp_expression.find(']', 1);
248714f1b3e8SDimitry Andric       if (close_bracket_position ==
248814f1b3e8SDimitry Andric           llvm::StringRef::npos) // if there is no ], this is a syntax error
2489f034231aSEd Maste       {
249014f1b3e8SDimitry Andric         *reason_to_stop =
249114f1b3e8SDimitry Andric             ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol;
2492f034231aSEd Maste         *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
249314f1b3e8SDimitry Andric         return nullptr;
2494f034231aSEd Maste       }
249514f1b3e8SDimitry Andric 
249614f1b3e8SDimitry Andric       llvm::StringRef bracket_expr =
249714f1b3e8SDimitry Andric           temp_expression.slice(1, close_bracket_position);
249814f1b3e8SDimitry Andric 
249914f1b3e8SDimitry Andric       // If this was an empty expression it would have been caught by the if
250014f1b3e8SDimitry Andric       // above.
250114f1b3e8SDimitry Andric       assert(!bracket_expr.empty());
250214f1b3e8SDimitry Andric 
250314f1b3e8SDimitry Andric       if (!bracket_expr.contains('-')) {
2504f73363f1SDimitry Andric         // if no separator, this is of the form [N].  Note that this cannot be
2505f73363f1SDimitry Andric         // an unbounded range of the form [], because that case was handled
250614f1b3e8SDimitry Andric         // above with an unconditional return.
250714f1b3e8SDimitry Andric         unsigned long index = 0;
250814f1b3e8SDimitry Andric         if (bracket_expr.getAsInteger(0, index)) {
250914f1b3e8SDimitry Andric           *reason_to_stop =
251014f1b3e8SDimitry Andric               ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol;
2511f034231aSEd Maste           *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
251214f1b3e8SDimitry Andric           return nullptr;
2513f034231aSEd Maste         }
251414f1b3e8SDimitry Andric 
2515f034231aSEd Maste         // from here on we do have a valid index
251614f1b3e8SDimitry Andric         if (root_compiler_type_info.Test(eTypeIsArray)) {
25177fa27ce4SDimitry Andric           ValueObjectSP child_valobj_sp = root->GetChildAtIndex(index);
2518f034231aSEd Maste           if (!child_valobj_sp)
25195e95aa85SEd Maste             child_valobj_sp = root->GetSyntheticArrayMember(index, true);
2520f034231aSEd Maste           if (!child_valobj_sp)
252114f1b3e8SDimitry Andric             if (root->HasSyntheticValue() &&
2522ac9a064cSDimitry Andric                 llvm::expectedToStdOptional(
2523ac9a064cSDimitry Andric                     root->GetSyntheticValue()->GetNumChildren())
2524ac9a064cSDimitry Andric                         .value_or(0) > index)
252514f1b3e8SDimitry Andric               child_valobj_sp =
25267fa27ce4SDimitry Andric                   root->GetSyntheticValue()->GetChildAtIndex(index);
252714f1b3e8SDimitry Andric           if (child_valobj_sp) {
2528f034231aSEd Maste             root = child_valobj_sp;
252914f1b3e8SDimitry Andric             remainder =
253014f1b3e8SDimitry Andric                 temp_expression.substr(close_bracket_position + 1); // skip ]
2531f034231aSEd Maste             *final_result = ValueObject::eExpressionPathEndResultTypePlain;
2532f034231aSEd Maste             continue;
253314f1b3e8SDimitry Andric           } else {
253414f1b3e8SDimitry Andric             *reason_to_stop =
253514f1b3e8SDimitry Andric                 ValueObject::eExpressionPathScanEndReasonNoSuchChild;
2536f034231aSEd Maste             *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
253714f1b3e8SDimitry Andric             return nullptr;
2538f034231aSEd Maste           }
253914f1b3e8SDimitry Andric         } else if (root_compiler_type_info.Test(eTypeIsPointer)) {
254014f1b3e8SDimitry Andric           if (*what_next ==
254114f1b3e8SDimitry Andric                   ValueObject::
254214f1b3e8SDimitry Andric                       eExpressionPathAftermathDereference && // if this is a
254314f1b3e8SDimitry Andric                                                              // ptr-to-scalar, I
254414f1b3e8SDimitry Andric                                                              // am accessing it
254514f1b3e8SDimitry Andric                                                              // by index and I
254614f1b3e8SDimitry Andric                                                              // would have
254714f1b3e8SDimitry Andric                                                              // deref'ed anyway,
254814f1b3e8SDimitry Andric                                                              // then do it now
254914f1b3e8SDimitry Andric                                                              // and use this as
255014f1b3e8SDimitry Andric                                                              // a bitfield
255114f1b3e8SDimitry Andric               pointee_compiler_type_info.Test(eTypeIsScalar)) {
2552b76161e4SDimitry Andric             Status error;
2553f034231aSEd Maste             root = root->Dereference(error);
255414f1b3e8SDimitry Andric             if (error.Fail() || !root) {
255514f1b3e8SDimitry Andric               *reason_to_stop =
255614f1b3e8SDimitry Andric                   ValueObject::eExpressionPathScanEndReasonDereferencingFailed;
2557f034231aSEd Maste               *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
255814f1b3e8SDimitry Andric               return nullptr;
255914f1b3e8SDimitry Andric             } else {
2560f034231aSEd Maste               *what_next = eExpressionPathAftermathNothing;
2561f034231aSEd Maste               continue;
2562f034231aSEd Maste             }
256314f1b3e8SDimitry Andric           } else {
256414f1b3e8SDimitry Andric             if (root->GetCompilerType().GetMinimumLanguage() ==
256514f1b3e8SDimitry Andric                     eLanguageTypeObjC &&
256614f1b3e8SDimitry Andric                 pointee_compiler_type_info.AllClear(eTypeIsPointer) &&
256714f1b3e8SDimitry Andric                 root->HasSyntheticValue() &&
256814f1b3e8SDimitry Andric                 (options.m_synthetic_children_traversal ==
256914f1b3e8SDimitry Andric                      GetValueForExpressionPathOptions::
257014f1b3e8SDimitry Andric                          SyntheticChildrenTraversal::ToSynthetic ||
257114f1b3e8SDimitry Andric                  options.m_synthetic_children_traversal ==
257214f1b3e8SDimitry Andric                      GetValueForExpressionPathOptions::
257314f1b3e8SDimitry Andric                          SyntheticChildrenTraversal::Both)) {
25747fa27ce4SDimitry Andric               root = root->GetSyntheticValue()->GetChildAtIndex(index);
257514f1b3e8SDimitry Andric             } else
25765e95aa85SEd Maste               root = root->GetSyntheticArrayMember(index, true);
257714f1b3e8SDimitry Andric             if (!root) {
257814f1b3e8SDimitry Andric               *reason_to_stop =
257914f1b3e8SDimitry Andric                   ValueObject::eExpressionPathScanEndReasonNoSuchChild;
2580f034231aSEd Maste               *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
258114f1b3e8SDimitry Andric               return nullptr;
258214f1b3e8SDimitry Andric             } else {
258314f1b3e8SDimitry Andric               remainder =
258414f1b3e8SDimitry Andric                   temp_expression.substr(close_bracket_position + 1); // skip ]
2585f034231aSEd Maste               *final_result = ValueObject::eExpressionPathEndResultTypePlain;
2586f034231aSEd Maste               continue;
2587f034231aSEd Maste             }
2588f034231aSEd Maste           }
258914f1b3e8SDimitry Andric         } else if (root_compiler_type_info.Test(eTypeIsScalar)) {
2590f034231aSEd Maste           root = root->GetSyntheticBitFieldChild(index, index, true);
259114f1b3e8SDimitry Andric           if (!root) {
259214f1b3e8SDimitry Andric             *reason_to_stop =
259314f1b3e8SDimitry Andric                 ValueObject::eExpressionPathScanEndReasonNoSuchChild;
2594f034231aSEd Maste             *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
259514f1b3e8SDimitry Andric             return nullptr;
259614f1b3e8SDimitry Andric           } else // we do not know how to expand members of bitfields, so we
259714f1b3e8SDimitry Andric                  // just return and let the caller do any further processing
2598f034231aSEd Maste           {
259914f1b3e8SDimitry Andric             *reason_to_stop = ValueObject::
260014f1b3e8SDimitry Andric                 eExpressionPathScanEndReasonBitfieldRangeOperatorMet;
2601f034231aSEd Maste             *final_result = ValueObject::eExpressionPathEndResultTypeBitfield;
2602f034231aSEd Maste             return root;
2603f034231aSEd Maste           }
260414f1b3e8SDimitry Andric         } else if (root_compiler_type_info.Test(eTypeIsVector)) {
26057fa27ce4SDimitry Andric           root = root->GetChildAtIndex(index);
260614f1b3e8SDimitry Andric           if (!root) {
260714f1b3e8SDimitry Andric             *reason_to_stop =
260814f1b3e8SDimitry Andric                 ValueObject::eExpressionPathScanEndReasonNoSuchChild;
2609f034231aSEd Maste             *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
2610f034231aSEd Maste             return ValueObjectSP();
261114f1b3e8SDimitry Andric           } else {
261214f1b3e8SDimitry Andric             remainder =
261314f1b3e8SDimitry Andric                 temp_expression.substr(close_bracket_position + 1); // skip ]
2614f034231aSEd Maste             *final_result = ValueObject::eExpressionPathEndResultTypePlain;
2615f034231aSEd Maste             continue;
2616f034231aSEd Maste           }
261714f1b3e8SDimitry Andric         } else if (options.m_synthetic_children_traversal ==
261814f1b3e8SDimitry Andric                        GetValueForExpressionPathOptions::
261914f1b3e8SDimitry Andric                            SyntheticChildrenTraversal::ToSynthetic ||
262014f1b3e8SDimitry Andric                    options.m_synthetic_children_traversal ==
262114f1b3e8SDimitry Andric                        GetValueForExpressionPathOptions::
262214f1b3e8SDimitry Andric                            SyntheticChildrenTraversal::Both) {
2623f034231aSEd Maste           if (root->HasSyntheticValue())
2624f034231aSEd Maste             root = root->GetSyntheticValue();
262514f1b3e8SDimitry Andric           else if (!root->IsSynthetic()) {
262614f1b3e8SDimitry Andric             *reason_to_stop =
262714f1b3e8SDimitry Andric                 ValueObject::eExpressionPathScanEndReasonSyntheticValueMissing;
2628f034231aSEd Maste             *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
262914f1b3e8SDimitry Andric             return nullptr;
2630f034231aSEd Maste           }
2631f73363f1SDimitry Andric           // if we are here, then root itself is a synthetic VO.. should be
2632f73363f1SDimitry Andric           // good to go
2633f034231aSEd Maste 
263414f1b3e8SDimitry Andric           if (!root) {
263514f1b3e8SDimitry Andric             *reason_to_stop =
263614f1b3e8SDimitry Andric                 ValueObject::eExpressionPathScanEndReasonSyntheticValueMissing;
2637f034231aSEd Maste             *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
263814f1b3e8SDimitry Andric             return nullptr;
2639f034231aSEd Maste           }
26407fa27ce4SDimitry Andric           root = root->GetChildAtIndex(index);
264114f1b3e8SDimitry Andric           if (!root) {
264214f1b3e8SDimitry Andric             *reason_to_stop =
264314f1b3e8SDimitry Andric                 ValueObject::eExpressionPathScanEndReasonNoSuchChild;
2644f034231aSEd Maste             *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
264514f1b3e8SDimitry Andric             return nullptr;
264614f1b3e8SDimitry Andric           } else {
264714f1b3e8SDimitry Andric             remainder =
264814f1b3e8SDimitry Andric                 temp_expression.substr(close_bracket_position + 1); // skip ]
2649f034231aSEd Maste             *final_result = ValueObject::eExpressionPathEndResultTypePlain;
2650f034231aSEd Maste             continue;
2651f034231aSEd Maste           }
265214f1b3e8SDimitry Andric         } else {
265314f1b3e8SDimitry Andric           *reason_to_stop =
265414f1b3e8SDimitry Andric               ValueObject::eExpressionPathScanEndReasonNoSuchChild;
2655f034231aSEd Maste           *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
265614f1b3e8SDimitry Andric           return nullptr;
2657f034231aSEd Maste         }
265814f1b3e8SDimitry Andric       } else {
265914f1b3e8SDimitry Andric         // we have a low and a high index
266014f1b3e8SDimitry Andric         llvm::StringRef sleft, sright;
266114f1b3e8SDimitry Andric         unsigned long low_index, high_index;
266214f1b3e8SDimitry Andric         std::tie(sleft, sright) = bracket_expr.split('-');
266314f1b3e8SDimitry Andric         if (sleft.getAsInteger(0, low_index) ||
266414f1b3e8SDimitry Andric             sright.getAsInteger(0, high_index)) {
266514f1b3e8SDimitry Andric           *reason_to_stop =
266614f1b3e8SDimitry Andric               ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol;
2667f034231aSEd Maste           *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
266814f1b3e8SDimitry Andric           return nullptr;
2669f034231aSEd Maste         }
267014f1b3e8SDimitry Andric 
267114f1b3e8SDimitry Andric         if (low_index > high_index) // swap indices if required
267214f1b3e8SDimitry Andric           std::swap(low_index, high_index);
267314f1b3e8SDimitry Andric 
267414f1b3e8SDimitry Andric         if (root_compiler_type_info.Test(
267514f1b3e8SDimitry Andric                 eTypeIsScalar)) // expansion only works for scalars
2676f034231aSEd Maste         {
267714f1b3e8SDimitry Andric           root = root->GetSyntheticBitFieldChild(low_index, high_index, true);
267814f1b3e8SDimitry Andric           if (!root) {
267914f1b3e8SDimitry Andric             *reason_to_stop =
268014f1b3e8SDimitry Andric                 ValueObject::eExpressionPathScanEndReasonNoSuchChild;
2681f034231aSEd Maste             *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
268214f1b3e8SDimitry Andric             return nullptr;
268314f1b3e8SDimitry Andric           } else {
268414f1b3e8SDimitry Andric             *reason_to_stop = ValueObject::
268514f1b3e8SDimitry Andric                 eExpressionPathScanEndReasonBitfieldRangeOperatorMet;
2686f034231aSEd Maste             *final_result = ValueObject::eExpressionPathEndResultTypeBitfield;
2687f034231aSEd Maste             return root;
2688f034231aSEd Maste           }
268914f1b3e8SDimitry Andric         } else if (root_compiler_type_info.Test(
269014f1b3e8SDimitry Andric                        eTypeIsPointer) && // if this is a ptr-to-scalar, I am
269114f1b3e8SDimitry Andric                                           // accessing it by index and I would
269214f1b3e8SDimitry Andric                                           // have deref'ed anyway, then do it
269314f1b3e8SDimitry Andric                                           // now and use this as a bitfield
269414f1b3e8SDimitry Andric                    *what_next ==
269514f1b3e8SDimitry Andric                        ValueObject::eExpressionPathAftermathDereference &&
269614f1b3e8SDimitry Andric                    pointee_compiler_type_info.Test(eTypeIsScalar)) {
2697b76161e4SDimitry Andric           Status error;
2698f034231aSEd Maste           root = root->Dereference(error);
269914f1b3e8SDimitry Andric           if (error.Fail() || !root) {
270014f1b3e8SDimitry Andric             *reason_to_stop =
270114f1b3e8SDimitry Andric                 ValueObject::eExpressionPathScanEndReasonDereferencingFailed;
2702f034231aSEd Maste             *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
270314f1b3e8SDimitry Andric             return nullptr;
270414f1b3e8SDimitry Andric           } else {
2705f034231aSEd Maste             *what_next = ValueObject::eExpressionPathAftermathNothing;
2706f034231aSEd Maste             continue;
2707f034231aSEd Maste           }
270814f1b3e8SDimitry Andric         } else {
270914f1b3e8SDimitry Andric           *reason_to_stop =
271014f1b3e8SDimitry Andric               ValueObject::eExpressionPathScanEndReasonArrayRangeOperatorMet;
2711f034231aSEd Maste           *final_result = ValueObject::eExpressionPathEndResultTypeBoundedRange;
2712f034231aSEd Maste           return root;
2713f034231aSEd Maste         }
2714f034231aSEd Maste       }
2715f034231aSEd Maste       break;
2716f034231aSEd Maste     }
2717f034231aSEd Maste     default: // some non-separator is in the way
2718f034231aSEd Maste     {
271914f1b3e8SDimitry Andric       *reason_to_stop =
272014f1b3e8SDimitry Andric           ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol;
2721f034231aSEd Maste       *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
272214f1b3e8SDimitry Andric       return nullptr;
2723f034231aSEd Maste     }
2724f034231aSEd Maste     }
2725f034231aSEd Maste   }
2726f034231aSEd Maste }
2727f034231aSEd Maste 
Dump(Stream & s)2728ac9a064cSDimitry Andric llvm::Error ValueObject::Dump(Stream &s) {
2729ac9a064cSDimitry Andric   return Dump(s, DumpValueObjectOptions(*this));
2730ac9a064cSDimitry Andric }
2731f034231aSEd Maste 
Dump(Stream & s,const DumpValueObjectOptions & options)2732ac9a064cSDimitry Andric llvm::Error ValueObject::Dump(Stream &s,
2733ac9a064cSDimitry Andric                               const DumpValueObjectOptions &options) {
2734ac9a064cSDimitry Andric   ValueObjectPrinter printer(*this, &s, options);
2735ac9a064cSDimitry Andric   return printer.PrintValueObject();
2736f034231aSEd Maste }
2737f034231aSEd Maste 
CreateConstantValue(ConstString name)27385f29bb8aSDimitry Andric ValueObjectSP ValueObject::CreateConstantValue(ConstString name) {
2739f034231aSEd Maste   ValueObjectSP valobj_sp;
2740f034231aSEd Maste 
274114f1b3e8SDimitry Andric   if (UpdateValueIfNeeded(false) && m_error.Success()) {
2742f034231aSEd Maste     ExecutionContext exe_ctx(GetExecutionContextRef());
2743f034231aSEd Maste 
2744f034231aSEd Maste     DataExtractor data;
2745f034231aSEd Maste     data.SetByteOrder(m_data.GetByteOrder());
2746f034231aSEd Maste     data.SetAddressByteSize(m_data.GetAddressByteSize());
2747f034231aSEd Maste 
274814f1b3e8SDimitry Andric     if (IsBitfield()) {
2749f034231aSEd Maste       Value v(Scalar(GetValueAsUnsigned(UINT64_MAX)));
2750ead24645SDimitry Andric       m_error = v.GetValueAsData(&exe_ctx, data, GetModule().get());
275114f1b3e8SDimitry Andric     } else
2752ead24645SDimitry Andric       m_error = m_value.GetValueAsData(&exe_ctx, data, GetModule().get());
2753f034231aSEd Maste 
275414f1b3e8SDimitry Andric     valobj_sp = ValueObjectConstResult::Create(
275514f1b3e8SDimitry Andric         exe_ctx.GetBestExecutionContextScope(), GetCompilerType(), name, data,
2756f034231aSEd Maste         GetAddressOf());
2757f034231aSEd Maste   }
2758f034231aSEd Maste 
275914f1b3e8SDimitry Andric   if (!valobj_sp) {
2760866dcdacSEd Maste     ExecutionContext exe_ctx(GetExecutionContextRef());
276114f1b3e8SDimitry Andric     valobj_sp = ValueObjectConstResult::Create(
276214f1b3e8SDimitry Andric         exe_ctx.GetBestExecutionContextScope(), m_error);
2763f034231aSEd Maste   }
2764f034231aSEd Maste   return valobj_sp;
2765f034231aSEd Maste }
2766f034231aSEd Maste 
GetQualifiedRepresentationIfAvailable(lldb::DynamicValueType dynValue,bool synthValue)276714f1b3e8SDimitry Andric ValueObjectSP ValueObject::GetQualifiedRepresentationIfAvailable(
276814f1b3e8SDimitry Andric     lldb::DynamicValueType dynValue, bool synthValue) {
2769b1c73532SDimitry Andric   ValueObjectSP result_sp;
277014f1b3e8SDimitry Andric   switch (dynValue) {
2771205afe67SEd Maste   case lldb::eDynamicCanRunTarget:
277214f1b3e8SDimitry Andric   case lldb::eDynamicDontRunTarget: {
2773b1c73532SDimitry Andric     if (!IsDynamic())
2774b1c73532SDimitry Andric       result_sp = GetDynamicValue(dynValue);
277514f1b3e8SDimitry Andric   } break;
277614f1b3e8SDimitry Andric   case lldb::eNoDynamicValues: {
2777b1c73532SDimitry Andric     if (IsDynamic())
2778b1c73532SDimitry Andric       result_sp = GetStaticValue();
277914f1b3e8SDimitry Andric   } break;
2780205afe67SEd Maste   }
2781b1c73532SDimitry Andric   if (!result_sp)
2782b1c73532SDimitry Andric     result_sp = GetSP();
2783b1c73532SDimitry Andric   assert(result_sp);
2784205afe67SEd Maste 
2785b1c73532SDimitry Andric   bool is_synthetic = result_sp->IsSynthetic();
2786b1c73532SDimitry Andric   if (synthValue && !is_synthetic) {
2787b1c73532SDimitry Andric     if (auto synth_sp = result_sp->GetSyntheticValue())
2788b1c73532SDimitry Andric       return synth_sp;
2789205afe67SEd Maste   }
2790b1c73532SDimitry Andric   if (!synthValue && is_synthetic) {
2791b1c73532SDimitry Andric     if (auto non_synth_sp = result_sp->GetNonSyntheticValue())
2792b1c73532SDimitry Andric       return non_synth_sp;
2793205afe67SEd Maste   }
2794205afe67SEd Maste 
2795205afe67SEd Maste   return result_sp;
2796205afe67SEd Maste }
2797205afe67SEd Maste 
Dereference(Status & error)2798b76161e4SDimitry Andric ValueObjectSP ValueObject::Dereference(Status &error) {
2799f034231aSEd Maste   if (m_deref_valobj)
2800f034231aSEd Maste     return m_deref_valobj->GetSP();
2801f034231aSEd Maste 
2802e81d9d49SDimitry Andric   const bool is_pointer_or_reference_type = IsPointerOrReferenceType();
280314f1b3e8SDimitry Andric   if (is_pointer_or_reference_type) {
2804f034231aSEd Maste     bool omit_empty_base_classes = true;
2805f034231aSEd Maste     bool ignore_array_bounds = false;
2806f034231aSEd Maste 
2807f034231aSEd Maste     std::string child_name_str;
2808f034231aSEd Maste     uint32_t child_byte_size = 0;
2809f034231aSEd Maste     int32_t child_byte_offset = 0;
2810f034231aSEd Maste     uint32_t child_bitfield_bit_size = 0;
2811f034231aSEd Maste     uint32_t child_bitfield_bit_offset = 0;
2812f034231aSEd Maste     bool child_is_base_class = false;
2813f034231aSEd Maste     bool child_is_deref_of_parent = false;
2814f034231aSEd Maste     const bool transparent_pointers = false;
2815e81d9d49SDimitry Andric     CompilerType compiler_type = GetCompilerType();
2816cfca06d7SDimitry Andric     uint64_t language_flags = 0;
2817f034231aSEd Maste 
2818f034231aSEd Maste     ExecutionContext exe_ctx(GetExecutionContextRef());
2819f034231aSEd Maste 
2820ac9a064cSDimitry Andric     CompilerType child_compiler_type;
2821ac9a064cSDimitry Andric     auto child_compiler_type_or_err = compiler_type.GetChildCompilerTypeAtIndex(
282214f1b3e8SDimitry Andric         &exe_ctx, 0, transparent_pointers, omit_empty_base_classes,
282314f1b3e8SDimitry Andric         ignore_array_bounds, child_name_str, child_byte_size, child_byte_offset,
282414f1b3e8SDimitry Andric         child_bitfield_bit_size, child_bitfield_bit_offset, child_is_base_class,
282514f1b3e8SDimitry Andric         child_is_deref_of_parent, this, language_flags);
2826ac9a064cSDimitry Andric     if (!child_compiler_type_or_err)
2827ac9a064cSDimitry Andric       LLDB_LOG_ERROR(GetLog(LLDBLog::Types),
2828ac9a064cSDimitry Andric                      child_compiler_type_or_err.takeError(),
2829ac9a064cSDimitry Andric                      "could not find child: {0}");
2830ac9a064cSDimitry Andric     else
2831ac9a064cSDimitry Andric       child_compiler_type = *child_compiler_type_or_err;
2832ac9a064cSDimitry Andric 
283314f1b3e8SDimitry Andric     if (child_compiler_type && child_byte_size) {
2834f034231aSEd Maste       ConstString child_name;
2835f034231aSEd Maste       if (!child_name_str.empty())
2836f034231aSEd Maste         child_name.SetCString(child_name_str.c_str());
2837f034231aSEd Maste 
283814f1b3e8SDimitry Andric       m_deref_valobj = new ValueObjectChild(
283914f1b3e8SDimitry Andric           *this, child_compiler_type, child_name, child_byte_size,
284014f1b3e8SDimitry Andric           child_byte_offset, child_bitfield_bit_size, child_bitfield_bit_offset,
284114f1b3e8SDimitry Andric           child_is_base_class, child_is_deref_of_parent, eAddressTypeInvalid,
2842e81d9d49SDimitry Andric           language_flags);
2843f034231aSEd Maste     }
2844cfca06d7SDimitry Andric 
2845cfca06d7SDimitry Andric     // In case of incomplete child compiler type, use the pointee type and try
2846cfca06d7SDimitry Andric     // to recreate a new ValueObjectChild using it.
2847cfca06d7SDimitry Andric     if (!m_deref_valobj) {
2848e3b55780SDimitry Andric       // FIXME(#59012): C++ stdlib formatters break with incomplete types (e.g.
2849e3b55780SDimitry Andric       // `std::vector<int> &`). Remove ObjC restriction once that's resolved.
2850e3b55780SDimitry Andric       if (Language::LanguageIsObjC(GetPreferredDisplayLanguage()) &&
2851e3b55780SDimitry Andric           HasSyntheticValue()) {
2852cfca06d7SDimitry Andric         child_compiler_type = compiler_type.GetPointeeType();
2853cfca06d7SDimitry Andric 
2854cfca06d7SDimitry Andric         if (child_compiler_type) {
2855cfca06d7SDimitry Andric           ConstString child_name;
2856cfca06d7SDimitry Andric           if (!child_name_str.empty())
2857cfca06d7SDimitry Andric             child_name.SetCString(child_name_str.c_str());
2858cfca06d7SDimitry Andric 
2859cfca06d7SDimitry Andric           m_deref_valobj = new ValueObjectChild(
2860cfca06d7SDimitry Andric               *this, child_compiler_type, child_name, child_byte_size,
2861cfca06d7SDimitry Andric               child_byte_offset, child_bitfield_bit_size,
2862cfca06d7SDimitry Andric               child_bitfield_bit_offset, child_is_base_class,
2863cfca06d7SDimitry Andric               child_is_deref_of_parent, eAddressTypeInvalid, language_flags);
2864cfca06d7SDimitry Andric         }
2865cfca06d7SDimitry Andric       }
2866cfca06d7SDimitry Andric     }
2867cfca06d7SDimitry Andric 
286874a628f7SDimitry Andric   } else if (HasSyntheticValue()) {
286974a628f7SDimitry Andric     m_deref_valobj =
28707fa27ce4SDimitry Andric         GetSyntheticValue()->GetChildMemberWithName("$$dereference$$").get();
2871cfca06d7SDimitry Andric   } else if (IsSynthetic()) {
28727fa27ce4SDimitry Andric     m_deref_valobj = GetChildMemberWithName("$$dereference$$").get();
2873f034231aSEd Maste   }
2874f034231aSEd Maste 
287514f1b3e8SDimitry Andric   if (m_deref_valobj) {
2876f034231aSEd Maste     error.Clear();
2877f034231aSEd Maste     return m_deref_valobj->GetSP();
287814f1b3e8SDimitry Andric   } else {
2879f034231aSEd Maste     StreamString strm;
2880cfca06d7SDimitry Andric     GetExpressionPath(strm);
2881f034231aSEd Maste 
2882e81d9d49SDimitry Andric     if (is_pointer_or_reference_type)
288314f1b3e8SDimitry Andric       error.SetErrorStringWithFormat("dereference failed: (%s) %s",
288414f1b3e8SDimitry Andric                                      GetTypeName().AsCString("<invalid type>"),
288514f1b3e8SDimitry Andric                                      strm.GetData());
2886f034231aSEd Maste     else
288714f1b3e8SDimitry Andric       error.SetErrorStringWithFormat("not a pointer or reference type: (%s) %s",
288814f1b3e8SDimitry Andric                                      GetTypeName().AsCString("<invalid type>"),
288914f1b3e8SDimitry Andric                                      strm.GetData());
2890f034231aSEd Maste     return ValueObjectSP();
2891f034231aSEd Maste   }
2892f034231aSEd Maste }
2893f034231aSEd Maste 
AddressOf(Status & error)2894b76161e4SDimitry Andric ValueObjectSP ValueObject::AddressOf(Status &error) {
2895f034231aSEd Maste   if (m_addr_of_valobj_sp)
2896f034231aSEd Maste     return m_addr_of_valobj_sp;
2897f034231aSEd Maste 
2898f034231aSEd Maste   AddressType address_type = eAddressTypeInvalid;
2899f034231aSEd Maste   const bool scalar_is_load_address = false;
2900f034231aSEd Maste   addr_t addr = GetAddressOf(scalar_is_load_address, &address_type);
2901f034231aSEd Maste   error.Clear();
2902ac9a064cSDimitry Andric   if (addr != LLDB_INVALID_ADDRESS && address_type != eAddressTypeHost) {
2903ac9a064cSDimitry Andric     switch (address_type) {
2904ac9a064cSDimitry Andric     case eAddressTypeInvalid: {
2905f034231aSEd Maste       StreamString expr_path_strm;
2906cfca06d7SDimitry Andric       GetExpressionPath(expr_path_strm);
2907ac9a064cSDimitry Andric       error.SetErrorStringWithFormat("'%s' is not in memory",
2908ac9a064cSDimitry Andric                                      expr_path_strm.GetData());
2909ac9a064cSDimitry Andric     } break;
2910f034231aSEd Maste 
2911f034231aSEd Maste     case eAddressTypeFile:
291214f1b3e8SDimitry Andric     case eAddressTypeLoad: {
2913e81d9d49SDimitry Andric       CompilerType compiler_type = GetCompilerType();
2914ac9a064cSDimitry Andric       if (compiler_type) {
29154df029ccSDimitry Andric         std::string name(1, '&');
29164df029ccSDimitry Andric         name.append(m_name.AsCString(""));
2917ac9a064cSDimitry Andric         ExecutionContext exe_ctx(GetExecutionContextRef());
29184df029ccSDimitry Andric         m_addr_of_valobj_sp = ValueObjectConstResult::Create(
2919ac9a064cSDimitry Andric             exe_ctx.GetBestExecutionContextScope(),
2920ac9a064cSDimitry Andric             compiler_type.GetPointerType(), ConstString(name.c_str()), addr,
29214df029ccSDimitry Andric             eAddressTypeInvalid, m_data.GetAddressByteSize());
2922ac9a064cSDimitry Andric       }
2923ac9a064cSDimitry Andric     } break;
2924ac9a064cSDimitry Andric     default:
2925ac9a064cSDimitry Andric       break;
2926ac9a064cSDimitry Andric     }
2927ac9a064cSDimitry Andric   } else {
2928ac9a064cSDimitry Andric     StreamString expr_path_strm;
2929ac9a064cSDimitry Andric     GetExpressionPath(expr_path_strm);
2930ac9a064cSDimitry Andric     error.SetErrorStringWithFormat("'%s' doesn't have a valid address",
2931ac9a064cSDimitry Andric                                    expr_path_strm.GetData());
2932ac9a064cSDimitry Andric   }
2933ac9a064cSDimitry Andric 
2934f034231aSEd Maste   return m_addr_of_valobj_sp;
2935f034231aSEd Maste }
2936f034231aSEd Maste 
DoCast(const CompilerType & compiler_type)29377fa27ce4SDimitry Andric ValueObjectSP ValueObject::DoCast(const CompilerType &compiler_type) {
2938e81d9d49SDimitry Andric     return ValueObjectCast::Create(*this, GetName(), compiler_type);
2939f034231aSEd Maste }
2940f034231aSEd Maste 
Cast(const CompilerType & compiler_type)29417fa27ce4SDimitry Andric ValueObjectSP ValueObject::Cast(const CompilerType &compiler_type) {
29427fa27ce4SDimitry Andric   // Only allow casts if the original type is equal or larger than the cast
2943ac9a064cSDimitry Andric   // type, unless we know this is a load address.  Getting the size wrong for
2944ac9a064cSDimitry Andric   // a host side storage could leak lldb memory, so we absolutely want to
2945ac9a064cSDimitry Andric   // prevent that.  We may not always get the right value, for instance if we
2946ac9a064cSDimitry Andric   // have an expression result value that's copied into a storage location in
2947ac9a064cSDimitry Andric   // the target may not have copied enough memory.  I'm not trying to fix that
2948ac9a064cSDimitry Andric   // here, I'm just making Cast from a smaller to a larger possible in all the
2949ac9a064cSDimitry Andric   // cases where that doesn't risk making a Value out of random lldb memory.
2950ac9a064cSDimitry Andric   // You have to check the ValueObject's Value for the address types, since
2951ac9a064cSDimitry Andric   // ValueObjects that use live addresses will tell you they fetch data from the
2952ac9a064cSDimitry Andric   // live address, but once they are made, they actually don't.
2953ac9a064cSDimitry Andric   // FIXME: Can we make ValueObject's with a live address fetch "more data" from
2954ac9a064cSDimitry Andric   // the live address if it is still valid?
2955ac9a064cSDimitry Andric 
29567fa27ce4SDimitry Andric   Status error;
29577fa27ce4SDimitry Andric   CompilerType my_type = GetCompilerType();
29587fa27ce4SDimitry Andric 
29597fa27ce4SDimitry Andric   ExecutionContextScope *exe_scope
29607fa27ce4SDimitry Andric       = ExecutionContext(GetExecutionContextRef())
29617fa27ce4SDimitry Andric           .GetBestExecutionContextScope();
29627fa27ce4SDimitry Andric   if (compiler_type.GetByteSize(exe_scope)
2963ac9a064cSDimitry Andric       <= GetCompilerType().GetByteSize(exe_scope)
2964ac9a064cSDimitry Andric       || m_value.GetValueType() == Value::ValueType::LoadAddress)
29657fa27ce4SDimitry Andric         return DoCast(compiler_type);
2966ac9a064cSDimitry Andric 
29677fa27ce4SDimitry Andric   error.SetErrorString("Can only cast to a type that is equal to or smaller "
29687fa27ce4SDimitry Andric                        "than the orignal type.");
29697fa27ce4SDimitry Andric 
29707fa27ce4SDimitry Andric   return ValueObjectConstResult::Create(
29717fa27ce4SDimitry Andric       ExecutionContext(GetExecutionContextRef()).GetBestExecutionContextScope(),
29727fa27ce4SDimitry Andric                        error);
29737fa27ce4SDimitry Andric }
29747fa27ce4SDimitry Andric 
Clone(ConstString new_name)29755f29bb8aSDimitry Andric lldb::ValueObjectSP ValueObject::Clone(ConstString new_name) {
297674a628f7SDimitry Andric   return ValueObjectCast::Create(*this, new_name, GetCompilerType());
297774a628f7SDimitry Andric }
297874a628f7SDimitry Andric 
CastPointerType(const char * name,CompilerType & compiler_type)297914f1b3e8SDimitry Andric ValueObjectSP ValueObject::CastPointerType(const char *name,
298014f1b3e8SDimitry Andric                                            CompilerType &compiler_type) {
2981f034231aSEd Maste   ValueObjectSP valobj_sp;
2982f034231aSEd Maste   AddressType address_type;
2983f034231aSEd Maste   addr_t ptr_value = GetPointerValue(&address_type);
2984f034231aSEd Maste 
298514f1b3e8SDimitry Andric   if (ptr_value != LLDB_INVALID_ADDRESS) {
2986f034231aSEd Maste     Address ptr_addr(ptr_value);
2987f034231aSEd Maste     ExecutionContext exe_ctx(GetExecutionContextRef());
298814f1b3e8SDimitry Andric     valobj_sp = ValueObjectMemory::Create(
298914f1b3e8SDimitry Andric         exe_ctx.GetBestExecutionContextScope(), name, ptr_addr, compiler_type);
2990f034231aSEd Maste   }
2991f034231aSEd Maste   return valobj_sp;
2992f034231aSEd Maste }
2993f034231aSEd Maste 
CastPointerType(const char * name,TypeSP & type_sp)299414f1b3e8SDimitry Andric ValueObjectSP ValueObject::CastPointerType(const char *name, TypeSP &type_sp) {
2995f034231aSEd Maste   ValueObjectSP valobj_sp;
2996f034231aSEd Maste   AddressType address_type;
2997f034231aSEd Maste   addr_t ptr_value = GetPointerValue(&address_type);
2998f034231aSEd Maste 
299914f1b3e8SDimitry Andric   if (ptr_value != LLDB_INVALID_ADDRESS) {
3000f034231aSEd Maste     Address ptr_addr(ptr_value);
3001f034231aSEd Maste     ExecutionContext exe_ctx(GetExecutionContextRef());
300214f1b3e8SDimitry Andric     valobj_sp = ValueObjectMemory::Create(
300314f1b3e8SDimitry Andric         exe_ctx.GetBestExecutionContextScope(), name, ptr_addr, type_sp);
3004f034231aSEd Maste   }
3005f034231aSEd Maste   return valobj_sp;
3006f034231aSEd Maste }
3007f034231aSEd Maste 
GetLoadAddress()3008ac9a064cSDimitry Andric lldb::addr_t ValueObject::GetLoadAddress() {
3009ac9a064cSDimitry Andric   lldb::addr_t addr_value = LLDB_INVALID_ADDRESS;
3010ac9a064cSDimitry Andric   if (auto target_sp = GetTargetSP()) {
3011ac9a064cSDimitry Andric     const bool scalar_is_load_address = true;
3012ac9a064cSDimitry Andric     AddressType addr_type;
3013ac9a064cSDimitry Andric     addr_value = GetAddressOf(scalar_is_load_address, &addr_type);
3014ac9a064cSDimitry Andric     if (addr_type == eAddressTypeFile) {
3015ac9a064cSDimitry Andric       lldb::ModuleSP module_sp(GetModule());
3016ac9a064cSDimitry Andric       if (!module_sp)
3017ac9a064cSDimitry Andric         addr_value = LLDB_INVALID_ADDRESS;
3018ac9a064cSDimitry Andric       else {
3019ac9a064cSDimitry Andric         Address tmp_addr;
3020ac9a064cSDimitry Andric         module_sp->ResolveFileAddress(addr_value, tmp_addr);
3021ac9a064cSDimitry Andric         addr_value = tmp_addr.GetLoadAddress(target_sp.get());
3022ac9a064cSDimitry Andric       }
3023ac9a064cSDimitry Andric     } else if (addr_type == eAddressTypeHost ||
3024ac9a064cSDimitry Andric                addr_type == eAddressTypeInvalid)
3025ac9a064cSDimitry Andric       addr_value = LLDB_INVALID_ADDRESS;
3026ac9a064cSDimitry Andric   }
3027ac9a064cSDimitry Andric   return addr_value;
3028ac9a064cSDimitry Andric }
3029ac9a064cSDimitry Andric 
CastDerivedToBaseType(CompilerType type,const llvm::ArrayRef<uint32_t> & base_type_indices)3030ac9a064cSDimitry Andric llvm::Expected<lldb::ValueObjectSP> ValueObject::CastDerivedToBaseType(
3031ac9a064cSDimitry Andric     CompilerType type, const llvm::ArrayRef<uint32_t> &base_type_indices) {
3032ac9a064cSDimitry Andric   // Make sure the starting type and the target type are both valid for this
3033ac9a064cSDimitry Andric   // type of cast; otherwise return the shared pointer to the original
3034ac9a064cSDimitry Andric   // (unchanged) ValueObject.
3035ac9a064cSDimitry Andric   if (!type.IsPointerType() && !type.IsReferenceType())
3036ac9a064cSDimitry Andric     return llvm::make_error<llvm::StringError>(
3037ac9a064cSDimitry Andric         "Invalid target type: should be a pointer or a reference",
3038ac9a064cSDimitry Andric         llvm::inconvertibleErrorCode());
3039ac9a064cSDimitry Andric 
3040ac9a064cSDimitry Andric   CompilerType start_type = GetCompilerType();
3041ac9a064cSDimitry Andric   if (start_type.IsReferenceType())
3042ac9a064cSDimitry Andric     start_type = start_type.GetNonReferenceType();
3043ac9a064cSDimitry Andric 
3044ac9a064cSDimitry Andric   auto target_record_type =
3045ac9a064cSDimitry Andric       type.IsPointerType() ? type.GetPointeeType() : type.GetNonReferenceType();
3046ac9a064cSDimitry Andric   auto start_record_type =
3047ac9a064cSDimitry Andric       start_type.IsPointerType() ? start_type.GetPointeeType() : start_type;
3048ac9a064cSDimitry Andric 
3049ac9a064cSDimitry Andric   if (!target_record_type.IsRecordType() || !start_record_type.IsRecordType())
3050ac9a064cSDimitry Andric     return llvm::make_error<llvm::StringError>(
3051ac9a064cSDimitry Andric         "Underlying start & target types should be record types",
3052ac9a064cSDimitry Andric         llvm::inconvertibleErrorCode());
3053ac9a064cSDimitry Andric 
3054ac9a064cSDimitry Andric   if (target_record_type.CompareTypes(start_record_type))
3055ac9a064cSDimitry Andric     return llvm::make_error<llvm::StringError>(
3056ac9a064cSDimitry Andric         "Underlying start & target types should be different",
3057ac9a064cSDimitry Andric         llvm::inconvertibleErrorCode());
3058ac9a064cSDimitry Andric 
3059ac9a064cSDimitry Andric   if (base_type_indices.empty())
3060ac9a064cSDimitry Andric     return llvm::make_error<llvm::StringError>(
3061ac9a064cSDimitry Andric         "Children sequence must be non-empty", llvm::inconvertibleErrorCode());
3062ac9a064cSDimitry Andric 
3063ac9a064cSDimitry Andric   // Both the starting & target types are valid for the cast, and the list of
3064ac9a064cSDimitry Andric   // base class indices is non-empty, so we can proceed with the cast.
3065ac9a064cSDimitry Andric 
3066ac9a064cSDimitry Andric   lldb::TargetSP target = GetTargetSP();
3067ac9a064cSDimitry Andric   // The `value` can be a pointer, but GetChildAtIndex works for pointers too.
3068ac9a064cSDimitry Andric   lldb::ValueObjectSP inner_value = GetSP();
3069ac9a064cSDimitry Andric 
3070ac9a064cSDimitry Andric   for (const uint32_t i : base_type_indices)
3071ac9a064cSDimitry Andric     // Create synthetic value if needed.
3072ac9a064cSDimitry Andric     inner_value =
3073ac9a064cSDimitry Andric         inner_value->GetChildAtIndex(i, /*can_create_synthetic*/ true);
3074ac9a064cSDimitry Andric 
3075ac9a064cSDimitry Andric   // At this point type of `inner_value` should be the dereferenced target
3076ac9a064cSDimitry Andric   // type.
3077ac9a064cSDimitry Andric   CompilerType inner_value_type = inner_value->GetCompilerType();
3078ac9a064cSDimitry Andric   if (type.IsPointerType()) {
3079ac9a064cSDimitry Andric     if (!inner_value_type.CompareTypes(type.GetPointeeType()))
3080ac9a064cSDimitry Andric       return llvm::make_error<llvm::StringError>(
3081ac9a064cSDimitry Andric           "casted value doesn't match the desired type",
3082ac9a064cSDimitry Andric           llvm::inconvertibleErrorCode());
3083ac9a064cSDimitry Andric 
3084ac9a064cSDimitry Andric     uintptr_t addr = inner_value->GetLoadAddress();
3085ac9a064cSDimitry Andric     llvm::StringRef name = "";
3086ac9a064cSDimitry Andric     ExecutionContext exe_ctx(target.get(), false);
3087ac9a064cSDimitry Andric     return ValueObject::CreateValueObjectFromAddress(name, addr, exe_ctx, type,
3088ac9a064cSDimitry Andric                                                      /* do deref */ false);
3089ac9a064cSDimitry Andric   }
3090ac9a064cSDimitry Andric 
3091ac9a064cSDimitry Andric   // At this point the target type should be a reference.
3092ac9a064cSDimitry Andric   if (!inner_value_type.CompareTypes(type.GetNonReferenceType()))
3093ac9a064cSDimitry Andric     return llvm::make_error<llvm::StringError>(
3094ac9a064cSDimitry Andric         "casted value doesn't match the desired type",
3095ac9a064cSDimitry Andric         llvm::inconvertibleErrorCode());
3096ac9a064cSDimitry Andric 
3097ac9a064cSDimitry Andric   return lldb::ValueObjectSP(inner_value->Cast(type.GetNonReferenceType()));
3098ac9a064cSDimitry Andric }
3099ac9a064cSDimitry Andric 
3100ac9a064cSDimitry Andric llvm::Expected<lldb::ValueObjectSP>
CastBaseToDerivedType(CompilerType type,uint64_t offset)3101ac9a064cSDimitry Andric ValueObject::CastBaseToDerivedType(CompilerType type, uint64_t offset) {
3102ac9a064cSDimitry Andric   // Make sure the starting type and the target type are both valid for this
3103ac9a064cSDimitry Andric   // type of cast; otherwise return the shared pointer to the original
3104ac9a064cSDimitry Andric   // (unchanged) ValueObject.
3105ac9a064cSDimitry Andric   if (!type.IsPointerType() && !type.IsReferenceType())
3106ac9a064cSDimitry Andric     return llvm::make_error<llvm::StringError>(
3107ac9a064cSDimitry Andric         "Invalid target type: should be a pointer or a reference",
3108ac9a064cSDimitry Andric         llvm::inconvertibleErrorCode());
3109ac9a064cSDimitry Andric 
3110ac9a064cSDimitry Andric   CompilerType start_type = GetCompilerType();
3111ac9a064cSDimitry Andric   if (start_type.IsReferenceType())
3112ac9a064cSDimitry Andric     start_type = start_type.GetNonReferenceType();
3113ac9a064cSDimitry Andric 
3114ac9a064cSDimitry Andric   auto target_record_type =
3115ac9a064cSDimitry Andric       type.IsPointerType() ? type.GetPointeeType() : type.GetNonReferenceType();
3116ac9a064cSDimitry Andric   auto start_record_type =
3117ac9a064cSDimitry Andric       start_type.IsPointerType() ? start_type.GetPointeeType() : start_type;
3118ac9a064cSDimitry Andric 
3119ac9a064cSDimitry Andric   if (!target_record_type.IsRecordType() || !start_record_type.IsRecordType())
3120ac9a064cSDimitry Andric     return llvm::make_error<llvm::StringError>(
3121ac9a064cSDimitry Andric         "Underlying start & target types should be record types",
3122ac9a064cSDimitry Andric         llvm::inconvertibleErrorCode());
3123ac9a064cSDimitry Andric 
3124ac9a064cSDimitry Andric   if (target_record_type.CompareTypes(start_record_type))
3125ac9a064cSDimitry Andric     return llvm::make_error<llvm::StringError>(
3126ac9a064cSDimitry Andric         "Underlying start & target types should be different",
3127ac9a064cSDimitry Andric         llvm::inconvertibleErrorCode());
3128ac9a064cSDimitry Andric 
3129ac9a064cSDimitry Andric   CompilerType virtual_base;
3130ac9a064cSDimitry Andric   if (target_record_type.IsVirtualBase(start_record_type, &virtual_base)) {
3131ac9a064cSDimitry Andric     if (!virtual_base.IsValid())
3132ac9a064cSDimitry Andric       return llvm::make_error<llvm::StringError>(
3133ac9a064cSDimitry Andric           "virtual base should be valid", llvm::inconvertibleErrorCode());
3134ac9a064cSDimitry Andric     return llvm::make_error<llvm::StringError>(
3135ac9a064cSDimitry Andric         llvm::Twine("cannot cast " + start_type.TypeDescription() + " to " +
3136ac9a064cSDimitry Andric                     type.TypeDescription() + " via virtual base " +
3137ac9a064cSDimitry Andric                     virtual_base.TypeDescription()),
3138ac9a064cSDimitry Andric         llvm::inconvertibleErrorCode());
3139ac9a064cSDimitry Andric   }
3140ac9a064cSDimitry Andric 
3141ac9a064cSDimitry Andric   // Both the starting & target types are valid for the cast,  so we can
3142ac9a064cSDimitry Andric   // proceed with the cast.
3143ac9a064cSDimitry Andric 
3144ac9a064cSDimitry Andric   lldb::TargetSP target = GetTargetSP();
3145ac9a064cSDimitry Andric   auto pointer_type =
3146ac9a064cSDimitry Andric       type.IsPointerType() ? type : type.GetNonReferenceType().GetPointerType();
3147ac9a064cSDimitry Andric 
3148ac9a064cSDimitry Andric   uintptr_t addr =
3149ac9a064cSDimitry Andric       type.IsPointerType() ? GetValueAsUnsigned(0) : GetLoadAddress();
3150ac9a064cSDimitry Andric 
3151ac9a064cSDimitry Andric   llvm::StringRef name = "";
3152ac9a064cSDimitry Andric   ExecutionContext exe_ctx(target.get(), false);
3153ac9a064cSDimitry Andric   lldb::ValueObjectSP value = ValueObject::CreateValueObjectFromAddress(
3154ac9a064cSDimitry Andric       name, addr - offset, exe_ctx, pointer_type, /* do_deref */ false);
3155ac9a064cSDimitry Andric 
3156ac9a064cSDimitry Andric   if (type.IsPointerType())
3157ac9a064cSDimitry Andric     return value;
3158ac9a064cSDimitry Andric 
3159ac9a064cSDimitry Andric   // At this point the target type is a reference. Since `value` is a pointer,
3160ac9a064cSDimitry Andric   // it has to be dereferenced.
3161ac9a064cSDimitry Andric   Status error;
3162ac9a064cSDimitry Andric   return value->Dereference(error);
3163ac9a064cSDimitry Andric }
3164ac9a064cSDimitry Andric 
CastToBasicType(CompilerType type)3165ac9a064cSDimitry Andric lldb::ValueObjectSP ValueObject::CastToBasicType(CompilerType type) {
3166ac9a064cSDimitry Andric   bool is_scalar = GetCompilerType().IsScalarType();
3167ac9a064cSDimitry Andric   bool is_enum = GetCompilerType().IsEnumerationType();
3168ac9a064cSDimitry Andric   bool is_pointer =
3169ac9a064cSDimitry Andric       GetCompilerType().IsPointerType() || GetCompilerType().IsNullPtrType();
3170ac9a064cSDimitry Andric   bool is_float = GetCompilerType().IsFloat();
3171ac9a064cSDimitry Andric   bool is_integer = GetCompilerType().IsInteger();
3172ac9a064cSDimitry Andric 
3173ac9a064cSDimitry Andric   if (!type.IsScalarType()) {
3174ac9a064cSDimitry Andric     m_error.SetErrorString("target type must be a scalar");
3175ac9a064cSDimitry Andric     return GetSP();
3176ac9a064cSDimitry Andric   }
3177ac9a064cSDimitry Andric 
3178ac9a064cSDimitry Andric   if (!is_scalar && !is_enum && !is_pointer) {
3179ac9a064cSDimitry Andric     m_error.SetErrorString("argument must be a scalar, enum, or pointer");
3180ac9a064cSDimitry Andric     return GetSP();
3181ac9a064cSDimitry Andric   }
3182ac9a064cSDimitry Andric 
3183ac9a064cSDimitry Andric   lldb::TargetSP target = GetTargetSP();
3184ac9a064cSDimitry Andric   uint64_t type_byte_size = 0;
3185ac9a064cSDimitry Andric   uint64_t val_byte_size = 0;
3186ac9a064cSDimitry Andric   if (auto temp = type.GetByteSize(target.get()))
3187ac9a064cSDimitry Andric     type_byte_size = temp.value();
3188ac9a064cSDimitry Andric   if (auto temp = GetCompilerType().GetByteSize(target.get()))
3189ac9a064cSDimitry Andric     val_byte_size = temp.value();
3190ac9a064cSDimitry Andric 
3191ac9a064cSDimitry Andric   if (is_pointer) {
3192ac9a064cSDimitry Andric     if (!type.IsInteger() && !type.IsBoolean()) {
3193ac9a064cSDimitry Andric       m_error.SetErrorString("target type must be an integer or boolean");
3194ac9a064cSDimitry Andric       return GetSP();
3195ac9a064cSDimitry Andric     }
3196ac9a064cSDimitry Andric     if (!type.IsBoolean() && type_byte_size < val_byte_size) {
3197ac9a064cSDimitry Andric       m_error.SetErrorString(
3198ac9a064cSDimitry Andric           "target type cannot be smaller than the pointer type");
3199ac9a064cSDimitry Andric       return GetSP();
3200ac9a064cSDimitry Andric     }
3201ac9a064cSDimitry Andric   }
3202ac9a064cSDimitry Andric 
3203ac9a064cSDimitry Andric   if (type.IsBoolean()) {
3204ac9a064cSDimitry Andric     if (!is_scalar || is_integer)
3205ac9a064cSDimitry Andric       return ValueObject::CreateValueObjectFromBool(
3206ac9a064cSDimitry Andric           target, GetValueAsUnsigned(0) != 0, "result");
3207ac9a064cSDimitry Andric     else if (is_scalar && is_float) {
3208ac9a064cSDimitry Andric       auto float_value_or_err = GetValueAsAPFloat();
3209ac9a064cSDimitry Andric       if (float_value_or_err)
3210ac9a064cSDimitry Andric         return ValueObject::CreateValueObjectFromBool(
3211ac9a064cSDimitry Andric             target, !float_value_or_err->isZero(), "result");
3212ac9a064cSDimitry Andric       else {
3213ac9a064cSDimitry Andric         m_error.SetErrorStringWithFormat(
3214ac9a064cSDimitry Andric             "cannot get value as APFloat: %s",
3215ac9a064cSDimitry Andric             llvm::toString(float_value_or_err.takeError()).c_str());
3216ac9a064cSDimitry Andric         return GetSP();
3217ac9a064cSDimitry Andric       }
3218ac9a064cSDimitry Andric     }
3219ac9a064cSDimitry Andric   }
3220ac9a064cSDimitry Andric 
3221ac9a064cSDimitry Andric   if (type.IsInteger()) {
3222ac9a064cSDimitry Andric     if (!is_scalar || is_integer) {
3223ac9a064cSDimitry Andric       auto int_value_or_err = GetValueAsAPSInt();
3224ac9a064cSDimitry Andric       if (int_value_or_err) {
3225ac9a064cSDimitry Andric         // Get the value as APSInt and extend or truncate it to the requested
3226ac9a064cSDimitry Andric         // size.
3227ac9a064cSDimitry Andric         llvm::APSInt ext =
3228ac9a064cSDimitry Andric             int_value_or_err->extOrTrunc(type_byte_size * CHAR_BIT);
3229ac9a064cSDimitry Andric         return ValueObject::CreateValueObjectFromAPInt(target, ext, type,
3230ac9a064cSDimitry Andric                                                        "result");
3231ac9a064cSDimitry Andric       } else {
3232ac9a064cSDimitry Andric         m_error.SetErrorStringWithFormat(
3233ac9a064cSDimitry Andric             "cannot get value as APSInt: %s",
3234ac9a064cSDimitry Andric             llvm::toString(int_value_or_err.takeError()).c_str());
3235ac9a064cSDimitry Andric         ;
3236ac9a064cSDimitry Andric         return GetSP();
3237ac9a064cSDimitry Andric       }
3238ac9a064cSDimitry Andric     } else if (is_scalar && is_float) {
3239ac9a064cSDimitry Andric       llvm::APSInt integer(type_byte_size * CHAR_BIT, !type.IsSigned());
3240ac9a064cSDimitry Andric       bool is_exact;
3241ac9a064cSDimitry Andric       auto float_value_or_err = GetValueAsAPFloat();
3242ac9a064cSDimitry Andric       if (float_value_or_err) {
3243ac9a064cSDimitry Andric         llvm::APFloatBase::opStatus status =
3244ac9a064cSDimitry Andric             float_value_or_err->convertToInteger(
3245ac9a064cSDimitry Andric                 integer, llvm::APFloat::rmTowardZero, &is_exact);
3246ac9a064cSDimitry Andric 
3247ac9a064cSDimitry Andric         // Casting floating point values that are out of bounds of the target
3248ac9a064cSDimitry Andric         // type is undefined behaviour.
3249ac9a064cSDimitry Andric         if (status & llvm::APFloatBase::opInvalidOp) {
3250ac9a064cSDimitry Andric           m_error.SetErrorStringWithFormat(
3251ac9a064cSDimitry Andric               "invalid type cast detected: %s",
3252ac9a064cSDimitry Andric               llvm::toString(float_value_or_err.takeError()).c_str());
3253ac9a064cSDimitry Andric           return GetSP();
3254ac9a064cSDimitry Andric         }
3255ac9a064cSDimitry Andric         return ValueObject::CreateValueObjectFromAPInt(target, integer, type,
3256ac9a064cSDimitry Andric                                                        "result");
3257ac9a064cSDimitry Andric       }
3258ac9a064cSDimitry Andric     }
3259ac9a064cSDimitry Andric   }
3260ac9a064cSDimitry Andric 
3261ac9a064cSDimitry Andric   if (type.IsFloat()) {
3262ac9a064cSDimitry Andric     if (!is_scalar) {
3263ac9a064cSDimitry Andric       auto int_value_or_err = GetValueAsAPSInt();
3264ac9a064cSDimitry Andric       if (int_value_or_err) {
3265ac9a064cSDimitry Andric         llvm::APSInt ext =
3266ac9a064cSDimitry Andric             int_value_or_err->extOrTrunc(type_byte_size * CHAR_BIT);
3267ac9a064cSDimitry Andric         Scalar scalar_int(ext);
3268ac9a064cSDimitry Andric         llvm::APFloat f = scalar_int.CreateAPFloatFromAPSInt(
3269ac9a064cSDimitry Andric             type.GetCanonicalType().GetBasicTypeEnumeration());
3270ac9a064cSDimitry Andric         return ValueObject::CreateValueObjectFromAPFloat(target, f, type,
3271ac9a064cSDimitry Andric                                                          "result");
3272ac9a064cSDimitry Andric       } else {
3273ac9a064cSDimitry Andric         m_error.SetErrorStringWithFormat(
3274ac9a064cSDimitry Andric             "cannot get value as APSInt: %s",
3275ac9a064cSDimitry Andric             llvm::toString(int_value_or_err.takeError()).c_str());
3276ac9a064cSDimitry Andric         return GetSP();
3277ac9a064cSDimitry Andric       }
3278ac9a064cSDimitry Andric     } else {
3279ac9a064cSDimitry Andric       if (is_integer) {
3280ac9a064cSDimitry Andric         auto int_value_or_err = GetValueAsAPSInt();
3281ac9a064cSDimitry Andric         if (int_value_or_err) {
3282ac9a064cSDimitry Andric           Scalar scalar_int(*int_value_or_err);
3283ac9a064cSDimitry Andric           llvm::APFloat f = scalar_int.CreateAPFloatFromAPSInt(
3284ac9a064cSDimitry Andric               type.GetCanonicalType().GetBasicTypeEnumeration());
3285ac9a064cSDimitry Andric           return ValueObject::CreateValueObjectFromAPFloat(target, f, type,
3286ac9a064cSDimitry Andric                                                            "result");
3287ac9a064cSDimitry Andric         } else {
3288ac9a064cSDimitry Andric           m_error.SetErrorStringWithFormat(
3289ac9a064cSDimitry Andric               "cannot get value as APSInt: %s",
3290ac9a064cSDimitry Andric               llvm::toString(int_value_or_err.takeError()).c_str());
3291ac9a064cSDimitry Andric           return GetSP();
3292ac9a064cSDimitry Andric         }
3293ac9a064cSDimitry Andric       }
3294ac9a064cSDimitry Andric       if (is_float) {
3295ac9a064cSDimitry Andric         auto float_value_or_err = GetValueAsAPFloat();
3296ac9a064cSDimitry Andric         if (float_value_or_err) {
3297ac9a064cSDimitry Andric           Scalar scalar_float(*float_value_or_err);
3298ac9a064cSDimitry Andric           llvm::APFloat f = scalar_float.CreateAPFloatFromAPFloat(
3299ac9a064cSDimitry Andric               type.GetCanonicalType().GetBasicTypeEnumeration());
3300ac9a064cSDimitry Andric           return ValueObject::CreateValueObjectFromAPFloat(target, f, type,
3301ac9a064cSDimitry Andric                                                            "result");
3302ac9a064cSDimitry Andric         } else {
3303ac9a064cSDimitry Andric           m_error.SetErrorStringWithFormat(
3304ac9a064cSDimitry Andric               "cannot get value as APFloat: %s",
3305ac9a064cSDimitry Andric               llvm::toString(float_value_or_err.takeError()).c_str());
3306ac9a064cSDimitry Andric           return GetSP();
3307ac9a064cSDimitry Andric         }
3308ac9a064cSDimitry Andric       }
3309ac9a064cSDimitry Andric     }
3310ac9a064cSDimitry Andric   }
3311ac9a064cSDimitry Andric 
3312ac9a064cSDimitry Andric   m_error.SetErrorString("Unable to perform requested cast");
3313ac9a064cSDimitry Andric   return GetSP();
3314ac9a064cSDimitry Andric }
3315ac9a064cSDimitry Andric 
CastToEnumType(CompilerType type)3316ac9a064cSDimitry Andric lldb::ValueObjectSP ValueObject::CastToEnumType(CompilerType type) {
3317ac9a064cSDimitry Andric   bool is_enum = GetCompilerType().IsEnumerationType();
3318ac9a064cSDimitry Andric   bool is_integer = GetCompilerType().IsInteger();
3319ac9a064cSDimitry Andric   bool is_float = GetCompilerType().IsFloat();
3320ac9a064cSDimitry Andric 
3321ac9a064cSDimitry Andric   if (!is_enum && !is_integer && !is_float) {
3322ac9a064cSDimitry Andric     m_error.SetErrorString("argument must be an integer, a float, or an enum");
3323ac9a064cSDimitry Andric     return GetSP();
3324ac9a064cSDimitry Andric   }
3325ac9a064cSDimitry Andric 
3326ac9a064cSDimitry Andric   if (!type.IsEnumerationType()) {
3327ac9a064cSDimitry Andric     m_error.SetErrorString("target type must be an enum");
3328ac9a064cSDimitry Andric     return GetSP();
3329ac9a064cSDimitry Andric   }
3330ac9a064cSDimitry Andric 
3331ac9a064cSDimitry Andric   lldb::TargetSP target = GetTargetSP();
3332ac9a064cSDimitry Andric   uint64_t byte_size = 0;
3333ac9a064cSDimitry Andric   if (auto temp = type.GetByteSize(target.get()))
3334ac9a064cSDimitry Andric     byte_size = temp.value();
3335ac9a064cSDimitry Andric 
3336ac9a064cSDimitry Andric   if (is_float) {
3337ac9a064cSDimitry Andric     llvm::APSInt integer(byte_size * CHAR_BIT, !type.IsSigned());
3338ac9a064cSDimitry Andric     bool is_exact;
3339ac9a064cSDimitry Andric     auto value_or_err = GetValueAsAPFloat();
3340ac9a064cSDimitry Andric     if (value_or_err) {
3341ac9a064cSDimitry Andric       llvm::APFloatBase::opStatus status = value_or_err->convertToInteger(
3342ac9a064cSDimitry Andric           integer, llvm::APFloat::rmTowardZero, &is_exact);
3343ac9a064cSDimitry Andric 
3344ac9a064cSDimitry Andric       // Casting floating point values that are out of bounds of the target
3345ac9a064cSDimitry Andric       // type is undefined behaviour.
3346ac9a064cSDimitry Andric       if (status & llvm::APFloatBase::opInvalidOp) {
3347ac9a064cSDimitry Andric         m_error.SetErrorStringWithFormat(
3348ac9a064cSDimitry Andric             "invalid type cast detected: %s",
3349ac9a064cSDimitry Andric             llvm::toString(value_or_err.takeError()).c_str());
3350ac9a064cSDimitry Andric         return GetSP();
3351ac9a064cSDimitry Andric       }
3352ac9a064cSDimitry Andric       return ValueObject::CreateValueObjectFromAPInt(target, integer, type,
3353ac9a064cSDimitry Andric                                                      "result");
3354ac9a064cSDimitry Andric     } else {
3355ac9a064cSDimitry Andric       m_error.SetErrorString("cannot get value as APFloat");
3356ac9a064cSDimitry Andric       return GetSP();
3357ac9a064cSDimitry Andric     }
3358ac9a064cSDimitry Andric   } else {
3359ac9a064cSDimitry Andric     // Get the value as APSInt and extend or truncate it to the requested size.
3360ac9a064cSDimitry Andric     auto value_or_err = GetValueAsAPSInt();
3361ac9a064cSDimitry Andric     if (value_or_err) {
3362ac9a064cSDimitry Andric       llvm::APSInt ext = value_or_err->extOrTrunc(byte_size * CHAR_BIT);
3363ac9a064cSDimitry Andric       return ValueObject::CreateValueObjectFromAPInt(target, ext, type,
3364ac9a064cSDimitry Andric                                                      "result");
3365ac9a064cSDimitry Andric     } else {
3366ac9a064cSDimitry Andric       m_error.SetErrorStringWithFormat(
3367ac9a064cSDimitry Andric           "cannot get value as APSInt: %s",
3368ac9a064cSDimitry Andric           llvm::toString(value_or_err.takeError()).c_str());
3369ac9a064cSDimitry Andric       return GetSP();
3370ac9a064cSDimitry Andric     }
3371ac9a064cSDimitry Andric   }
3372ac9a064cSDimitry Andric   m_error.SetErrorString("Cannot perform requested cast");
3373ac9a064cSDimitry Andric   return GetSP();
3374ac9a064cSDimitry Andric }
3375ac9a064cSDimitry Andric 
EvaluationPoint()3376344a3780SDimitry Andric ValueObject::EvaluationPoint::EvaluationPoint() : m_mod_id(), m_exe_ctx_ref() {}
3377f034231aSEd Maste 
EvaluationPoint(ExecutionContextScope * exe_scope,bool use_selected)337814f1b3e8SDimitry Andric ValueObject::EvaluationPoint::EvaluationPoint(ExecutionContextScope *exe_scope,
337914f1b3e8SDimitry Andric                                               bool use_selected)
3380145449b1SDimitry Andric     : m_mod_id(), m_exe_ctx_ref() {
3381f034231aSEd Maste   ExecutionContext exe_ctx(exe_scope);
3382f034231aSEd Maste   TargetSP target_sp(exe_ctx.GetTargetSP());
338314f1b3e8SDimitry Andric   if (target_sp) {
3384f034231aSEd Maste     m_exe_ctx_ref.SetTargetSP(target_sp);
3385f034231aSEd Maste     ProcessSP process_sp(exe_ctx.GetProcessSP());
3386f034231aSEd Maste     if (!process_sp)
3387f034231aSEd Maste       process_sp = target_sp->GetProcessSP();
3388f034231aSEd Maste 
338914f1b3e8SDimitry Andric     if (process_sp) {
3390f034231aSEd Maste       m_mod_id = process_sp->GetModID();
3391f034231aSEd Maste       m_exe_ctx_ref.SetProcessSP(process_sp);
3392f034231aSEd Maste 
3393f034231aSEd Maste       ThreadSP thread_sp(exe_ctx.GetThreadSP());
3394f034231aSEd Maste 
339514f1b3e8SDimitry Andric       if (!thread_sp) {
3396f034231aSEd Maste         if (use_selected)
3397f034231aSEd Maste           thread_sp = process_sp->GetThreadList().GetSelectedThread();
3398f034231aSEd Maste       }
3399f034231aSEd Maste 
340014f1b3e8SDimitry Andric       if (thread_sp) {
3401f034231aSEd Maste         m_exe_ctx_ref.SetThreadSP(thread_sp);
3402f034231aSEd Maste 
3403f034231aSEd Maste         StackFrameSP frame_sp(exe_ctx.GetFrameSP());
340414f1b3e8SDimitry Andric         if (!frame_sp) {
3405f034231aSEd Maste           if (use_selected)
34067fa27ce4SDimitry Andric             frame_sp = thread_sp->GetSelectedFrame(DoNoSelectMostRelevantFrame);
3407f034231aSEd Maste         }
3408f034231aSEd Maste         if (frame_sp)
3409f034231aSEd Maste           m_exe_ctx_ref.SetFrameSP(frame_sp);
3410f034231aSEd Maste       }
3411f034231aSEd Maste     }
3412f034231aSEd Maste   }
3413f034231aSEd Maste }
3414f034231aSEd Maste 
EvaluationPoint(const ValueObject::EvaluationPoint & rhs)341514f1b3e8SDimitry Andric ValueObject::EvaluationPoint::EvaluationPoint(
341614f1b3e8SDimitry Andric     const ValueObject::EvaluationPoint &rhs)
3417145449b1SDimitry Andric     : m_mod_id(), m_exe_ctx_ref(rhs.m_exe_ctx_ref) {}
3418f034231aSEd Maste 
3419344a3780SDimitry Andric ValueObject::EvaluationPoint::~EvaluationPoint() = default;
3420f034231aSEd Maste 
342114f1b3e8SDimitry Andric // This function checks the EvaluationPoint against the current process state.
3422f73363f1SDimitry Andric // If the current state matches the evaluation point, or the evaluation point
3423f73363f1SDimitry Andric // is already invalid, then we return false, meaning "no change".  If the
3424f73363f1SDimitry Andric // current state is different, we update our state, and return true meaning
3425f73363f1SDimitry Andric // "yes, change".  If we did see a change, we also set m_needs_update to true,
3426f73363f1SDimitry Andric // so future calls to NeedsUpdate will return true. exe_scope will be set to
3427f73363f1SDimitry Andric // the current execution context scope.
3428f034231aSEd Maste 
SyncWithProcessState(bool accept_invalid_exe_ctx)342914f1b3e8SDimitry Andric bool ValueObject::EvaluationPoint::SyncWithProcessState(
343014f1b3e8SDimitry Andric     bool accept_invalid_exe_ctx) {
3431f73363f1SDimitry Andric   // Start with the target, if it is NULL, then we're obviously not going to
3432f73363f1SDimitry Andric   // get any further:
3433866dcdacSEd Maste   const bool thread_and_frame_only_if_stopped = true;
343414f1b3e8SDimitry Andric   ExecutionContext exe_ctx(
343514f1b3e8SDimitry Andric       m_exe_ctx_ref.Lock(thread_and_frame_only_if_stopped));
3436f034231aSEd Maste 
34375f29bb8aSDimitry Andric   if (exe_ctx.GetTargetPtr() == nullptr)
3438f034231aSEd Maste     return false;
3439f034231aSEd Maste 
3440f034231aSEd Maste   // If we don't have a process nothing can change.
3441f034231aSEd Maste   Process *process = exe_ctx.GetProcessPtr();
34425f29bb8aSDimitry Andric   if (process == nullptr)
3443f034231aSEd Maste     return false;
3444f034231aSEd Maste 
3445f034231aSEd Maste   // If our stop id is the current stop ID, nothing has changed:
3446f034231aSEd Maste   ProcessModID current_mod_id = process->GetModID();
3447f034231aSEd Maste 
344814f1b3e8SDimitry Andric   // If the current stop id is 0, either we haven't run yet, or the process
3449f73363f1SDimitry Andric   // state has been cleared. In either case, we aren't going to be able to sync
3450f73363f1SDimitry Andric   // with the process state.
3451f034231aSEd Maste   if (current_mod_id.GetStopID() == 0)
3452f034231aSEd Maste     return false;
3453f034231aSEd Maste 
3454f034231aSEd Maste   bool changed = false;
3455f034231aSEd Maste   const bool was_valid = m_mod_id.IsValid();
345614f1b3e8SDimitry Andric   if (was_valid) {
345714f1b3e8SDimitry Andric     if (m_mod_id == current_mod_id) {
3458f73363f1SDimitry Andric       // Everything is already up to date in this object, no need to update the
3459f73363f1SDimitry Andric       // execution context scope.
3460f034231aSEd Maste       changed = false;
346114f1b3e8SDimitry Andric     } else {
3462f034231aSEd Maste       m_mod_id = current_mod_id;
3463f034231aSEd Maste       m_needs_update = true;
3464f034231aSEd Maste       changed = true;
3465f034231aSEd Maste     }
3466f034231aSEd Maste   }
3467f034231aSEd Maste 
346814f1b3e8SDimitry Andric   // Now re-look up the thread and frame in case the underlying objects have
3469f73363f1SDimitry Andric   // gone away & been recreated. That way we'll be sure to return a valid
3470f73363f1SDimitry Andric   // exe_scope. If we used to have a thread or a frame but can't find it
3471f73363f1SDimitry Andric   // anymore, then mark ourselves as invalid.
3472f034231aSEd Maste 
347314f1b3e8SDimitry Andric   if (!accept_invalid_exe_ctx) {
347414f1b3e8SDimitry Andric     if (m_exe_ctx_ref.HasThreadRef()) {
3475f034231aSEd Maste       ThreadSP thread_sp(m_exe_ctx_ref.GetThreadSP());
347614f1b3e8SDimitry Andric       if (thread_sp) {
347714f1b3e8SDimitry Andric         if (m_exe_ctx_ref.HasFrameRef()) {
3478f034231aSEd Maste           StackFrameSP frame_sp(m_exe_ctx_ref.GetFrameSP());
347914f1b3e8SDimitry Andric           if (!frame_sp) {
3480f034231aSEd Maste             // We used to have a frame, but now it is gone
3481f034231aSEd Maste             SetInvalid();
3482f034231aSEd Maste             changed = was_valid;
3483f034231aSEd Maste           }
3484f034231aSEd Maste         }
348514f1b3e8SDimitry Andric       } else {
3486f034231aSEd Maste         // We used to have a thread, but now it is gone
3487f034231aSEd Maste         SetInvalid();
3488f034231aSEd Maste         changed = was_valid;
3489f034231aSEd Maste       }
3490f034231aSEd Maste     }
34915e95aa85SEd Maste   }
34925e95aa85SEd Maste 
3493f034231aSEd Maste   return changed;
3494f034231aSEd Maste }
3495f034231aSEd Maste 
SetUpdated()349614f1b3e8SDimitry Andric void ValueObject::EvaluationPoint::SetUpdated() {
3497f034231aSEd Maste   ProcessSP process_sp(m_exe_ctx_ref.GetProcessSP());
3498f034231aSEd Maste   if (process_sp)
3499f034231aSEd Maste     m_mod_id = process_sp->GetModID();
3500f034231aSEd Maste   m_needs_update = false;
3501f034231aSEd Maste }
3502f034231aSEd Maste 
ClearUserVisibleData(uint32_t clear_mask)350314f1b3e8SDimitry Andric void ValueObject::ClearUserVisibleData(uint32_t clear_mask) {
350414f1b3e8SDimitry Andric   if ((clear_mask & eClearUserVisibleDataItemsValue) ==
350514f1b3e8SDimitry Andric       eClearUserVisibleDataItemsValue)
3506f034231aSEd Maste     m_value_str.clear();
3507f034231aSEd Maste 
350814f1b3e8SDimitry Andric   if ((clear_mask & eClearUserVisibleDataItemsLocation) ==
350914f1b3e8SDimitry Andric       eClearUserVisibleDataItemsLocation)
3510f034231aSEd Maste     m_location_str.clear();
3511f034231aSEd Maste 
351214f1b3e8SDimitry Andric   if ((clear_mask & eClearUserVisibleDataItemsSummary) ==
351314f1b3e8SDimitry Andric       eClearUserVisibleDataItemsSummary)
3514f034231aSEd Maste     m_summary_str.clear();
3515f034231aSEd Maste 
351614f1b3e8SDimitry Andric   if ((clear_mask & eClearUserVisibleDataItemsDescription) ==
351714f1b3e8SDimitry Andric       eClearUserVisibleDataItemsDescription)
3518f034231aSEd Maste     m_object_desc_str.clear();
3519f034231aSEd Maste 
352014f1b3e8SDimitry Andric   if ((clear_mask & eClearUserVisibleDataItemsSyntheticChildren) ==
352114f1b3e8SDimitry Andric       eClearUserVisibleDataItemsSyntheticChildren) {
3522f034231aSEd Maste     if (m_synthetic_value)
35235f29bb8aSDimitry Andric       m_synthetic_value = nullptr;
3524f034231aSEd Maste   }
3525f034231aSEd Maste }
3526f034231aSEd Maste 
GetSymbolContextScope()352714f1b3e8SDimitry Andric SymbolContextScope *ValueObject::GetSymbolContextScope() {
352814f1b3e8SDimitry Andric   if (m_parent) {
3529f034231aSEd Maste     if (!m_parent->IsPointerOrReferenceType())
3530f034231aSEd Maste       return m_parent->GetSymbolContextScope();
3531f034231aSEd Maste   }
35325f29bb8aSDimitry Andric   return nullptr;
3533f034231aSEd Maste }
3534f034231aSEd Maste 
3535f034231aSEd Maste lldb::ValueObjectSP
CreateValueObjectFromExpression(llvm::StringRef name,llvm::StringRef expression,const ExecutionContext & exe_ctx)353614f1b3e8SDimitry Andric ValueObject::CreateValueObjectFromExpression(llvm::StringRef name,
353714f1b3e8SDimitry Andric                                              llvm::StringRef expression,
353814f1b3e8SDimitry Andric                                              const ExecutionContext &exe_ctx) {
353914f1b3e8SDimitry Andric   return CreateValueObjectFromExpression(name, expression, exe_ctx,
354014f1b3e8SDimitry Andric                                          EvaluateExpressionOptions());
3541205afe67SEd Maste }
3542205afe67SEd Maste 
CreateValueObjectFromExpression(llvm::StringRef name,llvm::StringRef expression,const ExecutionContext & exe_ctx,const EvaluateExpressionOptions & options)354314f1b3e8SDimitry Andric lldb::ValueObjectSP ValueObject::CreateValueObjectFromExpression(
354414f1b3e8SDimitry Andric     llvm::StringRef name, llvm::StringRef expression,
354514f1b3e8SDimitry Andric     const ExecutionContext &exe_ctx, const EvaluateExpressionOptions &options) {
3546f034231aSEd Maste   lldb::ValueObjectSP retval_sp;
3547f034231aSEd Maste   lldb::TargetSP target_sp(exe_ctx.GetTargetSP());
3548f034231aSEd Maste   if (!target_sp)
3549f034231aSEd Maste     return retval_sp;
355014f1b3e8SDimitry Andric   if (expression.empty())
3551f034231aSEd Maste     return retval_sp;
355214f1b3e8SDimitry Andric   target_sp->EvaluateExpression(expression, exe_ctx.GetFrameSP().get(),
355314f1b3e8SDimitry Andric                                 retval_sp, options);
355414f1b3e8SDimitry Andric   if (retval_sp && !name.empty())
3555f034231aSEd Maste     retval_sp->SetName(ConstString(name));
3556f034231aSEd Maste   return retval_sp;
3557f034231aSEd Maste }
3558f034231aSEd Maste 
CreateValueObjectFromAddress(llvm::StringRef name,uint64_t address,const ExecutionContext & exe_ctx,CompilerType type,bool do_deref)355914f1b3e8SDimitry Andric lldb::ValueObjectSP ValueObject::CreateValueObjectFromAddress(
356014f1b3e8SDimitry Andric     llvm::StringRef name, uint64_t address, const ExecutionContext &exe_ctx,
3561ac9a064cSDimitry Andric     CompilerType type, bool do_deref) {
356214f1b3e8SDimitry Andric   if (type) {
3563e81d9d49SDimitry Andric     CompilerType pointer_type(type.GetPointerType());
3564ac9a064cSDimitry Andric     if (!do_deref)
3565ac9a064cSDimitry Andric       pointer_type = type;
356614f1b3e8SDimitry Andric     if (pointer_type) {
356714f1b3e8SDimitry Andric       lldb::DataBufferSP buffer(
356814f1b3e8SDimitry Andric           new lldb_private::DataBufferHeap(&address, sizeof(lldb::addr_t)));
356914f1b3e8SDimitry Andric       lldb::ValueObjectSP ptr_result_valobj_sp(ValueObjectConstResult::Create(
357014f1b3e8SDimitry Andric           exe_ctx.GetBestExecutionContextScope(), pointer_type,
357114f1b3e8SDimitry Andric           ConstString(name), buffer, exe_ctx.GetByteOrder(),
3572f034231aSEd Maste           exe_ctx.GetAddressByteSize()));
357314f1b3e8SDimitry Andric       if (ptr_result_valobj_sp) {
3574ac9a064cSDimitry Andric         if (do_deref)
357514f1b3e8SDimitry Andric           ptr_result_valobj_sp->GetValue().SetValueType(
3576344a3780SDimitry Andric               Value::ValueType::LoadAddress);
3577b76161e4SDimitry Andric         Status err;
3578ac9a064cSDimitry Andric         if (do_deref)
3579f034231aSEd Maste           ptr_result_valobj_sp = ptr_result_valobj_sp->Dereference(err);
358014f1b3e8SDimitry Andric         if (ptr_result_valobj_sp && !name.empty())
3581f034231aSEd Maste           ptr_result_valobj_sp->SetName(ConstString(name));
3582f034231aSEd Maste       }
3583f034231aSEd Maste       return ptr_result_valobj_sp;
3584f034231aSEd Maste     }
3585f034231aSEd Maste   }
3586f034231aSEd Maste   return lldb::ValueObjectSP();
3587f034231aSEd Maste }
3588f034231aSEd Maste 
CreateValueObjectFromData(llvm::StringRef name,const DataExtractor & data,const ExecutionContext & exe_ctx,CompilerType type)358914f1b3e8SDimitry Andric lldb::ValueObjectSP ValueObject::CreateValueObjectFromData(
359014f1b3e8SDimitry Andric     llvm::StringRef name, const DataExtractor &data,
359114f1b3e8SDimitry Andric     const ExecutionContext &exe_ctx, CompilerType type) {
3592f034231aSEd Maste   lldb::ValueObjectSP new_value_sp;
359314f1b3e8SDimitry Andric   new_value_sp = ValueObjectConstResult::Create(
359414f1b3e8SDimitry Andric       exe_ctx.GetBestExecutionContextScope(), type, ConstString(name), data,
3595f034231aSEd Maste       LLDB_INVALID_ADDRESS);
3596f034231aSEd Maste   new_value_sp->SetAddressTypeOfChildren(eAddressTypeLoad);
359714f1b3e8SDimitry Andric   if (new_value_sp && !name.empty())
3598f034231aSEd Maste     new_value_sp->SetName(ConstString(name));
3599f034231aSEd Maste   return new_value_sp;
3600f034231aSEd Maste }
3601f034231aSEd Maste 
3602ac9a064cSDimitry Andric lldb::ValueObjectSP
CreateValueObjectFromAPInt(lldb::TargetSP target,const llvm::APInt & v,CompilerType type,llvm::StringRef name)3603ac9a064cSDimitry Andric ValueObject::CreateValueObjectFromAPInt(lldb::TargetSP target,
3604ac9a064cSDimitry Andric                                         const llvm::APInt &v, CompilerType type,
3605ac9a064cSDimitry Andric                                         llvm::StringRef name) {
3606ac9a064cSDimitry Andric   ExecutionContext exe_ctx(target.get(), false);
3607ac9a064cSDimitry Andric   uint64_t byte_size = 0;
3608ac9a064cSDimitry Andric   if (auto temp = type.GetByteSize(target.get()))
3609ac9a064cSDimitry Andric     byte_size = temp.value();
3610ac9a064cSDimitry Andric   lldb::DataExtractorSP data_sp = std::make_shared<DataExtractor>(
3611ac9a064cSDimitry Andric       reinterpret_cast<const void *>(v.getRawData()), byte_size,
3612ac9a064cSDimitry Andric       exe_ctx.GetByteOrder(), exe_ctx.GetAddressByteSize());
3613ac9a064cSDimitry Andric   return ValueObject::CreateValueObjectFromData(name, *data_sp, exe_ctx, type);
3614ac9a064cSDimitry Andric }
3615ac9a064cSDimitry Andric 
CreateValueObjectFromAPFloat(lldb::TargetSP target,const llvm::APFloat & v,CompilerType type,llvm::StringRef name)3616ac9a064cSDimitry Andric lldb::ValueObjectSP ValueObject::CreateValueObjectFromAPFloat(
3617ac9a064cSDimitry Andric     lldb::TargetSP target, const llvm::APFloat &v, CompilerType type,
3618ac9a064cSDimitry Andric     llvm::StringRef name) {
3619ac9a064cSDimitry Andric   return CreateValueObjectFromAPInt(target, v.bitcastToAPInt(), type, name);
3620ac9a064cSDimitry Andric }
3621ac9a064cSDimitry Andric 
3622ac9a064cSDimitry Andric lldb::ValueObjectSP
CreateValueObjectFromBool(lldb::TargetSP target,bool value,llvm::StringRef name)3623ac9a064cSDimitry Andric ValueObject::CreateValueObjectFromBool(lldb::TargetSP target, bool value,
3624ac9a064cSDimitry Andric                                        llvm::StringRef name) {
3625ac9a064cSDimitry Andric   CompilerType target_type;
3626ac9a064cSDimitry Andric   if (target) {
3627ac9a064cSDimitry Andric     for (auto type_system_sp : target->GetScratchTypeSystems())
3628ac9a064cSDimitry Andric       if (auto compiler_type =
3629ac9a064cSDimitry Andric               type_system_sp->GetBasicTypeFromAST(lldb::eBasicTypeBool)) {
3630ac9a064cSDimitry Andric         target_type = compiler_type;
3631ac9a064cSDimitry Andric         break;
3632ac9a064cSDimitry Andric       }
3633ac9a064cSDimitry Andric   }
3634ac9a064cSDimitry Andric   ExecutionContext exe_ctx(target.get(), false);
3635ac9a064cSDimitry Andric   uint64_t byte_size = 0;
3636ac9a064cSDimitry Andric   if (auto temp = target_type.GetByteSize(target.get()))
3637ac9a064cSDimitry Andric     byte_size = temp.value();
3638ac9a064cSDimitry Andric   lldb::DataExtractorSP data_sp = std::make_shared<DataExtractor>(
3639ac9a064cSDimitry Andric       reinterpret_cast<const void *>(&value), byte_size, exe_ctx.GetByteOrder(),
3640ac9a064cSDimitry Andric       exe_ctx.GetAddressByteSize());
3641ac9a064cSDimitry Andric   return ValueObject::CreateValueObjectFromData(name, *data_sp, exe_ctx,
3642ac9a064cSDimitry Andric                                                 target_type);
3643ac9a064cSDimitry Andric }
3644ac9a064cSDimitry Andric 
CreateValueObjectFromNullptr(lldb::TargetSP target,CompilerType type,llvm::StringRef name)3645ac9a064cSDimitry Andric lldb::ValueObjectSP ValueObject::CreateValueObjectFromNullptr(
3646ac9a064cSDimitry Andric     lldb::TargetSP target, CompilerType type, llvm::StringRef name) {
3647ac9a064cSDimitry Andric   if (!type.IsNullPtrType()) {
3648ac9a064cSDimitry Andric     lldb::ValueObjectSP ret_val;
3649ac9a064cSDimitry Andric     return ret_val;
3650ac9a064cSDimitry Andric   }
3651ac9a064cSDimitry Andric   uintptr_t zero = 0;
3652ac9a064cSDimitry Andric   ExecutionContext exe_ctx(target.get(), false);
3653ac9a064cSDimitry Andric   uint64_t byte_size = 0;
3654ac9a064cSDimitry Andric   if (auto temp = type.GetByteSize(target.get()))
3655ac9a064cSDimitry Andric     byte_size = temp.value();
3656ac9a064cSDimitry Andric   lldb::DataExtractorSP data_sp = std::make_shared<DataExtractor>(
3657ac9a064cSDimitry Andric       reinterpret_cast<const void *>(zero), byte_size, exe_ctx.GetByteOrder(),
3658ac9a064cSDimitry Andric       exe_ctx.GetAddressByteSize());
3659ac9a064cSDimitry Andric   return ValueObject::CreateValueObjectFromData(name, *data_sp, exe_ctx, type);
3660ac9a064cSDimitry Andric }
3661ac9a064cSDimitry Andric 
GetModule()366214f1b3e8SDimitry Andric ModuleSP ValueObject::GetModule() {
3663f034231aSEd Maste   ValueObject *root(GetRoot());
3664f034231aSEd Maste   if (root != this)
3665f034231aSEd Maste     return root->GetModule();
3666f034231aSEd Maste   return lldb::ModuleSP();
3667f034231aSEd Maste }
3668f034231aSEd Maste 
GetRoot()366914f1b3e8SDimitry Andric ValueObject *ValueObject::GetRoot() {
3670f034231aSEd Maste   if (m_root)
3671f034231aSEd Maste     return m_root;
367212bd4897SEd Maste   return (m_root = FollowParentChain([](ValueObject *vo) -> bool {
367312bd4897SEd Maste             return (vo->m_parent != nullptr);
367412bd4897SEd Maste           }));
3675f034231aSEd Maste }
367612bd4897SEd Maste 
367712bd4897SEd Maste ValueObject *
FollowParentChain(std::function<bool (ValueObject *)> f)367814f1b3e8SDimitry Andric ValueObject::FollowParentChain(std::function<bool(ValueObject *)> f) {
367912bd4897SEd Maste   ValueObject *vo = this;
368014f1b3e8SDimitry Andric   while (vo) {
368194994d37SDimitry Andric     if (!f(vo))
368212bd4897SEd Maste       break;
368312bd4897SEd Maste     vo = vo->m_parent;
368412bd4897SEd Maste   }
368512bd4897SEd Maste   return vo;
3686f034231aSEd Maste }
3687f034231aSEd Maste 
GetAddressTypeOfChildren()368814f1b3e8SDimitry Andric AddressType ValueObject::GetAddressTypeOfChildren() {
368914f1b3e8SDimitry Andric   if (m_address_type_of_ptr_or_ref_children == eAddressTypeInvalid) {
3690f034231aSEd Maste     ValueObject *root(GetRoot());
3691f034231aSEd Maste     if (root != this)
3692f034231aSEd Maste       return root->GetAddressTypeOfChildren();
3693f034231aSEd Maste   }
3694f034231aSEd Maste   return m_address_type_of_ptr_or_ref_children;
3695f034231aSEd Maste }
3696f034231aSEd Maste 
GetDynamicValueType()369714f1b3e8SDimitry Andric lldb::DynamicValueType ValueObject::GetDynamicValueType() {
3698f034231aSEd Maste   ValueObject *with_dv_info = this;
369914f1b3e8SDimitry Andric   while (with_dv_info) {
3700f034231aSEd Maste     if (with_dv_info->HasDynamicValueTypeInfo())
3701f034231aSEd Maste       return with_dv_info->GetDynamicValueTypeImpl();
3702f034231aSEd Maste     with_dv_info = with_dv_info->m_parent;
3703f034231aSEd Maste   }
3704f034231aSEd Maste   return lldb::eNoDynamicValues;
3705f034231aSEd Maste }
3706f034231aSEd Maste 
GetFormat() const370714f1b3e8SDimitry Andric lldb::Format ValueObject::GetFormat() const {
3708f034231aSEd Maste   const ValueObject *with_fmt_info = this;
370914f1b3e8SDimitry Andric   while (with_fmt_info) {
3710f034231aSEd Maste     if (with_fmt_info->m_format != lldb::eFormatDefault)
3711f034231aSEd Maste       return with_fmt_info->m_format;
3712f034231aSEd Maste     with_fmt_info = with_fmt_info->m_parent;
3713f034231aSEd Maste   }
3714f034231aSEd Maste   return m_format;
3715f034231aSEd Maste }
3716205afe67SEd Maste 
GetPreferredDisplayLanguage()371714f1b3e8SDimitry Andric lldb::LanguageType ValueObject::GetPreferredDisplayLanguage() {
371812bd4897SEd Maste   lldb::LanguageType type = m_preferred_display_language;
371914f1b3e8SDimitry Andric   if (m_preferred_display_language == lldb::eLanguageTypeUnknown) {
372014f1b3e8SDimitry Andric     if (GetRoot()) {
372114f1b3e8SDimitry Andric       if (GetRoot() == this) {
372214f1b3e8SDimitry Andric         if (StackFrameSP frame_sp = GetFrameSP()) {
372314f1b3e8SDimitry Andric           const SymbolContext &sc(
372414f1b3e8SDimitry Andric               frame_sp->GetSymbolContext(eSymbolContextCompUnit));
3725205afe67SEd Maste           if (CompileUnit *cu = sc.comp_unit)
3726205afe67SEd Maste             type = cu->GetLanguage();
3727205afe67SEd Maste         }
372814f1b3e8SDimitry Andric       } else {
3729205afe67SEd Maste         type = GetRoot()->GetPreferredDisplayLanguage();
3730205afe67SEd Maste       }
3731205afe67SEd Maste     }
373212bd4897SEd Maste   }
373312bd4897SEd Maste   return (m_preferred_display_language = type); // only compute it once
373412bd4897SEd Maste }
373512bd4897SEd Maste 
SetPreferredDisplayLanguageIfNeeded(lldb::LanguageType lt)373614f1b3e8SDimitry Andric void ValueObject::SetPreferredDisplayLanguageIfNeeded(lldb::LanguageType lt) {
3737e81d9d49SDimitry Andric   if (m_preferred_display_language == lldb::eLanguageTypeUnknown)
3738e81d9d49SDimitry Andric     SetPreferredDisplayLanguage(lt);
3739e81d9d49SDimitry Andric }
3740e81d9d49SDimitry Andric 
CanProvideValue()374114f1b3e8SDimitry Andric bool ValueObject::CanProvideValue() {
3742f73363f1SDimitry Andric   // we need to support invalid types as providers of values because some bare-
3743f73363f1SDimitry Andric   // board debugging scenarios have no notion of types, but still manage to
3744f73363f1SDimitry Andric   // have raw numeric values for things like registers. sigh.
3745b60736ecSDimitry Andric   CompilerType type = GetCompilerType();
374694994d37SDimitry Andric   return (!type.IsValid()) || (0 != (type.GetTypeInfo() & eTypeHasValue));
3747205afe67SEd Maste }
3748205afe67SEd Maste 
3749344a3780SDimitry Andric 
3750205afe67SEd Maste 
Persist()375114f1b3e8SDimitry Andric ValueObjectSP ValueObject::Persist() {
3752205afe67SEd Maste   if (!UpdateValueIfNeeded())
3753205afe67SEd Maste     return nullptr;
3754205afe67SEd Maste 
3755205afe67SEd Maste   TargetSP target_sp(GetTargetSP());
3756205afe67SEd Maste   if (!target_sp)
3757205afe67SEd Maste     return nullptr;
3758205afe67SEd Maste 
375914f1b3e8SDimitry Andric   PersistentExpressionState *persistent_state =
376014f1b3e8SDimitry Andric       target_sp->GetPersistentExpressionStateForLanguage(
376114f1b3e8SDimitry Andric           GetPreferredDisplayLanguage());
3762205afe67SEd Maste 
3763e81d9d49SDimitry Andric   if (!persistent_state)
3764e81d9d49SDimitry Andric     return nullptr;
3765e81d9d49SDimitry Andric 
3766cfca06d7SDimitry Andric   ConstString name = persistent_state->GetNextPersistentVariableName();
3767e81d9d49SDimitry Andric 
376814f1b3e8SDimitry Andric   ValueObjectSP const_result_sp =
376914f1b3e8SDimitry Andric       ValueObjectConstResult::Create(target_sp.get(), GetValue(), name);
3770e81d9d49SDimitry Andric 
3771cfca06d7SDimitry Andric   ExpressionVariableSP persistent_var_sp =
377214f1b3e8SDimitry Andric       persistent_state->CreatePersistentVariable(const_result_sp);
3773cfca06d7SDimitry Andric   persistent_var_sp->m_live_sp = persistent_var_sp->m_frozen_sp;
3774cfca06d7SDimitry Andric   persistent_var_sp->m_flags |= ExpressionVariable::EVIsProgramReference;
3775205afe67SEd Maste 
3776cfca06d7SDimitry Andric   return persistent_var_sp->GetValueObject();
3777205afe67SEd Maste }
3778b1c73532SDimitry Andric 
GetVTable()3779b1c73532SDimitry Andric lldb::ValueObjectSP ValueObject::GetVTable() {
3780b1c73532SDimitry Andric   return ValueObjectVTable::Create(*this);
3781b1c73532SDimitry Andric }
3782