15ffd83dbSDimitry Andric //===-- ValueObject.cpp ---------------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "lldb/Core/ValueObject.h"
100b57cec5SDimitry Andric 
110b57cec5SDimitry Andric #include "lldb/Core/Address.h"
12fe6060f1SDimitry Andric #include "lldb/Core/Declaration.h"
130b57cec5SDimitry Andric #include "lldb/Core/Module.h"
140b57cec5SDimitry Andric #include "lldb/Core/ValueObjectCast.h"
150b57cec5SDimitry Andric #include "lldb/Core/ValueObjectChild.h"
160b57cec5SDimitry Andric #include "lldb/Core/ValueObjectConstResult.h"
170b57cec5SDimitry Andric #include "lldb/Core/ValueObjectDynamicValue.h"
180b57cec5SDimitry Andric #include "lldb/Core/ValueObjectMemory.h"
190b57cec5SDimitry Andric #include "lldb/Core/ValueObjectSyntheticFilter.h"
20c9157d92SDimitry Andric #include "lldb/Core/ValueObjectVTable.h"
210b57cec5SDimitry Andric #include "lldb/DataFormatters/DataVisualization.h"
220b57cec5SDimitry Andric #include "lldb/DataFormatters/DumpValueObjectOptions.h"
230b57cec5SDimitry Andric #include "lldb/DataFormatters/FormatManager.h"
240b57cec5SDimitry Andric #include "lldb/DataFormatters/StringPrinter.h"
250b57cec5SDimitry Andric #include "lldb/DataFormatters/TypeFormat.h"
260b57cec5SDimitry Andric #include "lldb/DataFormatters/TypeSummary.h"
270b57cec5SDimitry Andric #include "lldb/DataFormatters/ValueObjectPrinter.h"
280b57cec5SDimitry Andric #include "lldb/Expression/ExpressionVariable.h"
29480093f4SDimitry Andric #include "lldb/Host/Config.h"
300b57cec5SDimitry Andric #include "lldb/Symbol/CompileUnit.h"
310b57cec5SDimitry Andric #include "lldb/Symbol/CompilerType.h"
320b57cec5SDimitry Andric #include "lldb/Symbol/SymbolContext.h"
330b57cec5SDimitry Andric #include "lldb/Symbol/Type.h"
340b57cec5SDimitry Andric #include "lldb/Symbol/Variable.h"
350b57cec5SDimitry Andric #include "lldb/Target/ExecutionContext.h"
360b57cec5SDimitry Andric #include "lldb/Target/Language.h"
370b57cec5SDimitry Andric #include "lldb/Target/LanguageRuntime.h"
380b57cec5SDimitry Andric #include "lldb/Target/Process.h"
390b57cec5SDimitry Andric #include "lldb/Target/StackFrame.h"
400b57cec5SDimitry Andric #include "lldb/Target/Target.h"
410b57cec5SDimitry Andric #include "lldb/Target/Thread.h"
420b57cec5SDimitry Andric #include "lldb/Target/ThreadList.h"
430b57cec5SDimitry Andric #include "lldb/Utility/DataBuffer.h"
440b57cec5SDimitry Andric #include "lldb/Utility/DataBufferHeap.h"
450b57cec5SDimitry Andric #include "lldb/Utility/Flags.h"
4681ad6265SDimitry Andric #include "lldb/Utility/LLDBLog.h"
470b57cec5SDimitry Andric #include "lldb/Utility/Log.h"
480b57cec5SDimitry Andric #include "lldb/Utility/Scalar.h"
490b57cec5SDimitry Andric #include "lldb/Utility/Stream.h"
500b57cec5SDimitry Andric #include "lldb/Utility/StreamString.h"
510b57cec5SDimitry Andric #include "lldb/lldb-private-types.h"
520b57cec5SDimitry Andric 
530b57cec5SDimitry Andric #include "llvm/Support/Compiler.h"
540b57cec5SDimitry Andric 
550b57cec5SDimitry Andric #include <algorithm>
560b57cec5SDimitry Andric #include <cstdint>
570b57cec5SDimitry Andric #include <cstdlib>
580b57cec5SDimitry Andric #include <memory>
59bdd1243dSDimitry Andric #include <optional>
600b57cec5SDimitry Andric #include <tuple>
610b57cec5SDimitry Andric 
62fe6060f1SDimitry Andric #include <cassert>
63fe6060f1SDimitry Andric #include <cinttypes>
64fe6060f1SDimitry Andric #include <cstdio>
65fe6060f1SDimitry Andric #include <cstring>
66fe6060f1SDimitry Andric 
67fe6060f1SDimitry Andric #include <lldb/Core/ValueObject.h>
680b57cec5SDimitry Andric 
690b57cec5SDimitry Andric namespace lldb_private {
700b57cec5SDimitry Andric class ExecutionContextScope;
710b57cec5SDimitry Andric }
720b57cec5SDimitry Andric namespace lldb_private {
730b57cec5SDimitry Andric class SymbolContextScope;
740b57cec5SDimitry Andric }
750b57cec5SDimitry Andric 
760b57cec5SDimitry Andric using namespace lldb;
770b57cec5SDimitry Andric using namespace lldb_private;
780b57cec5SDimitry Andric 
790b57cec5SDimitry Andric static user_id_t g_value_obj_uid = 0;
800b57cec5SDimitry Andric 
810b57cec5SDimitry Andric // ValueObject constructor
ValueObject(ValueObject & parent)820b57cec5SDimitry Andric ValueObject::ValueObject(ValueObject &parent)
83fe6060f1SDimitry Andric     : m_parent(&parent), m_update_point(parent.GetUpdatePoint()),
84fe6060f1SDimitry Andric       m_manager(parent.GetManager()), m_id(++g_value_obj_uid) {
85fe6060f1SDimitry Andric   m_flags.m_is_synthetic_children_generated =
86fe6060f1SDimitry Andric       parent.m_flags.m_is_synthetic_children_generated;
87480093f4SDimitry Andric   m_data.SetByteOrder(parent.GetDataExtractor().GetByteOrder());
88480093f4SDimitry Andric   m_data.SetAddressByteSize(parent.GetDataExtractor().GetAddressByteSize());
890b57cec5SDimitry Andric   m_manager->ManageObject(this);
900b57cec5SDimitry Andric }
910b57cec5SDimitry Andric 
920b57cec5SDimitry Andric // ValueObject constructor
ValueObject(ExecutionContextScope * exe_scope,ValueObjectManager & manager,AddressType child_ptr_or_ref_addr_type)930b57cec5SDimitry Andric ValueObject::ValueObject(ExecutionContextScope *exe_scope,
945ffd83dbSDimitry Andric                          ValueObjectManager &manager,
950b57cec5SDimitry Andric                          AddressType child_ptr_or_ref_addr_type)
96fe6060f1SDimitry Andric     : m_update_point(exe_scope), m_manager(&manager),
970b57cec5SDimitry Andric       m_address_type_of_ptr_or_ref_children(child_ptr_or_ref_addr_type),
98fe6060f1SDimitry Andric       m_id(++g_value_obj_uid) {
99480093f4SDimitry Andric   if (exe_scope) {
100480093f4SDimitry Andric     TargetSP target_sp(exe_scope->CalculateTarget());
101480093f4SDimitry Andric     if (target_sp) {
102480093f4SDimitry Andric       const ArchSpec &arch = target_sp->GetArchitecture();
103480093f4SDimitry Andric       m_data.SetByteOrder(arch.GetByteOrder());
104480093f4SDimitry Andric       m_data.SetAddressByteSize(arch.GetAddressByteSize());
105480093f4SDimitry Andric     }
106480093f4SDimitry Andric   }
1070b57cec5SDimitry Andric   m_manager->ManageObject(this);
1080b57cec5SDimitry Andric }
1090b57cec5SDimitry Andric 
1100b57cec5SDimitry Andric // Destructor
111fe6060f1SDimitry Andric ValueObject::~ValueObject() = default;
1120b57cec5SDimitry Andric 
UpdateValueIfNeeded(bool update_format)1130b57cec5SDimitry Andric bool ValueObject::UpdateValueIfNeeded(bool update_format) {
1140b57cec5SDimitry Andric 
1150b57cec5SDimitry Andric   bool did_change_formats = false;
1160b57cec5SDimitry Andric 
1170b57cec5SDimitry Andric   if (update_format)
1180b57cec5SDimitry Andric     did_change_formats = UpdateFormatsIfNeeded();
1190b57cec5SDimitry Andric 
1200b57cec5SDimitry Andric   // If this is a constant value, then our success is predicated on whether we
1210b57cec5SDimitry Andric   // have an error or not
1220b57cec5SDimitry Andric   if (GetIsConstant()) {
1230b57cec5SDimitry Andric     // if you are constant, things might still have changed behind your back
1240b57cec5SDimitry Andric     // (e.g. you are a frozen object and things have changed deeper than you
1250b57cec5SDimitry Andric     // cared to freeze-dry yourself) in this case, your value has not changed,
1260b57cec5SDimitry Andric     // but "computed" entries might have, so you might now have a different
1270b57cec5SDimitry Andric     // summary, or a different object description. clear these so we will
1280b57cec5SDimitry Andric     // recompute them
1290b57cec5SDimitry Andric     if (update_format && !did_change_formats)
1300b57cec5SDimitry Andric       ClearUserVisibleData(eClearUserVisibleDataItemsSummary |
1310b57cec5SDimitry Andric                            eClearUserVisibleDataItemsDescription);
1320b57cec5SDimitry Andric     return m_error.Success();
1330b57cec5SDimitry Andric   }
1340b57cec5SDimitry Andric 
1350b57cec5SDimitry Andric   bool first_update = IsChecksumEmpty();
1360b57cec5SDimitry Andric 
1370b57cec5SDimitry Andric   if (NeedsUpdating()) {
1380b57cec5SDimitry Andric     m_update_point.SetUpdated();
1390b57cec5SDimitry Andric 
1400b57cec5SDimitry Andric     // Save the old value using swap to avoid a string copy which also will
1410b57cec5SDimitry Andric     // clear our m_value_str
1420b57cec5SDimitry Andric     if (m_value_str.empty()) {
143fe6060f1SDimitry Andric       m_flags.m_old_value_valid = false;
1440b57cec5SDimitry Andric     } else {
145fe6060f1SDimitry Andric       m_flags.m_old_value_valid = true;
1460b57cec5SDimitry Andric       m_old_value_str.swap(m_value_str);
1470b57cec5SDimitry Andric       ClearUserVisibleData(eClearUserVisibleDataItemsValue);
1480b57cec5SDimitry Andric     }
1490b57cec5SDimitry Andric 
1500b57cec5SDimitry Andric     ClearUserVisibleData();
1510b57cec5SDimitry Andric 
1520b57cec5SDimitry Andric     if (IsInScope()) {
1530b57cec5SDimitry Andric       const bool value_was_valid = GetValueIsValid();
1540b57cec5SDimitry Andric       SetValueDidChange(false);
1550b57cec5SDimitry Andric 
1560b57cec5SDimitry Andric       m_error.Clear();
1570b57cec5SDimitry Andric 
1580b57cec5SDimitry Andric       // Call the pure virtual function to update the value
1590b57cec5SDimitry Andric 
1600b57cec5SDimitry Andric       bool need_compare_checksums = false;
1610b57cec5SDimitry Andric       llvm::SmallVector<uint8_t, 16> old_checksum;
1620b57cec5SDimitry Andric 
1630b57cec5SDimitry Andric       if (!first_update && CanProvideValue()) {
1640b57cec5SDimitry Andric         need_compare_checksums = true;
1650b57cec5SDimitry Andric         old_checksum.resize(m_value_checksum.size());
1660b57cec5SDimitry Andric         std::copy(m_value_checksum.begin(), m_value_checksum.end(),
1670b57cec5SDimitry Andric                   old_checksum.begin());
1680b57cec5SDimitry Andric       }
1690b57cec5SDimitry Andric 
1700b57cec5SDimitry Andric       bool success = UpdateValue();
1710b57cec5SDimitry Andric 
1720b57cec5SDimitry Andric       SetValueIsValid(success);
1730b57cec5SDimitry Andric 
1740b57cec5SDimitry Andric       if (success) {
175480093f4SDimitry Andric         UpdateChildrenAddressType();
1760b57cec5SDimitry Andric         const uint64_t max_checksum_size = 128;
1770b57cec5SDimitry Andric         m_data.Checksum(m_value_checksum, max_checksum_size);
1780b57cec5SDimitry Andric       } else {
1790b57cec5SDimitry Andric         need_compare_checksums = false;
1800b57cec5SDimitry Andric         m_value_checksum.clear();
1810b57cec5SDimitry Andric       }
1820b57cec5SDimitry Andric 
1830b57cec5SDimitry Andric       assert(!need_compare_checksums ||
1840b57cec5SDimitry Andric              (!old_checksum.empty() && !m_value_checksum.empty()));
1850b57cec5SDimitry Andric 
1860b57cec5SDimitry Andric       if (first_update)
1870b57cec5SDimitry Andric         SetValueDidChange(false);
188fe6060f1SDimitry Andric       else if (!m_flags.m_value_did_change && !success) {
1890b57cec5SDimitry Andric         // The value wasn't gotten successfully, so we mark this as changed if
1900b57cec5SDimitry Andric         // the value used to be valid and now isn't
1910b57cec5SDimitry Andric         SetValueDidChange(value_was_valid);
1920b57cec5SDimitry Andric       } else if (need_compare_checksums) {
1930b57cec5SDimitry Andric         SetValueDidChange(memcmp(&old_checksum[0], &m_value_checksum[0],
1940b57cec5SDimitry Andric                                  m_value_checksum.size()));
1950b57cec5SDimitry Andric       }
1960b57cec5SDimitry Andric 
1970b57cec5SDimitry Andric     } else {
1980b57cec5SDimitry Andric       m_error.SetErrorString("out of scope");
1990b57cec5SDimitry Andric     }
2000b57cec5SDimitry Andric   }
2010b57cec5SDimitry Andric   return m_error.Success();
2020b57cec5SDimitry Andric }
2030b57cec5SDimitry Andric 
UpdateFormatsIfNeeded()2040b57cec5SDimitry Andric bool ValueObject::UpdateFormatsIfNeeded() {
20581ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::DataFormatters);
2069dba64beSDimitry Andric   LLDB_LOGF(log,
2079dba64beSDimitry Andric             "[%s %p] checking for FormatManager revisions. ValueObject "
2080b57cec5SDimitry Andric             "rev: %d - Global rev: %d",
2090b57cec5SDimitry Andric             GetName().GetCString(), static_cast<void *>(this),
2100b57cec5SDimitry Andric             m_last_format_mgr_revision,
2110b57cec5SDimitry Andric             DataVisualization::GetCurrentRevision());
2120b57cec5SDimitry Andric 
2130b57cec5SDimitry Andric   bool any_change = false;
2140b57cec5SDimitry Andric 
2150b57cec5SDimitry Andric   if ((m_last_format_mgr_revision != DataVisualization::GetCurrentRevision())) {
2160b57cec5SDimitry Andric     m_last_format_mgr_revision = DataVisualization::GetCurrentRevision();
2170b57cec5SDimitry Andric     any_change = true;
2180b57cec5SDimitry Andric 
2190b57cec5SDimitry Andric     SetValueFormat(DataVisualization::GetFormat(*this, eNoDynamicValues));
2200b57cec5SDimitry Andric     SetSummaryFormat(
2210b57cec5SDimitry Andric         DataVisualization::GetSummaryFormat(*this, GetDynamicValueType()));
2220b57cec5SDimitry Andric     SetSyntheticChildren(
2230b57cec5SDimitry Andric         DataVisualization::GetSyntheticChildren(*this, GetDynamicValueType()));
2240b57cec5SDimitry Andric   }
2250b57cec5SDimitry Andric 
2260b57cec5SDimitry Andric   return any_change;
2270b57cec5SDimitry Andric }
2280b57cec5SDimitry Andric 
SetNeedsUpdate()2290b57cec5SDimitry Andric void ValueObject::SetNeedsUpdate() {
2300b57cec5SDimitry Andric   m_update_point.SetNeedsUpdate();
2310b57cec5SDimitry Andric   // We have to clear the value string here so ConstResult children will notice
2320b57cec5SDimitry Andric   // if their values are changed by hand (i.e. with SetValueAsCString).
2330b57cec5SDimitry Andric   ClearUserVisibleData(eClearUserVisibleDataItemsValue);
2340b57cec5SDimitry Andric }
2350b57cec5SDimitry Andric 
ClearDynamicTypeInformation()2360b57cec5SDimitry Andric void ValueObject::ClearDynamicTypeInformation() {
237fe6060f1SDimitry Andric   m_flags.m_children_count_valid = false;
238fe6060f1SDimitry Andric   m_flags.m_did_calculate_complete_objc_class_type = false;
2390b57cec5SDimitry Andric   m_last_format_mgr_revision = 0;
2400b57cec5SDimitry Andric   m_override_type = CompilerType();
2410b57cec5SDimitry Andric   SetValueFormat(lldb::TypeFormatImplSP());
2420b57cec5SDimitry Andric   SetSummaryFormat(lldb::TypeSummaryImplSP());
2430b57cec5SDimitry Andric   SetSyntheticChildren(lldb::SyntheticChildrenSP());
2440b57cec5SDimitry Andric }
2450b57cec5SDimitry Andric 
MaybeCalculateCompleteType()2460b57cec5SDimitry Andric CompilerType ValueObject::MaybeCalculateCompleteType() {
2470b57cec5SDimitry Andric   CompilerType compiler_type(GetCompilerTypeImpl());
2480b57cec5SDimitry Andric 
249fe6060f1SDimitry Andric   if (m_flags.m_did_calculate_complete_objc_class_type) {
2500b57cec5SDimitry Andric     if (m_override_type.IsValid())
2510b57cec5SDimitry Andric       return m_override_type;
2520b57cec5SDimitry Andric     else
2530b57cec5SDimitry Andric       return compiler_type;
2540b57cec5SDimitry Andric   }
2550b57cec5SDimitry Andric 
256fe6060f1SDimitry Andric   m_flags.m_did_calculate_complete_objc_class_type = true;
2570b57cec5SDimitry Andric 
2580b57cec5SDimitry Andric   ProcessSP process_sp(
2590b57cec5SDimitry Andric       GetUpdatePoint().GetExecutionContextRef().GetProcessSP());
2600b57cec5SDimitry Andric 
2610b57cec5SDimitry Andric   if (!process_sp)
2620b57cec5SDimitry Andric     return compiler_type;
2630b57cec5SDimitry Andric 
2640b57cec5SDimitry Andric   if (auto *runtime =
2650b57cec5SDimitry Andric           process_sp->GetLanguageRuntime(GetObjectRuntimeLanguage())) {
266bdd1243dSDimitry Andric     if (std::optional<CompilerType> complete_type =
2670b57cec5SDimitry Andric             runtime->GetRuntimeType(compiler_type)) {
26881ad6265SDimitry Andric       m_override_type = *complete_type;
2690b57cec5SDimitry Andric       if (m_override_type.IsValid())
2700b57cec5SDimitry Andric         return m_override_type;
2710b57cec5SDimitry Andric     }
2720b57cec5SDimitry Andric   }
2730b57cec5SDimitry Andric   return compiler_type;
2740b57cec5SDimitry Andric }
2750b57cec5SDimitry Andric 
2760b57cec5SDimitry Andric 
2770b57cec5SDimitry Andric 
GetDataExtractor()2780b57cec5SDimitry Andric DataExtractor &ValueObject::GetDataExtractor() {
2790b57cec5SDimitry Andric   UpdateValueIfNeeded(false);
2800b57cec5SDimitry Andric   return m_data;
2810b57cec5SDimitry Andric }
2820b57cec5SDimitry Andric 
GetError()2830b57cec5SDimitry Andric const Status &ValueObject::GetError() {
2840b57cec5SDimitry Andric   UpdateValueIfNeeded(false);
2850b57cec5SDimitry Andric   return m_error;
2860b57cec5SDimitry Andric }
2870b57cec5SDimitry Andric 
GetLocationAsCStringImpl(const Value & value,const DataExtractor & data)2880b57cec5SDimitry Andric const char *ValueObject::GetLocationAsCStringImpl(const Value &value,
2890b57cec5SDimitry Andric                                                   const DataExtractor &data) {
2900b57cec5SDimitry Andric   if (UpdateValueIfNeeded(false)) {
2910b57cec5SDimitry Andric     if (m_location_str.empty()) {
2920b57cec5SDimitry Andric       StreamString sstr;
2930b57cec5SDimitry Andric 
2940b57cec5SDimitry Andric       Value::ValueType value_type = value.GetValueType();
2950b57cec5SDimitry Andric 
2960b57cec5SDimitry Andric       switch (value_type) {
297fe6060f1SDimitry Andric       case Value::ValueType::Invalid:
298fe6060f1SDimitry Andric         m_location_str = "invalid";
299fe6060f1SDimitry Andric         break;
300fe6060f1SDimitry Andric       case Value::ValueType::Scalar:
301fe6060f1SDimitry Andric         if (value.GetContextType() == Value::ContextType::RegisterInfo) {
3020b57cec5SDimitry Andric           RegisterInfo *reg_info = value.GetRegisterInfo();
3030b57cec5SDimitry Andric           if (reg_info) {
3040b57cec5SDimitry Andric             if (reg_info->name)
3050b57cec5SDimitry Andric               m_location_str = reg_info->name;
3060b57cec5SDimitry Andric             else if (reg_info->alt_name)
3070b57cec5SDimitry Andric               m_location_str = reg_info->alt_name;
3080b57cec5SDimitry Andric             if (m_location_str.empty())
3090b57cec5SDimitry Andric               m_location_str = (reg_info->encoding == lldb::eEncodingVector)
3100b57cec5SDimitry Andric                                    ? "vector"
3110b57cec5SDimitry Andric                                    : "scalar";
3120b57cec5SDimitry Andric           }
3130b57cec5SDimitry Andric         }
3140b57cec5SDimitry Andric         if (m_location_str.empty())
315e8d8bef9SDimitry Andric           m_location_str = "scalar";
3160b57cec5SDimitry Andric         break;
3170b57cec5SDimitry Andric 
318fe6060f1SDimitry Andric       case Value::ValueType::LoadAddress:
319fe6060f1SDimitry Andric       case Value::ValueType::FileAddress:
320fe6060f1SDimitry Andric       case Value::ValueType::HostAddress: {
3210b57cec5SDimitry Andric         uint32_t addr_nibble_size = data.GetAddressByteSize() * 2;
3220b57cec5SDimitry Andric         sstr.Printf("0x%*.*llx", addr_nibble_size, addr_nibble_size,
3230b57cec5SDimitry Andric                     value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS));
3245ffd83dbSDimitry Andric         m_location_str = std::string(sstr.GetString());
3250b57cec5SDimitry Andric       } break;
3260b57cec5SDimitry Andric       }
3270b57cec5SDimitry Andric     }
3280b57cec5SDimitry Andric   }
3290b57cec5SDimitry Andric   return m_location_str.c_str();
3300b57cec5SDimitry Andric }
3310b57cec5SDimitry Andric 
ResolveValue(Scalar & scalar)3320b57cec5SDimitry Andric bool ValueObject::ResolveValue(Scalar &scalar) {
3330b57cec5SDimitry Andric   if (UpdateValueIfNeeded(
3340b57cec5SDimitry Andric           false)) // make sure that you are up to date before returning anything
3350b57cec5SDimitry Andric   {
3360b57cec5SDimitry Andric     ExecutionContext exe_ctx(GetExecutionContextRef());
3370b57cec5SDimitry Andric     Value tmp_value(m_value);
338c9157d92SDimitry Andric     scalar = tmp_value.ResolveValue(&exe_ctx, GetModule().get());
3390b57cec5SDimitry Andric     if (scalar.IsValid()) {
3400b57cec5SDimitry Andric       const uint32_t bitfield_bit_size = GetBitfieldBitSize();
3410b57cec5SDimitry Andric       if (bitfield_bit_size)
3420b57cec5SDimitry Andric         return scalar.ExtractBitfield(bitfield_bit_size,
3430b57cec5SDimitry Andric                                       GetBitfieldBitOffset());
3440b57cec5SDimitry Andric       return true;
3450b57cec5SDimitry Andric     }
3460b57cec5SDimitry Andric   }
3470b57cec5SDimitry Andric   return false;
3480b57cec5SDimitry Andric }
3490b57cec5SDimitry Andric 
IsLogicalTrue(Status & error)3500b57cec5SDimitry Andric bool ValueObject::IsLogicalTrue(Status &error) {
3510b57cec5SDimitry Andric   if (Language *language = Language::FindPlugin(GetObjectRuntimeLanguage())) {
3520b57cec5SDimitry Andric     LazyBool is_logical_true = language->IsLogicalTrue(*this, error);
3530b57cec5SDimitry Andric     switch (is_logical_true) {
3540b57cec5SDimitry Andric     case eLazyBoolYes:
3550b57cec5SDimitry Andric     case eLazyBoolNo:
3560b57cec5SDimitry Andric       return (is_logical_true == true);
3570b57cec5SDimitry Andric     case eLazyBoolCalculate:
3580b57cec5SDimitry Andric       break;
3590b57cec5SDimitry Andric     }
3600b57cec5SDimitry Andric   }
3610b57cec5SDimitry Andric 
3620b57cec5SDimitry Andric   Scalar scalar_value;
3630b57cec5SDimitry Andric 
3640b57cec5SDimitry Andric   if (!ResolveValue(scalar_value)) {
3650b57cec5SDimitry Andric     error.SetErrorString("failed to get a scalar result");
3660b57cec5SDimitry Andric     return false;
3670b57cec5SDimitry Andric   }
3680b57cec5SDimitry Andric 
3690b57cec5SDimitry Andric   bool ret;
3700b57cec5SDimitry Andric   ret = scalar_value.ULongLong(1) != 0;
3710b57cec5SDimitry Andric   error.Clear();
3720b57cec5SDimitry Andric   return ret;
3730b57cec5SDimitry Andric }
3740b57cec5SDimitry Andric 
GetChildAtIndex(size_t idx,bool can_create)3750b57cec5SDimitry Andric ValueObjectSP ValueObject::GetChildAtIndex(size_t idx, bool can_create) {
3760b57cec5SDimitry Andric   ValueObjectSP child_sp;
3770b57cec5SDimitry Andric   // We may need to update our value if we are dynamic
3780b57cec5SDimitry Andric   if (IsPossibleDynamicType())
3790b57cec5SDimitry Andric     UpdateValueIfNeeded(false);
3800b57cec5SDimitry Andric   if (idx < GetNumChildren()) {
3810b57cec5SDimitry Andric     // Check if we have already made the child value object?
3820b57cec5SDimitry Andric     if (can_create && !m_children.HasChildAtIndex(idx)) {
3830b57cec5SDimitry Andric       // No we haven't created the child at this index, so lets have our
3840b57cec5SDimitry Andric       // subclass do it and cache the result for quick future access.
3850b57cec5SDimitry Andric       m_children.SetChildAtIndex(idx, CreateChildAtIndex(idx, false, 0));
3860b57cec5SDimitry Andric     }
3870b57cec5SDimitry Andric 
3880b57cec5SDimitry Andric     ValueObject *child = m_children.GetChildAtIndex(idx);
3890b57cec5SDimitry Andric     if (child != nullptr)
3900b57cec5SDimitry Andric       return child->GetSP();
3910b57cec5SDimitry Andric   }
3920b57cec5SDimitry Andric   return child_sp;
3930b57cec5SDimitry Andric }
3940b57cec5SDimitry Andric 
3950b57cec5SDimitry Andric lldb::ValueObjectSP
GetChildAtNamePath(llvm::ArrayRef<llvm::StringRef> names)396fe013be4SDimitry Andric ValueObject::GetChildAtNamePath(llvm::ArrayRef<llvm::StringRef> names) {
3970b57cec5SDimitry Andric   if (names.size() == 0)
3980b57cec5SDimitry Andric     return GetSP();
3990b57cec5SDimitry Andric   ValueObjectSP root(GetSP());
400fe013be4SDimitry Andric   for (llvm::StringRef name : names) {
401fe013be4SDimitry Andric     root = root->GetChildMemberWithName(name);
4020b57cec5SDimitry Andric     if (!root) {
4030b57cec5SDimitry Andric       return root;
4040b57cec5SDimitry Andric     }
4050b57cec5SDimitry Andric   }
4060b57cec5SDimitry Andric   return root;
4070b57cec5SDimitry Andric }
4080b57cec5SDimitry Andric 
GetIndexOfChildWithName(llvm::StringRef name)409fe013be4SDimitry Andric size_t ValueObject::GetIndexOfChildWithName(llvm::StringRef name) {
4100b57cec5SDimitry Andric   bool omit_empty_base_classes = true;
411fe013be4SDimitry Andric   return GetCompilerType().GetIndexOfChildWithName(name,
4120b57cec5SDimitry Andric                                                    omit_empty_base_classes);
4130b57cec5SDimitry Andric }
4140b57cec5SDimitry Andric 
GetChildMemberWithName(llvm::StringRef name,bool can_create)415fe013be4SDimitry Andric ValueObjectSP ValueObject::GetChildMemberWithName(llvm::StringRef name,
4160b57cec5SDimitry Andric                                                   bool can_create) {
4175ffd83dbSDimitry Andric   // We may need to update our value if we are dynamic.
4180b57cec5SDimitry Andric   if (IsPossibleDynamicType())
4190b57cec5SDimitry Andric     UpdateValueIfNeeded(false);
4200b57cec5SDimitry Andric 
4215ffd83dbSDimitry Andric   // When getting a child by name, it could be buried inside some base classes
4225ffd83dbSDimitry Andric   // (which really aren't part of the expression path), so we need a vector of
4235ffd83dbSDimitry Andric   // indexes that can get us down to the correct child.
4240b57cec5SDimitry Andric   std::vector<uint32_t> child_indexes;
4250b57cec5SDimitry Andric   bool omit_empty_base_classes = true;
426480093f4SDimitry Andric 
427480093f4SDimitry Andric   if (!GetCompilerType().IsValid())
428480093f4SDimitry Andric     return ValueObjectSP();
429480093f4SDimitry Andric 
4300b57cec5SDimitry Andric   const size_t num_child_indexes =
4310b57cec5SDimitry Andric       GetCompilerType().GetIndexOfChildMemberWithName(
432fe013be4SDimitry Andric           name, omit_empty_base_classes, child_indexes);
4335ffd83dbSDimitry Andric   if (num_child_indexes == 0)
4345ffd83dbSDimitry Andric     return nullptr;
4350b57cec5SDimitry Andric 
4365ffd83dbSDimitry Andric   ValueObjectSP child_sp = GetSP();
4375ffd83dbSDimitry Andric   for (uint32_t idx : child_indexes)
4385ffd83dbSDimitry Andric     if (child_sp)
4395ffd83dbSDimitry Andric       child_sp = child_sp->GetChildAtIndex(idx, can_create);
4400b57cec5SDimitry Andric   return child_sp;
4410b57cec5SDimitry Andric }
4420b57cec5SDimitry Andric 
GetNumChildren(uint32_t max)4430b57cec5SDimitry Andric size_t ValueObject::GetNumChildren(uint32_t max) {
4440b57cec5SDimitry Andric   UpdateValueIfNeeded();
4450b57cec5SDimitry Andric 
4460b57cec5SDimitry Andric   if (max < UINT32_MAX) {
447fe6060f1SDimitry Andric     if (m_flags.m_children_count_valid) {
4480b57cec5SDimitry Andric       size_t children_count = m_children.GetChildrenCount();
4490b57cec5SDimitry Andric       return children_count <= max ? children_count : max;
4500b57cec5SDimitry Andric     } else
4510b57cec5SDimitry Andric       return CalculateNumChildren(max);
4520b57cec5SDimitry Andric   }
4530b57cec5SDimitry Andric 
454fe6060f1SDimitry Andric   if (!m_flags.m_children_count_valid) {
4550b57cec5SDimitry Andric     SetNumChildren(CalculateNumChildren());
4560b57cec5SDimitry Andric   }
4570b57cec5SDimitry Andric   return m_children.GetChildrenCount();
4580b57cec5SDimitry Andric }
4590b57cec5SDimitry Andric 
MightHaveChildren()4600b57cec5SDimitry Andric bool ValueObject::MightHaveChildren() {
4610b57cec5SDimitry Andric   bool has_children = false;
4620b57cec5SDimitry Andric   const uint32_t type_info = GetTypeInfo();
4630b57cec5SDimitry Andric   if (type_info) {
4640b57cec5SDimitry Andric     if (type_info & (eTypeHasChildren | eTypeIsPointer | eTypeIsReference))
4650b57cec5SDimitry Andric       has_children = true;
4660b57cec5SDimitry Andric   } else {
4670b57cec5SDimitry Andric     has_children = GetNumChildren() > 0;
4680b57cec5SDimitry Andric   }
4690b57cec5SDimitry Andric   return has_children;
4700b57cec5SDimitry Andric }
4710b57cec5SDimitry Andric 
4720b57cec5SDimitry Andric // Should only be called by ValueObject::GetNumChildren()
SetNumChildren(size_t num_children)4730b57cec5SDimitry Andric void ValueObject::SetNumChildren(size_t num_children) {
474fe6060f1SDimitry Andric   m_flags.m_children_count_valid = true;
4750b57cec5SDimitry Andric   m_children.SetChildrenCount(num_children);
4760b57cec5SDimitry Andric }
4770b57cec5SDimitry Andric 
CreateChildAtIndex(size_t idx,bool synthetic_array_member,int32_t synthetic_index)4780b57cec5SDimitry Andric ValueObject *ValueObject::CreateChildAtIndex(size_t idx,
4790b57cec5SDimitry Andric                                              bool synthetic_array_member,
4800b57cec5SDimitry Andric                                              int32_t synthetic_index) {
4810b57cec5SDimitry Andric   ValueObject *valobj = nullptr;
4820b57cec5SDimitry Andric 
4830b57cec5SDimitry Andric   bool omit_empty_base_classes = true;
4840b57cec5SDimitry Andric   bool ignore_array_bounds = synthetic_array_member;
4850b57cec5SDimitry Andric   std::string child_name_str;
4860b57cec5SDimitry Andric   uint32_t child_byte_size = 0;
4870b57cec5SDimitry Andric   int32_t child_byte_offset = 0;
4880b57cec5SDimitry Andric   uint32_t child_bitfield_bit_size = 0;
4890b57cec5SDimitry Andric   uint32_t child_bitfield_bit_offset = 0;
4900b57cec5SDimitry Andric   bool child_is_base_class = false;
4910b57cec5SDimitry Andric   bool child_is_deref_of_parent = false;
4920b57cec5SDimitry Andric   uint64_t language_flags = 0;
4930b57cec5SDimitry Andric 
4940b57cec5SDimitry Andric   const bool transparent_pointers = !synthetic_array_member;
4950b57cec5SDimitry Andric   CompilerType child_compiler_type;
4960b57cec5SDimitry Andric 
4970b57cec5SDimitry Andric   ExecutionContext exe_ctx(GetExecutionContextRef());
4980b57cec5SDimitry Andric 
4990b57cec5SDimitry Andric   child_compiler_type = GetCompilerType().GetChildCompilerTypeAtIndex(
5000b57cec5SDimitry Andric       &exe_ctx, idx, transparent_pointers, omit_empty_base_classes,
5010b57cec5SDimitry Andric       ignore_array_bounds, child_name_str, child_byte_size, child_byte_offset,
5020b57cec5SDimitry Andric       child_bitfield_bit_size, child_bitfield_bit_offset, child_is_base_class,
5030b57cec5SDimitry Andric       child_is_deref_of_parent, this, language_flags);
5040b57cec5SDimitry Andric   if (child_compiler_type) {
5050b57cec5SDimitry Andric     if (synthetic_index)
5060b57cec5SDimitry Andric       child_byte_offset += child_byte_size * synthetic_index;
5070b57cec5SDimitry Andric 
5080b57cec5SDimitry Andric     ConstString child_name;
5090b57cec5SDimitry Andric     if (!child_name_str.empty())
5100b57cec5SDimitry Andric       child_name.SetCString(child_name_str.c_str());
5110b57cec5SDimitry Andric 
5120b57cec5SDimitry Andric     valobj = new ValueObjectChild(
5130b57cec5SDimitry Andric         *this, child_compiler_type, child_name, child_byte_size,
5140b57cec5SDimitry Andric         child_byte_offset, child_bitfield_bit_size, child_bitfield_bit_offset,
5150b57cec5SDimitry Andric         child_is_base_class, child_is_deref_of_parent, eAddressTypeInvalid,
5160b57cec5SDimitry Andric         language_flags);
5170b57cec5SDimitry Andric   }
5180b57cec5SDimitry Andric 
5195ffd83dbSDimitry Andric   // In case of an incomplete type, try to use the ValueObject's
5205ffd83dbSDimitry Andric   // synthetic value to create the child ValueObject.
5215ffd83dbSDimitry Andric   if (!valobj && synthetic_array_member) {
5225ffd83dbSDimitry Andric     if (ValueObjectSP synth_valobj_sp = GetSyntheticValue()) {
5235ffd83dbSDimitry Andric       valobj = synth_valobj_sp
5245ffd83dbSDimitry Andric                    ->GetChildAtIndex(synthetic_index, synthetic_array_member)
5255ffd83dbSDimitry Andric                    .get();
5265ffd83dbSDimitry Andric     }
5275ffd83dbSDimitry Andric   }
5285ffd83dbSDimitry Andric 
5290b57cec5SDimitry Andric   return valobj;
5300b57cec5SDimitry Andric }
5310b57cec5SDimitry Andric 
GetSummaryAsCString(TypeSummaryImpl * summary_ptr,std::string & destination,lldb::LanguageType lang)5320b57cec5SDimitry Andric bool ValueObject::GetSummaryAsCString(TypeSummaryImpl *summary_ptr,
5330b57cec5SDimitry Andric                                       std::string &destination,
5340b57cec5SDimitry Andric                                       lldb::LanguageType lang) {
5350b57cec5SDimitry Andric   return GetSummaryAsCString(summary_ptr, destination,
5360b57cec5SDimitry Andric                              TypeSummaryOptions().SetLanguage(lang));
5370b57cec5SDimitry Andric }
5380b57cec5SDimitry Andric 
GetSummaryAsCString(TypeSummaryImpl * summary_ptr,std::string & destination,const TypeSummaryOptions & options)5390b57cec5SDimitry Andric bool ValueObject::GetSummaryAsCString(TypeSummaryImpl *summary_ptr,
5400b57cec5SDimitry Andric                                       std::string &destination,
5410b57cec5SDimitry Andric                                       const TypeSummaryOptions &options) {
5420b57cec5SDimitry Andric   destination.clear();
5430b57cec5SDimitry Andric 
544bdd1243dSDimitry Andric   // If we have a forcefully completed type, don't try and show a summary from
545bdd1243dSDimitry Andric   // a valid summary string or function because the type is not complete and
546bdd1243dSDimitry Andric   // no member variables or member functions will be available.
547bdd1243dSDimitry Andric   if (GetCompilerType().IsForcefullyCompleted()) {
548bdd1243dSDimitry Andric       destination = "<incomplete type>";
549bdd1243dSDimitry Andric       return true;
550bdd1243dSDimitry Andric   }
551bdd1243dSDimitry Andric 
5520b57cec5SDimitry Andric   // ideally we would like to bail out if passing NULL, but if we do so we end
5530b57cec5SDimitry Andric   // up not providing the summary for function pointers anymore
554fe6060f1SDimitry Andric   if (/*summary_ptr == NULL ||*/ m_flags.m_is_getting_summary)
5550b57cec5SDimitry Andric     return false;
5560b57cec5SDimitry Andric 
557fe6060f1SDimitry Andric   m_flags.m_is_getting_summary = true;
5580b57cec5SDimitry Andric 
5590b57cec5SDimitry Andric   TypeSummaryOptions actual_options(options);
5600b57cec5SDimitry Andric 
5610b57cec5SDimitry Andric   if (actual_options.GetLanguage() == lldb::eLanguageTypeUnknown)
5620b57cec5SDimitry Andric     actual_options.SetLanguage(GetPreferredDisplayLanguage());
5630b57cec5SDimitry Andric 
5640b57cec5SDimitry Andric   // this is a hot path in code and we prefer to avoid setting this string all
5650b57cec5SDimitry Andric   // too often also clearing out other information that we might care to see in
5660b57cec5SDimitry Andric   // a crash log. might be useful in very specific situations though.
5670b57cec5SDimitry Andric   /*Host::SetCrashDescriptionWithFormat("Trying to fetch a summary for %s %s.
5680b57cec5SDimitry Andric    Summary provider's description is %s",
5690b57cec5SDimitry Andric    GetTypeName().GetCString(),
5700b57cec5SDimitry Andric    GetName().GetCString(),
5710b57cec5SDimitry Andric    summary_ptr->GetDescription().c_str());*/
5720b57cec5SDimitry Andric 
5730b57cec5SDimitry Andric   if (UpdateValueIfNeeded(false) && summary_ptr) {
5740b57cec5SDimitry Andric     if (HasSyntheticValue())
5750b57cec5SDimitry Andric       m_synthetic_value->UpdateValueIfNeeded(); // the summary might depend on
5760b57cec5SDimitry Andric                                                 // the synthetic children being
5770b57cec5SDimitry Andric                                                 // up-to-date (e.g. ${svar%#})
5780b57cec5SDimitry Andric     summary_ptr->FormatObject(this, destination, actual_options);
5790b57cec5SDimitry Andric   }
580fe6060f1SDimitry Andric   m_flags.m_is_getting_summary = false;
5810b57cec5SDimitry Andric   return !destination.empty();
5820b57cec5SDimitry Andric }
5830b57cec5SDimitry Andric 
GetSummaryAsCString(lldb::LanguageType lang)5840b57cec5SDimitry Andric const char *ValueObject::GetSummaryAsCString(lldb::LanguageType lang) {
5850b57cec5SDimitry Andric   if (UpdateValueIfNeeded(true) && m_summary_str.empty()) {
5860b57cec5SDimitry Andric     TypeSummaryOptions summary_options;
5870b57cec5SDimitry Andric     summary_options.SetLanguage(lang);
5880b57cec5SDimitry Andric     GetSummaryAsCString(GetSummaryFormat().get(), m_summary_str,
5890b57cec5SDimitry Andric                         summary_options);
5900b57cec5SDimitry Andric   }
5910b57cec5SDimitry Andric   if (m_summary_str.empty())
5920b57cec5SDimitry Andric     return nullptr;
5930b57cec5SDimitry Andric   return m_summary_str.c_str();
5940b57cec5SDimitry Andric }
5950b57cec5SDimitry Andric 
GetSummaryAsCString(std::string & destination,const TypeSummaryOptions & options)5960b57cec5SDimitry Andric bool ValueObject::GetSummaryAsCString(std::string &destination,
5970b57cec5SDimitry Andric                                       const TypeSummaryOptions &options) {
5980b57cec5SDimitry Andric   return GetSummaryAsCString(GetSummaryFormat().get(), destination, options);
5990b57cec5SDimitry Andric }
6000b57cec5SDimitry Andric 
IsCStringContainer(bool check_pointer)6010b57cec5SDimitry Andric bool ValueObject::IsCStringContainer(bool check_pointer) {
6020b57cec5SDimitry Andric   CompilerType pointee_or_element_compiler_type;
6030b57cec5SDimitry Andric   const Flags type_flags(GetTypeInfo(&pointee_or_element_compiler_type));
6040b57cec5SDimitry Andric   bool is_char_arr_ptr(type_flags.AnySet(eTypeIsArray | eTypeIsPointer) &&
6050b57cec5SDimitry Andric                        pointee_or_element_compiler_type.IsCharType());
6060b57cec5SDimitry Andric   if (!is_char_arr_ptr)
6070b57cec5SDimitry Andric     return false;
6080b57cec5SDimitry Andric   if (!check_pointer)
6090b57cec5SDimitry Andric     return true;
6100b57cec5SDimitry Andric   if (type_flags.Test(eTypeIsArray))
6110b57cec5SDimitry Andric     return true;
6120b57cec5SDimitry Andric   addr_t cstr_address = LLDB_INVALID_ADDRESS;
6130b57cec5SDimitry Andric   AddressType cstr_address_type = eAddressTypeInvalid;
6145ffd83dbSDimitry Andric   cstr_address = GetPointerValue(&cstr_address_type);
6150b57cec5SDimitry Andric   return (cstr_address != LLDB_INVALID_ADDRESS);
6160b57cec5SDimitry Andric }
6170b57cec5SDimitry Andric 
GetPointeeData(DataExtractor & data,uint32_t item_idx,uint32_t item_count)6180b57cec5SDimitry Andric size_t ValueObject::GetPointeeData(DataExtractor &data, uint32_t item_idx,
6190b57cec5SDimitry Andric                                    uint32_t item_count) {
6200b57cec5SDimitry Andric   CompilerType pointee_or_element_compiler_type;
6210b57cec5SDimitry Andric   const uint32_t type_info = GetTypeInfo(&pointee_or_element_compiler_type);
6220b57cec5SDimitry Andric   const bool is_pointer_type = type_info & eTypeIsPointer;
6230b57cec5SDimitry Andric   const bool is_array_type = type_info & eTypeIsArray;
6240b57cec5SDimitry Andric   if (!(is_pointer_type || is_array_type))
6250b57cec5SDimitry Andric     return 0;
6260b57cec5SDimitry Andric 
6270b57cec5SDimitry Andric   if (item_count == 0)
6280b57cec5SDimitry Andric     return 0;
6290b57cec5SDimitry Andric 
6300b57cec5SDimitry Andric   ExecutionContext exe_ctx(GetExecutionContextRef());
6310b57cec5SDimitry Andric 
632bdd1243dSDimitry Andric   std::optional<uint64_t> item_type_size =
6330b57cec5SDimitry Andric       pointee_or_element_compiler_type.GetByteSize(
6340b57cec5SDimitry Andric           exe_ctx.GetBestExecutionContextScope());
6350b57cec5SDimitry Andric   if (!item_type_size)
6360b57cec5SDimitry Andric     return 0;
6370b57cec5SDimitry Andric   const uint64_t bytes = item_count * *item_type_size;
6380b57cec5SDimitry Andric   const uint64_t offset = item_idx * *item_type_size;
6390b57cec5SDimitry Andric 
6400b57cec5SDimitry Andric   if (item_idx == 0 && item_count == 1) // simply a deref
6410b57cec5SDimitry Andric   {
6420b57cec5SDimitry Andric     if (is_pointer_type) {
6430b57cec5SDimitry Andric       Status error;
6440b57cec5SDimitry Andric       ValueObjectSP pointee_sp = Dereference(error);
6450b57cec5SDimitry Andric       if (error.Fail() || pointee_sp.get() == nullptr)
6460b57cec5SDimitry Andric         return 0;
6470b57cec5SDimitry Andric       return pointee_sp->GetData(data, error);
6480b57cec5SDimitry Andric     } else {
649fe013be4SDimitry Andric       ValueObjectSP child_sp = GetChildAtIndex(0);
6500b57cec5SDimitry Andric       if (child_sp.get() == nullptr)
6510b57cec5SDimitry Andric         return 0;
6520b57cec5SDimitry Andric       Status error;
6530b57cec5SDimitry Andric       return child_sp->GetData(data, error);
6540b57cec5SDimitry Andric     }
6550b57cec5SDimitry Andric     return true;
6560b57cec5SDimitry Andric   } else /* (items > 1) */
6570b57cec5SDimitry Andric   {
6580b57cec5SDimitry Andric     Status error;
6590b57cec5SDimitry Andric     lldb_private::DataBufferHeap *heap_buf_ptr = nullptr;
6600b57cec5SDimitry Andric     lldb::DataBufferSP data_sp(heap_buf_ptr =
6610b57cec5SDimitry Andric                                    new lldb_private::DataBufferHeap());
6620b57cec5SDimitry Andric 
6630b57cec5SDimitry Andric     AddressType addr_type;
6640b57cec5SDimitry Andric     lldb::addr_t addr = is_pointer_type ? GetPointerValue(&addr_type)
6650b57cec5SDimitry Andric                                         : GetAddressOf(true, &addr_type);
6660b57cec5SDimitry Andric 
6670b57cec5SDimitry Andric     switch (addr_type) {
6680b57cec5SDimitry Andric     case eAddressTypeFile: {
6690b57cec5SDimitry Andric       ModuleSP module_sp(GetModule());
6700b57cec5SDimitry Andric       if (module_sp) {
6710b57cec5SDimitry Andric         addr = addr + offset;
6720b57cec5SDimitry Andric         Address so_addr;
6730b57cec5SDimitry Andric         module_sp->ResolveFileAddress(addr, so_addr);
6740b57cec5SDimitry Andric         ExecutionContext exe_ctx(GetExecutionContextRef());
6750b57cec5SDimitry Andric         Target *target = exe_ctx.GetTargetPtr();
6760b57cec5SDimitry Andric         if (target) {
6770b57cec5SDimitry Andric           heap_buf_ptr->SetByteSize(bytes);
6780b57cec5SDimitry Andric           size_t bytes_read = target->ReadMemory(
679fe6060f1SDimitry Andric               so_addr, heap_buf_ptr->GetBytes(), bytes, error, true);
6800b57cec5SDimitry Andric           if (error.Success()) {
6810b57cec5SDimitry Andric             data.SetData(data_sp);
6820b57cec5SDimitry Andric             return bytes_read;
6830b57cec5SDimitry Andric           }
6840b57cec5SDimitry Andric         }
6850b57cec5SDimitry Andric       }
6860b57cec5SDimitry Andric     } break;
6870b57cec5SDimitry Andric     case eAddressTypeLoad: {
6880b57cec5SDimitry Andric       ExecutionContext exe_ctx(GetExecutionContextRef());
6890b57cec5SDimitry Andric       Process *process = exe_ctx.GetProcessPtr();
6900b57cec5SDimitry Andric       if (process) {
6910b57cec5SDimitry Andric         heap_buf_ptr->SetByteSize(bytes);
6920b57cec5SDimitry Andric         size_t bytes_read = process->ReadMemory(
6930b57cec5SDimitry Andric             addr + offset, heap_buf_ptr->GetBytes(), bytes, error);
6940b57cec5SDimitry Andric         if (error.Success() || bytes_read > 0) {
6950b57cec5SDimitry Andric           data.SetData(data_sp);
6960b57cec5SDimitry Andric           return bytes_read;
6970b57cec5SDimitry Andric         }
6980b57cec5SDimitry Andric       }
6990b57cec5SDimitry Andric     } break;
7000b57cec5SDimitry Andric     case eAddressTypeHost: {
7010b57cec5SDimitry Andric       auto max_bytes =
7020b57cec5SDimitry Andric           GetCompilerType().GetByteSize(exe_ctx.GetBestExecutionContextScope());
7030b57cec5SDimitry Andric       if (max_bytes && *max_bytes > offset) {
7040b57cec5SDimitry Andric         size_t bytes_read = std::min<uint64_t>(*max_bytes - offset, bytes);
7050b57cec5SDimitry Andric         addr = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
7060b57cec5SDimitry Andric         if (addr == 0 || addr == LLDB_INVALID_ADDRESS)
7070b57cec5SDimitry Andric           break;
7080b57cec5SDimitry Andric         heap_buf_ptr->CopyData((uint8_t *)(addr + offset), bytes_read);
7090b57cec5SDimitry Andric         data.SetData(data_sp);
7100b57cec5SDimitry Andric         return bytes_read;
7110b57cec5SDimitry Andric       }
7120b57cec5SDimitry Andric     } break;
7130b57cec5SDimitry Andric     case eAddressTypeInvalid:
7140b57cec5SDimitry Andric       break;
7150b57cec5SDimitry Andric     }
7160b57cec5SDimitry Andric   }
7170b57cec5SDimitry Andric   return 0;
7180b57cec5SDimitry Andric }
7190b57cec5SDimitry Andric 
GetData(DataExtractor & data,Status & error)7200b57cec5SDimitry Andric uint64_t ValueObject::GetData(DataExtractor &data, Status &error) {
7210b57cec5SDimitry Andric   UpdateValueIfNeeded(false);
7220b57cec5SDimitry Andric   ExecutionContext exe_ctx(GetExecutionContextRef());
7239dba64beSDimitry Andric   error = m_value.GetValueAsData(&exe_ctx, data, GetModule().get());
7240b57cec5SDimitry Andric   if (error.Fail()) {
7250b57cec5SDimitry Andric     if (m_data.GetByteSize()) {
7260b57cec5SDimitry Andric       data = m_data;
7270b57cec5SDimitry Andric       error.Clear();
7280b57cec5SDimitry Andric       return data.GetByteSize();
7290b57cec5SDimitry Andric     } else {
7300b57cec5SDimitry Andric       return 0;
7310b57cec5SDimitry Andric     }
7320b57cec5SDimitry Andric   }
7330b57cec5SDimitry Andric   data.SetAddressByteSize(m_data.GetAddressByteSize());
7340b57cec5SDimitry Andric   data.SetByteOrder(m_data.GetByteOrder());
7350b57cec5SDimitry Andric   return data.GetByteSize();
7360b57cec5SDimitry Andric }
7370b57cec5SDimitry Andric 
SetData(DataExtractor & data,Status & error)7380b57cec5SDimitry Andric bool ValueObject::SetData(DataExtractor &data, Status &error) {
7390b57cec5SDimitry Andric   error.Clear();
7400b57cec5SDimitry Andric   // Make sure our value is up to date first so that our location and location
7410b57cec5SDimitry Andric   // type is valid.
7420b57cec5SDimitry Andric   if (!UpdateValueIfNeeded(false)) {
7430b57cec5SDimitry Andric     error.SetErrorString("unable to read value");
7440b57cec5SDimitry Andric     return false;
7450b57cec5SDimitry Andric   }
7460b57cec5SDimitry Andric 
7470b57cec5SDimitry Andric   uint64_t count = 0;
7480b57cec5SDimitry Andric   const Encoding encoding = GetCompilerType().GetEncoding(count);
7490b57cec5SDimitry Andric 
75081ad6265SDimitry Andric   const size_t byte_size = GetByteSize().value_or(0);
7510b57cec5SDimitry Andric 
7520b57cec5SDimitry Andric   Value::ValueType value_type = m_value.GetValueType();
7530b57cec5SDimitry Andric 
7540b57cec5SDimitry Andric   switch (value_type) {
755fe6060f1SDimitry Andric   case Value::ValueType::Invalid:
756fe6060f1SDimitry Andric     error.SetErrorString("invalid location");
757fe6060f1SDimitry Andric     return false;
758fe6060f1SDimitry Andric   case Value::ValueType::Scalar: {
7590b57cec5SDimitry Andric     Status set_error =
7600b57cec5SDimitry Andric         m_value.GetScalar().SetValueFromData(data, encoding, byte_size);
7610b57cec5SDimitry Andric 
7620b57cec5SDimitry Andric     if (!set_error.Success()) {
7630b57cec5SDimitry Andric       error.SetErrorStringWithFormat("unable to set scalar value: %s",
7640b57cec5SDimitry Andric                                      set_error.AsCString());
7650b57cec5SDimitry Andric       return false;
7660b57cec5SDimitry Andric     }
7670b57cec5SDimitry Andric   } break;
768fe6060f1SDimitry Andric   case Value::ValueType::LoadAddress: {
7690b57cec5SDimitry Andric     // If it is a load address, then the scalar value is the storage location
7700b57cec5SDimitry Andric     // of the data, and we have to shove this value down to that load location.
7710b57cec5SDimitry Andric     ExecutionContext exe_ctx(GetExecutionContextRef());
7720b57cec5SDimitry Andric     Process *process = exe_ctx.GetProcessPtr();
7730b57cec5SDimitry Andric     if (process) {
7740b57cec5SDimitry Andric       addr_t target_addr = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
7750b57cec5SDimitry Andric       size_t bytes_written = process->WriteMemory(
7760b57cec5SDimitry Andric           target_addr, data.GetDataStart(), byte_size, error);
7770b57cec5SDimitry Andric       if (!error.Success())
7780b57cec5SDimitry Andric         return false;
7790b57cec5SDimitry Andric       if (bytes_written != byte_size) {
7800b57cec5SDimitry Andric         error.SetErrorString("unable to write value to memory");
7810b57cec5SDimitry Andric         return false;
7820b57cec5SDimitry Andric       }
7830b57cec5SDimitry Andric     }
7840b57cec5SDimitry Andric   } break;
785fe6060f1SDimitry Andric   case Value::ValueType::HostAddress: {
7860b57cec5SDimitry Andric     // If it is a host address, then we stuff the scalar as a DataBuffer into
7870b57cec5SDimitry Andric     // the Value's data.
7880b57cec5SDimitry Andric     DataBufferSP buffer_sp(new DataBufferHeap(byte_size, 0));
7890b57cec5SDimitry Andric     m_data.SetData(buffer_sp, 0);
7900b57cec5SDimitry Andric     data.CopyByteOrderedData(0, byte_size,
7910b57cec5SDimitry Andric                              const_cast<uint8_t *>(m_data.GetDataStart()),
7920b57cec5SDimitry Andric                              byte_size, m_data.GetByteOrder());
7930b57cec5SDimitry Andric     m_value.GetScalar() = (uintptr_t)m_data.GetDataStart();
7940b57cec5SDimitry Andric   } break;
795fe6060f1SDimitry Andric   case Value::ValueType::FileAddress:
7960b57cec5SDimitry Andric     break;
7970b57cec5SDimitry Andric   }
7980b57cec5SDimitry Andric 
7990b57cec5SDimitry Andric   // If we have reached this point, then we have successfully changed the
8000b57cec5SDimitry Andric   // value.
8010b57cec5SDimitry Andric   SetNeedsUpdate();
8020b57cec5SDimitry Andric   return true;
8030b57cec5SDimitry Andric }
8040b57cec5SDimitry Andric 
CopyStringDataToBufferSP(const StreamString & source,lldb::WritableDataBufferSP & destination)8050b57cec5SDimitry Andric static bool CopyStringDataToBufferSP(const StreamString &source,
80681ad6265SDimitry Andric                                      lldb::WritableDataBufferSP &destination) {
807349cc55cSDimitry Andric   llvm::StringRef src = source.GetString();
80881ad6265SDimitry Andric   src = src.rtrim('\0');
809349cc55cSDimitry Andric   destination = std::make_shared<DataBufferHeap>(src.size(), 0);
810349cc55cSDimitry Andric   memcpy(destination->GetBytes(), src.data(), src.size());
8110b57cec5SDimitry Andric   return true;
8120b57cec5SDimitry Andric }
8130b57cec5SDimitry Andric 
8140b57cec5SDimitry Andric std::pair<size_t, bool>
ReadPointedString(lldb::WritableDataBufferSP & buffer_sp,Status & error,bool honor_array)81581ad6265SDimitry Andric ValueObject::ReadPointedString(lldb::WritableDataBufferSP &buffer_sp,
816*a58f00eaSDimitry Andric                                Status &error, bool honor_array) {
8170b57cec5SDimitry Andric   bool was_capped = false;
8180b57cec5SDimitry Andric   StreamString s;
8190b57cec5SDimitry Andric   ExecutionContext exe_ctx(GetExecutionContextRef());
8200b57cec5SDimitry Andric   Target *target = exe_ctx.GetTargetPtr();
8210b57cec5SDimitry Andric 
8220b57cec5SDimitry Andric   if (!target) {
8230b57cec5SDimitry Andric     s << "<no target to read from>";
8240b57cec5SDimitry Andric     error.SetErrorString("no target to read from");
8250b57cec5SDimitry Andric     CopyStringDataToBufferSP(s, buffer_sp);
8260b57cec5SDimitry Andric     return {0, was_capped};
8270b57cec5SDimitry Andric   }
8280b57cec5SDimitry Andric 
829*a58f00eaSDimitry Andric   const auto max_length = target->GetMaximumSizeOfStringSummary();
8300b57cec5SDimitry Andric 
8310b57cec5SDimitry Andric   size_t bytes_read = 0;
8320b57cec5SDimitry Andric   size_t total_bytes_read = 0;
8330b57cec5SDimitry Andric 
8340b57cec5SDimitry Andric   CompilerType compiler_type = GetCompilerType();
8350b57cec5SDimitry Andric   CompilerType elem_or_pointee_compiler_type;
8360b57cec5SDimitry Andric   const Flags type_flags(GetTypeInfo(&elem_or_pointee_compiler_type));
8370b57cec5SDimitry Andric   if (type_flags.AnySet(eTypeIsArray | eTypeIsPointer) &&
8380b57cec5SDimitry Andric       elem_or_pointee_compiler_type.IsCharType()) {
8390b57cec5SDimitry Andric     addr_t cstr_address = LLDB_INVALID_ADDRESS;
8400b57cec5SDimitry Andric     AddressType cstr_address_type = eAddressTypeInvalid;
8410b57cec5SDimitry Andric 
8420b57cec5SDimitry Andric     size_t cstr_len = 0;
8430b57cec5SDimitry Andric     bool capped_data = false;
8440b57cec5SDimitry Andric     const bool is_array = type_flags.Test(eTypeIsArray);
8450b57cec5SDimitry Andric     if (is_array) {
8460b57cec5SDimitry Andric       // We have an array
8470b57cec5SDimitry Andric       uint64_t array_size = 0;
848fe6060f1SDimitry Andric       if (compiler_type.IsArrayType(nullptr, &array_size)) {
8490b57cec5SDimitry Andric         cstr_len = array_size;
8500b57cec5SDimitry Andric         if (cstr_len > max_length) {
8510b57cec5SDimitry Andric           capped_data = true;
8520b57cec5SDimitry Andric           cstr_len = max_length;
8530b57cec5SDimitry Andric         }
8540b57cec5SDimitry Andric       }
8550b57cec5SDimitry Andric       cstr_address = GetAddressOf(true, &cstr_address_type);
8560b57cec5SDimitry Andric     } else {
8570b57cec5SDimitry Andric       // We have a pointer
8580b57cec5SDimitry Andric       cstr_address = GetPointerValue(&cstr_address_type);
8590b57cec5SDimitry Andric     }
8600b57cec5SDimitry Andric 
8610b57cec5SDimitry Andric     if (cstr_address == 0 || cstr_address == LLDB_INVALID_ADDRESS) {
8620b57cec5SDimitry Andric       if (cstr_address_type == eAddressTypeHost && is_array) {
8630b57cec5SDimitry Andric         const char *cstr = GetDataExtractor().PeekCStr(0);
8640b57cec5SDimitry Andric         if (cstr == nullptr) {
8650b57cec5SDimitry Andric           s << "<invalid address>";
8660b57cec5SDimitry Andric           error.SetErrorString("invalid address");
8670b57cec5SDimitry Andric           CopyStringDataToBufferSP(s, buffer_sp);
8680b57cec5SDimitry Andric           return {0, was_capped};
8690b57cec5SDimitry Andric         }
870349cc55cSDimitry Andric         s << llvm::StringRef(cstr, cstr_len);
871349cc55cSDimitry Andric         CopyStringDataToBufferSP(s, buffer_sp);
8720b57cec5SDimitry Andric         return {cstr_len, was_capped};
8730b57cec5SDimitry Andric       } else {
8740b57cec5SDimitry Andric         s << "<invalid address>";
8750b57cec5SDimitry Andric         error.SetErrorString("invalid address");
8760b57cec5SDimitry Andric         CopyStringDataToBufferSP(s, buffer_sp);
8770b57cec5SDimitry Andric         return {0, was_capped};
8780b57cec5SDimitry Andric       }
8790b57cec5SDimitry Andric     }
8800b57cec5SDimitry Andric 
8810b57cec5SDimitry Andric     Address cstr_so_addr(cstr_address);
8820b57cec5SDimitry Andric     DataExtractor data;
8830b57cec5SDimitry Andric     if (cstr_len > 0 && honor_array) {
8840b57cec5SDimitry Andric       // I am using GetPointeeData() here to abstract the fact that some
8850b57cec5SDimitry Andric       // ValueObjects are actually frozen pointers in the host but the pointed-
8860b57cec5SDimitry Andric       // to data lives in the debuggee, and GetPointeeData() automatically
8870b57cec5SDimitry Andric       // takes care of this
8880b57cec5SDimitry Andric       GetPointeeData(data, 0, cstr_len);
8890b57cec5SDimitry Andric 
8900b57cec5SDimitry Andric       if ((bytes_read = data.GetByteSize()) > 0) {
8910b57cec5SDimitry Andric         total_bytes_read = bytes_read;
8920b57cec5SDimitry Andric         for (size_t offset = 0; offset < bytes_read; offset++)
8930b57cec5SDimitry Andric           s.Printf("%c", *data.PeekData(offset, 1));
8940b57cec5SDimitry Andric         if (capped_data)
8950b57cec5SDimitry Andric           was_capped = true;
8960b57cec5SDimitry Andric       }
8970b57cec5SDimitry Andric     } else {
8980b57cec5SDimitry Andric       cstr_len = max_length;
8990b57cec5SDimitry Andric       const size_t k_max_buf_size = 64;
9000b57cec5SDimitry Andric 
9010b57cec5SDimitry Andric       size_t offset = 0;
9020b57cec5SDimitry Andric 
9030b57cec5SDimitry Andric       int cstr_len_displayed = -1;
9040b57cec5SDimitry Andric       bool capped_cstr = false;
9050b57cec5SDimitry Andric       // I am using GetPointeeData() here to abstract the fact that some
9060b57cec5SDimitry Andric       // ValueObjects are actually frozen pointers in the host but the pointed-
9070b57cec5SDimitry Andric       // to data lives in the debuggee, and GetPointeeData() automatically
9080b57cec5SDimitry Andric       // takes care of this
9090b57cec5SDimitry Andric       while ((bytes_read = GetPointeeData(data, offset, k_max_buf_size)) > 0) {
9100b57cec5SDimitry Andric         total_bytes_read += bytes_read;
9110b57cec5SDimitry Andric         const char *cstr = data.PeekCStr(0);
9120b57cec5SDimitry Andric         size_t len = strnlen(cstr, k_max_buf_size);
9130b57cec5SDimitry Andric         if (cstr_len_displayed < 0)
9140b57cec5SDimitry Andric           cstr_len_displayed = len;
9150b57cec5SDimitry Andric 
9160b57cec5SDimitry Andric         if (len == 0)
9170b57cec5SDimitry Andric           break;
9180b57cec5SDimitry Andric         cstr_len_displayed += len;
9190b57cec5SDimitry Andric         if (len > bytes_read)
9200b57cec5SDimitry Andric           len = bytes_read;
9210b57cec5SDimitry Andric         if (len > cstr_len)
9220b57cec5SDimitry Andric           len = cstr_len;
9230b57cec5SDimitry Andric 
9240b57cec5SDimitry Andric         for (size_t offset = 0; offset < bytes_read; offset++)
9250b57cec5SDimitry Andric           s.Printf("%c", *data.PeekData(offset, 1));
9260b57cec5SDimitry Andric 
9270b57cec5SDimitry Andric         if (len < k_max_buf_size)
9280b57cec5SDimitry Andric           break;
9290b57cec5SDimitry Andric 
9300b57cec5SDimitry Andric         if (len >= cstr_len) {
9310b57cec5SDimitry Andric           capped_cstr = true;
9320b57cec5SDimitry Andric           break;
9330b57cec5SDimitry Andric         }
9340b57cec5SDimitry Andric 
9350b57cec5SDimitry Andric         cstr_len -= len;
9360b57cec5SDimitry Andric         offset += len;
9370b57cec5SDimitry Andric       }
9380b57cec5SDimitry Andric 
9390b57cec5SDimitry Andric       if (cstr_len_displayed >= 0) {
9400b57cec5SDimitry Andric         if (capped_cstr)
9410b57cec5SDimitry Andric           was_capped = true;
9420b57cec5SDimitry Andric       }
9430b57cec5SDimitry Andric     }
9440b57cec5SDimitry Andric   } else {
9450b57cec5SDimitry Andric     error.SetErrorString("not a string object");
9460b57cec5SDimitry Andric     s << "<not a string object>";
9470b57cec5SDimitry Andric   }
9480b57cec5SDimitry Andric   CopyStringDataToBufferSP(s, buffer_sp);
9490b57cec5SDimitry Andric   return {total_bytes_read, was_capped};
9500b57cec5SDimitry Andric }
9510b57cec5SDimitry Andric 
GetObjectDescription()9520b57cec5SDimitry Andric const char *ValueObject::GetObjectDescription() {
9530b57cec5SDimitry Andric   if (!UpdateValueIfNeeded(true))
9540b57cec5SDimitry Andric     return nullptr;
9550b57cec5SDimitry Andric 
9560b57cec5SDimitry Andric   // Return cached value.
9570b57cec5SDimitry Andric   if (!m_object_desc_str.empty())
9580b57cec5SDimitry Andric     return m_object_desc_str.c_str();
9590b57cec5SDimitry Andric 
9600b57cec5SDimitry Andric   ExecutionContext exe_ctx(GetExecutionContextRef());
9610b57cec5SDimitry Andric   Process *process = exe_ctx.GetProcessPtr();
9620b57cec5SDimitry Andric   if (!process)
9630b57cec5SDimitry Andric     return nullptr;
9640b57cec5SDimitry Andric 
9650b57cec5SDimitry Andric   // Returns the object description produced by one language runtime.
9660b57cec5SDimitry Andric   auto get_object_description = [&](LanguageType language) -> const char * {
9670b57cec5SDimitry Andric     if (LanguageRuntime *runtime = process->GetLanguageRuntime(language)) {
9680b57cec5SDimitry Andric       StreamString s;
9690b57cec5SDimitry Andric       if (runtime->GetObjectDescription(s, *this)) {
9705ffd83dbSDimitry Andric         m_object_desc_str.append(std::string(s.GetString()));
9710b57cec5SDimitry Andric         return m_object_desc_str.c_str();
9720b57cec5SDimitry Andric       }
9730b57cec5SDimitry Andric     }
9740b57cec5SDimitry Andric     return nullptr;
9750b57cec5SDimitry Andric   };
9760b57cec5SDimitry Andric 
9770b57cec5SDimitry Andric   // Try the native language runtime first.
9780b57cec5SDimitry Andric   LanguageType native_language = GetObjectRuntimeLanguage();
9790b57cec5SDimitry Andric   if (const char *desc = get_object_description(native_language))
9800b57cec5SDimitry Andric     return desc;
9810b57cec5SDimitry Andric 
9820b57cec5SDimitry Andric   // Try the Objective-C language runtime. This fallback is necessary
9830b57cec5SDimitry Andric   // for Objective-C++ and mixed Objective-C / C++ programs.
9840b57cec5SDimitry Andric   if (Language::LanguageIsCFamily(native_language))
9850b57cec5SDimitry Andric     return get_object_description(eLanguageTypeObjC);
9860b57cec5SDimitry Andric   return nullptr;
9870b57cec5SDimitry Andric }
9880b57cec5SDimitry Andric 
GetValueAsCString(const lldb_private::TypeFormatImpl & format,std::string & destination)9890b57cec5SDimitry Andric bool ValueObject::GetValueAsCString(const lldb_private::TypeFormatImpl &format,
9900b57cec5SDimitry Andric                                     std::string &destination) {
9910b57cec5SDimitry Andric   if (UpdateValueIfNeeded(false))
9920b57cec5SDimitry Andric     return format.FormatObject(this, destination);
9930b57cec5SDimitry Andric   else
9940b57cec5SDimitry Andric     return false;
9950b57cec5SDimitry Andric }
9960b57cec5SDimitry Andric 
GetValueAsCString(lldb::Format format,std::string & destination)9970b57cec5SDimitry Andric bool ValueObject::GetValueAsCString(lldb::Format format,
9980b57cec5SDimitry Andric                                     std::string &destination) {
9990b57cec5SDimitry Andric   return GetValueAsCString(TypeFormatImpl_Format(format), destination);
10000b57cec5SDimitry Andric }
10010b57cec5SDimitry Andric 
GetValueAsCString()10020b57cec5SDimitry Andric const char *ValueObject::GetValueAsCString() {
10030b57cec5SDimitry Andric   if (UpdateValueIfNeeded(true)) {
10040b57cec5SDimitry Andric     lldb::TypeFormatImplSP format_sp;
10050b57cec5SDimitry Andric     lldb::Format my_format = GetFormat();
10060b57cec5SDimitry Andric     if (my_format == lldb::eFormatDefault) {
10070b57cec5SDimitry Andric       if (m_type_format_sp)
10080b57cec5SDimitry Andric         format_sp = m_type_format_sp;
10090b57cec5SDimitry Andric       else {
1010fe6060f1SDimitry Andric         if (m_flags.m_is_bitfield_for_scalar)
10110b57cec5SDimitry Andric           my_format = eFormatUnsigned;
10120b57cec5SDimitry Andric         else {
1013fe6060f1SDimitry Andric           if (m_value.GetContextType() == Value::ContextType::RegisterInfo) {
10140b57cec5SDimitry Andric             const RegisterInfo *reg_info = m_value.GetRegisterInfo();
10150b57cec5SDimitry Andric             if (reg_info)
10160b57cec5SDimitry Andric               my_format = reg_info->format;
10170b57cec5SDimitry Andric           } else {
10180b57cec5SDimitry Andric             my_format = GetValue().GetCompilerType().GetFormat();
10190b57cec5SDimitry Andric           }
10200b57cec5SDimitry Andric         }
10210b57cec5SDimitry Andric       }
10220b57cec5SDimitry Andric     }
10230b57cec5SDimitry Andric     if (my_format != m_last_format || m_value_str.empty()) {
10240b57cec5SDimitry Andric       m_last_format = my_format;
10250b57cec5SDimitry Andric       if (!format_sp)
10260b57cec5SDimitry Andric         format_sp = std::make_shared<TypeFormatImpl_Format>(my_format);
10270b57cec5SDimitry Andric       if (GetValueAsCString(*format_sp.get(), m_value_str)) {
1028fe6060f1SDimitry Andric         if (!m_flags.m_value_did_change && m_flags.m_old_value_valid) {
10290b57cec5SDimitry Andric           // The value was gotten successfully, so we consider the value as
10300b57cec5SDimitry Andric           // changed if the value string differs
10310b57cec5SDimitry Andric           SetValueDidChange(m_old_value_str != m_value_str);
10320b57cec5SDimitry Andric         }
10330b57cec5SDimitry Andric       }
10340b57cec5SDimitry Andric     }
10350b57cec5SDimitry Andric   }
10360b57cec5SDimitry Andric   if (m_value_str.empty())
10370b57cec5SDimitry Andric     return nullptr;
10380b57cec5SDimitry Andric   return m_value_str.c_str();
10390b57cec5SDimitry Andric }
10400b57cec5SDimitry Andric 
10410b57cec5SDimitry Andric // if > 8bytes, 0 is returned. this method should mostly be used to read
10420b57cec5SDimitry Andric // address values out of pointers
GetValueAsUnsigned(uint64_t fail_value,bool * success)10430b57cec5SDimitry Andric uint64_t ValueObject::GetValueAsUnsigned(uint64_t fail_value, bool *success) {
10440b57cec5SDimitry Andric   // If our byte size is zero this is an aggregate type that has children
10450b57cec5SDimitry Andric   if (CanProvideValue()) {
10460b57cec5SDimitry Andric     Scalar scalar;
10470b57cec5SDimitry Andric     if (ResolveValue(scalar)) {
10480b57cec5SDimitry Andric       if (success)
10490b57cec5SDimitry Andric         *success = true;
10505ffd83dbSDimitry Andric       scalar.MakeUnsigned();
10510b57cec5SDimitry Andric       return scalar.ULongLong(fail_value);
10520b57cec5SDimitry Andric     }
10530b57cec5SDimitry Andric     // fallthrough, otherwise...
10540b57cec5SDimitry Andric   }
10550b57cec5SDimitry Andric 
10560b57cec5SDimitry Andric   if (success)
10570b57cec5SDimitry Andric     *success = false;
10580b57cec5SDimitry Andric   return fail_value;
10590b57cec5SDimitry Andric }
10600b57cec5SDimitry Andric 
GetValueAsSigned(int64_t fail_value,bool * success)10610b57cec5SDimitry Andric int64_t ValueObject::GetValueAsSigned(int64_t fail_value, bool *success) {
10620b57cec5SDimitry Andric   // If our byte size is zero this is an aggregate type that has children
10630b57cec5SDimitry Andric   if (CanProvideValue()) {
10640b57cec5SDimitry Andric     Scalar scalar;
10650b57cec5SDimitry Andric     if (ResolveValue(scalar)) {
10660b57cec5SDimitry Andric       if (success)
10670b57cec5SDimitry Andric         *success = true;
10685ffd83dbSDimitry Andric       scalar.MakeSigned();
10690b57cec5SDimitry Andric       return scalar.SLongLong(fail_value);
10700b57cec5SDimitry Andric     }
10710b57cec5SDimitry Andric     // fallthrough, otherwise...
10720b57cec5SDimitry Andric   }
10730b57cec5SDimitry Andric 
10740b57cec5SDimitry Andric   if (success)
10750b57cec5SDimitry Andric     *success = false;
10760b57cec5SDimitry Andric   return fail_value;
10770b57cec5SDimitry Andric }
10780b57cec5SDimitry Andric 
10790b57cec5SDimitry Andric // if any more "special cases" are added to
10800b57cec5SDimitry Andric // ValueObject::DumpPrintableRepresentation() please keep this call up to date
10810b57cec5SDimitry Andric // by returning true for your new special cases. We will eventually move to
10820b57cec5SDimitry Andric // checking this call result before trying to display special cases
HasSpecialPrintableRepresentation(ValueObjectRepresentationStyle val_obj_display,Format custom_format)10830b57cec5SDimitry Andric bool ValueObject::HasSpecialPrintableRepresentation(
10840b57cec5SDimitry Andric     ValueObjectRepresentationStyle val_obj_display, Format custom_format) {
10850b57cec5SDimitry Andric   Flags flags(GetTypeInfo());
10860b57cec5SDimitry Andric   if (flags.AnySet(eTypeIsArray | eTypeIsPointer) &&
10870b57cec5SDimitry Andric       val_obj_display == ValueObject::eValueObjectRepresentationStyleValue) {
10880b57cec5SDimitry Andric     if (IsCStringContainer(true) &&
10890b57cec5SDimitry Andric         (custom_format == eFormatCString || custom_format == eFormatCharArray ||
10900b57cec5SDimitry Andric          custom_format == eFormatChar || custom_format == eFormatVectorOfChar))
10910b57cec5SDimitry Andric       return true;
10920b57cec5SDimitry Andric 
10930b57cec5SDimitry Andric     if (flags.Test(eTypeIsArray)) {
10940b57cec5SDimitry Andric       if ((custom_format == eFormatBytes) ||
10950b57cec5SDimitry Andric           (custom_format == eFormatBytesWithASCII))
10960b57cec5SDimitry Andric         return true;
10970b57cec5SDimitry Andric 
10980b57cec5SDimitry Andric       if ((custom_format == eFormatVectorOfChar) ||
10990b57cec5SDimitry Andric           (custom_format == eFormatVectorOfFloat32) ||
11000b57cec5SDimitry Andric           (custom_format == eFormatVectorOfFloat64) ||
11010b57cec5SDimitry Andric           (custom_format == eFormatVectorOfSInt16) ||
11020b57cec5SDimitry Andric           (custom_format == eFormatVectorOfSInt32) ||
11030b57cec5SDimitry Andric           (custom_format == eFormatVectorOfSInt64) ||
11040b57cec5SDimitry Andric           (custom_format == eFormatVectorOfSInt8) ||
11050b57cec5SDimitry Andric           (custom_format == eFormatVectorOfUInt128) ||
11060b57cec5SDimitry Andric           (custom_format == eFormatVectorOfUInt16) ||
11070b57cec5SDimitry Andric           (custom_format == eFormatVectorOfUInt32) ||
11080b57cec5SDimitry Andric           (custom_format == eFormatVectorOfUInt64) ||
11090b57cec5SDimitry Andric           (custom_format == eFormatVectorOfUInt8))
11100b57cec5SDimitry Andric         return true;
11110b57cec5SDimitry Andric     }
11120b57cec5SDimitry Andric   }
11130b57cec5SDimitry Andric   return false;
11140b57cec5SDimitry Andric }
11150b57cec5SDimitry Andric 
DumpPrintableRepresentation(Stream & s,ValueObjectRepresentationStyle val_obj_display,Format custom_format,PrintableRepresentationSpecialCases special,bool do_dump_error)11160b57cec5SDimitry Andric bool ValueObject::DumpPrintableRepresentation(
11170b57cec5SDimitry Andric     Stream &s, ValueObjectRepresentationStyle val_obj_display,
11180b57cec5SDimitry Andric     Format custom_format, PrintableRepresentationSpecialCases special,
11190b57cec5SDimitry Andric     bool do_dump_error) {
11200b57cec5SDimitry Andric 
1121fe013be4SDimitry Andric   // If the ValueObject has an error, we might end up dumping the type, which
1122fe013be4SDimitry Andric   // is useful, but if we don't even have a type, then don't examine the object
1123fe013be4SDimitry Andric   // further as that's not meaningful, only the error is.
1124fe013be4SDimitry Andric   if (m_error.Fail() && !GetCompilerType().IsValid()) {
1125fe013be4SDimitry Andric     if (do_dump_error)
1126fe013be4SDimitry Andric       s.Printf("<%s>", m_error.AsCString());
1127fe013be4SDimitry Andric     return false;
1128fe013be4SDimitry Andric   }
1129fe013be4SDimitry Andric 
11300b57cec5SDimitry Andric   Flags flags(GetTypeInfo());
11310b57cec5SDimitry Andric 
11320b57cec5SDimitry Andric   bool allow_special =
11330b57cec5SDimitry Andric       (special == ValueObject::PrintableRepresentationSpecialCases::eAllow);
11340b57cec5SDimitry Andric   const bool only_special = false;
11350b57cec5SDimitry Andric 
11360b57cec5SDimitry Andric   if (allow_special) {
11370b57cec5SDimitry Andric     if (flags.AnySet(eTypeIsArray | eTypeIsPointer) &&
11380b57cec5SDimitry Andric         val_obj_display == ValueObject::eValueObjectRepresentationStyleValue) {
11390b57cec5SDimitry Andric       // when being asked to get a printable display an array or pointer type
11400b57cec5SDimitry Andric       // directly, try to "do the right thing"
11410b57cec5SDimitry Andric 
11420b57cec5SDimitry Andric       if (IsCStringContainer(true) &&
11430b57cec5SDimitry Andric           (custom_format == eFormatCString ||
11440b57cec5SDimitry Andric            custom_format == eFormatCharArray || custom_format == eFormatChar ||
11450b57cec5SDimitry Andric            custom_format ==
11460b57cec5SDimitry Andric                eFormatVectorOfChar)) // print char[] & char* directly
11470b57cec5SDimitry Andric       {
11480b57cec5SDimitry Andric         Status error;
114981ad6265SDimitry Andric         lldb::WritableDataBufferSP buffer_sp;
1150*a58f00eaSDimitry Andric         std::pair<size_t, bool> read_string =
1151*a58f00eaSDimitry Andric             ReadPointedString(buffer_sp, error,
1152*a58f00eaSDimitry Andric                               (custom_format == eFormatVectorOfChar) ||
11530b57cec5SDimitry Andric                                   (custom_format == eFormatCharArray));
11540b57cec5SDimitry Andric         lldb_private::formatters::StringPrinter::
11550b57cec5SDimitry Andric             ReadBufferAndDumpToStreamOptions options(*this);
11560b57cec5SDimitry Andric         options.SetData(DataExtractor(
11570b57cec5SDimitry Andric             buffer_sp, lldb::eByteOrderInvalid,
11580b57cec5SDimitry Andric             8)); // none of this matters for a string - pass some defaults
11590b57cec5SDimitry Andric         options.SetStream(&s);
11600b57cec5SDimitry Andric         options.SetPrefixToken(nullptr);
11610b57cec5SDimitry Andric         options.SetQuote('"');
11620b57cec5SDimitry Andric         options.SetSourceSize(buffer_sp->GetByteSize());
11630b57cec5SDimitry Andric         options.SetIsTruncated(read_string.second);
1164349cc55cSDimitry Andric         options.SetBinaryZeroIsTerminator(custom_format != eFormatVectorOfChar);
11650b57cec5SDimitry Andric         formatters::StringPrinter::ReadBufferAndDumpToStream<
11660b57cec5SDimitry Andric             lldb_private::formatters::StringPrinter::StringElementType::ASCII>(
11670b57cec5SDimitry Andric             options);
11680b57cec5SDimitry Andric         return !error.Fail();
11690b57cec5SDimitry Andric       }
11700b57cec5SDimitry Andric 
11710b57cec5SDimitry Andric       if (custom_format == eFormatEnum)
11720b57cec5SDimitry Andric         return false;
11730b57cec5SDimitry Andric 
11740b57cec5SDimitry Andric       // this only works for arrays, because I have no way to know when the
11750b57cec5SDimitry Andric       // pointed memory ends, and no special \0 end of data marker
11760b57cec5SDimitry Andric       if (flags.Test(eTypeIsArray)) {
11770b57cec5SDimitry Andric         if ((custom_format == eFormatBytes) ||
11780b57cec5SDimitry Andric             (custom_format == eFormatBytesWithASCII)) {
11790b57cec5SDimitry Andric           const size_t count = GetNumChildren();
11800b57cec5SDimitry Andric 
11810b57cec5SDimitry Andric           s << '[';
11820b57cec5SDimitry Andric           for (size_t low = 0; low < count; low++) {
11830b57cec5SDimitry Andric 
11840b57cec5SDimitry Andric             if (low)
11850b57cec5SDimitry Andric               s << ',';
11860b57cec5SDimitry Andric 
1187fe013be4SDimitry Andric             ValueObjectSP child = GetChildAtIndex(low);
11880b57cec5SDimitry Andric             if (!child.get()) {
11890b57cec5SDimitry Andric               s << "<invalid child>";
11900b57cec5SDimitry Andric               continue;
11910b57cec5SDimitry Andric             }
11920b57cec5SDimitry Andric             child->DumpPrintableRepresentation(
11930b57cec5SDimitry Andric                 s, ValueObject::eValueObjectRepresentationStyleValue,
11940b57cec5SDimitry Andric                 custom_format);
11950b57cec5SDimitry Andric           }
11960b57cec5SDimitry Andric 
11970b57cec5SDimitry Andric           s << ']';
11980b57cec5SDimitry Andric 
11990b57cec5SDimitry Andric           return true;
12000b57cec5SDimitry Andric         }
12010b57cec5SDimitry Andric 
12020b57cec5SDimitry Andric         if ((custom_format == eFormatVectorOfChar) ||
12030b57cec5SDimitry Andric             (custom_format == eFormatVectorOfFloat32) ||
12040b57cec5SDimitry Andric             (custom_format == eFormatVectorOfFloat64) ||
12050b57cec5SDimitry Andric             (custom_format == eFormatVectorOfSInt16) ||
12060b57cec5SDimitry Andric             (custom_format == eFormatVectorOfSInt32) ||
12070b57cec5SDimitry Andric             (custom_format == eFormatVectorOfSInt64) ||
12080b57cec5SDimitry Andric             (custom_format == eFormatVectorOfSInt8) ||
12090b57cec5SDimitry Andric             (custom_format == eFormatVectorOfUInt128) ||
12100b57cec5SDimitry Andric             (custom_format == eFormatVectorOfUInt16) ||
12110b57cec5SDimitry Andric             (custom_format == eFormatVectorOfUInt32) ||
12120b57cec5SDimitry Andric             (custom_format == eFormatVectorOfUInt64) ||
12130b57cec5SDimitry Andric             (custom_format == eFormatVectorOfUInt8)) // arrays of bytes, bytes
12140b57cec5SDimitry Andric                                                      // with ASCII or any vector
12150b57cec5SDimitry Andric                                                      // format should be printed
12160b57cec5SDimitry Andric                                                      // directly
12170b57cec5SDimitry Andric         {
12180b57cec5SDimitry Andric           const size_t count = GetNumChildren();
12190b57cec5SDimitry Andric 
12200b57cec5SDimitry Andric           Format format = FormatManager::GetSingleItemFormat(custom_format);
12210b57cec5SDimitry Andric 
12220b57cec5SDimitry Andric           s << '[';
12230b57cec5SDimitry Andric           for (size_t low = 0; low < count; low++) {
12240b57cec5SDimitry Andric 
12250b57cec5SDimitry Andric             if (low)
12260b57cec5SDimitry Andric               s << ',';
12270b57cec5SDimitry Andric 
1228fe013be4SDimitry Andric             ValueObjectSP child = GetChildAtIndex(low);
12290b57cec5SDimitry Andric             if (!child.get()) {
12300b57cec5SDimitry Andric               s << "<invalid child>";
12310b57cec5SDimitry Andric               continue;
12320b57cec5SDimitry Andric             }
12330b57cec5SDimitry Andric             child->DumpPrintableRepresentation(
12340b57cec5SDimitry Andric                 s, ValueObject::eValueObjectRepresentationStyleValue, format);
12350b57cec5SDimitry Andric           }
12360b57cec5SDimitry Andric 
12370b57cec5SDimitry Andric           s << ']';
12380b57cec5SDimitry Andric 
12390b57cec5SDimitry Andric           return true;
12400b57cec5SDimitry Andric         }
12410b57cec5SDimitry Andric       }
12420b57cec5SDimitry Andric 
12430b57cec5SDimitry Andric       if ((custom_format == eFormatBoolean) ||
12440b57cec5SDimitry Andric           (custom_format == eFormatBinary) || (custom_format == eFormatChar) ||
12450b57cec5SDimitry Andric           (custom_format == eFormatCharPrintable) ||
12460b57cec5SDimitry Andric           (custom_format == eFormatComplexFloat) ||
12470b57cec5SDimitry Andric           (custom_format == eFormatDecimal) || (custom_format == eFormatHex) ||
12480b57cec5SDimitry Andric           (custom_format == eFormatHexUppercase) ||
12490b57cec5SDimitry Andric           (custom_format == eFormatFloat) || (custom_format == eFormatOctal) ||
12500b57cec5SDimitry Andric           (custom_format == eFormatOSType) ||
12510b57cec5SDimitry Andric           (custom_format == eFormatUnicode16) ||
12520b57cec5SDimitry Andric           (custom_format == eFormatUnicode32) ||
12530b57cec5SDimitry Andric           (custom_format == eFormatUnsigned) ||
12540b57cec5SDimitry Andric           (custom_format == eFormatPointer) ||
12550b57cec5SDimitry Andric           (custom_format == eFormatComplexInteger) ||
12560b57cec5SDimitry Andric           (custom_format == eFormatComplex) ||
12570b57cec5SDimitry Andric           (custom_format == eFormatDefault)) // use the [] operator
12580b57cec5SDimitry Andric         return false;
12590b57cec5SDimitry Andric     }
12600b57cec5SDimitry Andric   }
12610b57cec5SDimitry Andric 
12620b57cec5SDimitry Andric   if (only_special)
12630b57cec5SDimitry Andric     return false;
12640b57cec5SDimitry Andric 
12650b57cec5SDimitry Andric   bool var_success = false;
12660b57cec5SDimitry Andric 
12670b57cec5SDimitry Andric   {
12680b57cec5SDimitry Andric     llvm::StringRef str;
12690b57cec5SDimitry Andric 
12700b57cec5SDimitry Andric     // this is a local stream that we are using to ensure that the data pointed
12710b57cec5SDimitry Andric     // to by cstr survives long enough for us to copy it to its destination -
12720b57cec5SDimitry Andric     // it is necessary to have this temporary storage area for cases where our
12730b57cec5SDimitry Andric     // desired output is not backed by some other longer-term storage
12740b57cec5SDimitry Andric     StreamString strm;
12750b57cec5SDimitry Andric 
12760b57cec5SDimitry Andric     if (custom_format != eFormatInvalid)
12770b57cec5SDimitry Andric       SetFormat(custom_format);
12780b57cec5SDimitry Andric 
12790b57cec5SDimitry Andric     switch (val_obj_display) {
12800b57cec5SDimitry Andric     case eValueObjectRepresentationStyleValue:
12810b57cec5SDimitry Andric       str = GetValueAsCString();
12820b57cec5SDimitry Andric       break;
12830b57cec5SDimitry Andric 
12840b57cec5SDimitry Andric     case eValueObjectRepresentationStyleSummary:
12850b57cec5SDimitry Andric       str = GetSummaryAsCString();
12860b57cec5SDimitry Andric       break;
12870b57cec5SDimitry Andric 
12880b57cec5SDimitry Andric     case eValueObjectRepresentationStyleLanguageSpecific:
12890b57cec5SDimitry Andric       str = GetObjectDescription();
12900b57cec5SDimitry Andric       break;
12910b57cec5SDimitry Andric 
12920b57cec5SDimitry Andric     case eValueObjectRepresentationStyleLocation:
12930b57cec5SDimitry Andric       str = GetLocationAsCString();
12940b57cec5SDimitry Andric       break;
12950b57cec5SDimitry Andric 
12960b57cec5SDimitry Andric     case eValueObjectRepresentationStyleChildrenCount:
12970b57cec5SDimitry Andric       strm.Printf("%" PRIu64 "", (uint64_t)GetNumChildren());
12980b57cec5SDimitry Andric       str = strm.GetString();
12990b57cec5SDimitry Andric       break;
13000b57cec5SDimitry Andric 
13010b57cec5SDimitry Andric     case eValueObjectRepresentationStyleType:
13020b57cec5SDimitry Andric       str = GetTypeName().GetStringRef();
13030b57cec5SDimitry Andric       break;
13040b57cec5SDimitry Andric 
13050b57cec5SDimitry Andric     case eValueObjectRepresentationStyleName:
13060b57cec5SDimitry Andric       str = GetName().GetStringRef();
13070b57cec5SDimitry Andric       break;
13080b57cec5SDimitry Andric 
13090b57cec5SDimitry Andric     case eValueObjectRepresentationStyleExpressionPath:
13105ffd83dbSDimitry Andric       GetExpressionPath(strm);
13110b57cec5SDimitry Andric       str = strm.GetString();
13120b57cec5SDimitry Andric       break;
13130b57cec5SDimitry Andric     }
13140b57cec5SDimitry Andric 
13150b57cec5SDimitry Andric     if (str.empty()) {
13160b57cec5SDimitry Andric       if (val_obj_display == eValueObjectRepresentationStyleValue)
13170b57cec5SDimitry Andric         str = GetSummaryAsCString();
13180b57cec5SDimitry Andric       else if (val_obj_display == eValueObjectRepresentationStyleSummary) {
13190b57cec5SDimitry Andric         if (!CanProvideValue()) {
13200b57cec5SDimitry Andric           strm.Printf("%s @ %s", GetTypeName().AsCString(),
13210b57cec5SDimitry Andric                       GetLocationAsCString());
13220b57cec5SDimitry Andric           str = strm.GetString();
13230b57cec5SDimitry Andric         } else
13240b57cec5SDimitry Andric           str = GetValueAsCString();
13250b57cec5SDimitry Andric       }
13260b57cec5SDimitry Andric     }
13270b57cec5SDimitry Andric 
13280b57cec5SDimitry Andric     if (!str.empty())
13290b57cec5SDimitry Andric       s << str;
13300b57cec5SDimitry Andric     else {
1331fe013be4SDimitry Andric       // We checked for errors at the start, but do it again here in case
1332fe013be4SDimitry Andric       // realizing the value for dumping produced an error.
13330b57cec5SDimitry Andric       if (m_error.Fail()) {
13340b57cec5SDimitry Andric         if (do_dump_error)
13350b57cec5SDimitry Andric           s.Printf("<%s>", m_error.AsCString());
13360b57cec5SDimitry Andric         else
13370b57cec5SDimitry Andric           return false;
13380b57cec5SDimitry Andric       } else if (val_obj_display == eValueObjectRepresentationStyleSummary)
13390b57cec5SDimitry Andric         s.PutCString("<no summary available>");
13400b57cec5SDimitry Andric       else if (val_obj_display == eValueObjectRepresentationStyleValue)
13410b57cec5SDimitry Andric         s.PutCString("<no value available>");
13420b57cec5SDimitry Andric       else if (val_obj_display ==
13430b57cec5SDimitry Andric                eValueObjectRepresentationStyleLanguageSpecific)
13440b57cec5SDimitry Andric         s.PutCString("<not a valid Objective-C object>"); // edit this if we
13450b57cec5SDimitry Andric                                                           // have other runtimes
13460b57cec5SDimitry Andric                                                           // that support a
13470b57cec5SDimitry Andric                                                           // description
13480b57cec5SDimitry Andric       else
13490b57cec5SDimitry Andric         s.PutCString("<no printable representation>");
13500b57cec5SDimitry Andric     }
13510b57cec5SDimitry Andric 
13520b57cec5SDimitry Andric     // we should only return false here if we could not do *anything* even if
13530b57cec5SDimitry Andric     // we have an error message as output, that's a success from our callers'
13540b57cec5SDimitry Andric     // perspective, so return true
13550b57cec5SDimitry Andric     var_success = true;
13560b57cec5SDimitry Andric 
13570b57cec5SDimitry Andric     if (custom_format != eFormatInvalid)
13580b57cec5SDimitry Andric       SetFormat(eFormatDefault);
13590b57cec5SDimitry Andric   }
13600b57cec5SDimitry Andric 
13610b57cec5SDimitry Andric   return var_success;
13620b57cec5SDimitry Andric }
13630b57cec5SDimitry Andric 
GetAddressOf(bool scalar_is_load_address,AddressType * address_type)13640b57cec5SDimitry Andric addr_t ValueObject::GetAddressOf(bool scalar_is_load_address,
13650b57cec5SDimitry Andric                                  AddressType *address_type) {
13660b57cec5SDimitry Andric   // Can't take address of a bitfield
13670b57cec5SDimitry Andric   if (IsBitfield())
13680b57cec5SDimitry Andric     return LLDB_INVALID_ADDRESS;
13690b57cec5SDimitry Andric 
13700b57cec5SDimitry Andric   if (!UpdateValueIfNeeded(false))
13710b57cec5SDimitry Andric     return LLDB_INVALID_ADDRESS;
13720b57cec5SDimitry Andric 
13730b57cec5SDimitry Andric   switch (m_value.GetValueType()) {
1374fe6060f1SDimitry Andric   case Value::ValueType::Invalid:
1375fe6060f1SDimitry Andric     return LLDB_INVALID_ADDRESS;
1376fe6060f1SDimitry Andric   case Value::ValueType::Scalar:
13770b57cec5SDimitry Andric     if (scalar_is_load_address) {
13780b57cec5SDimitry Andric       if (address_type)
13790b57cec5SDimitry Andric         *address_type = eAddressTypeLoad;
13800b57cec5SDimitry Andric       return m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
13810b57cec5SDimitry Andric     }
13820b57cec5SDimitry Andric     break;
13830b57cec5SDimitry Andric 
1384fe6060f1SDimitry Andric   case Value::ValueType::LoadAddress:
1385fe6060f1SDimitry Andric   case Value::ValueType::FileAddress: {
13860b57cec5SDimitry Andric     if (address_type)
13870b57cec5SDimitry Andric       *address_type = m_value.GetValueAddressType();
13880b57cec5SDimitry Andric     return m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
13890b57cec5SDimitry Andric   } break;
1390fe6060f1SDimitry Andric   case Value::ValueType::HostAddress: {
13910b57cec5SDimitry Andric     if (address_type)
13920b57cec5SDimitry Andric       *address_type = m_value.GetValueAddressType();
13930b57cec5SDimitry Andric     return LLDB_INVALID_ADDRESS;
13940b57cec5SDimitry Andric   } break;
13950b57cec5SDimitry Andric   }
13960b57cec5SDimitry Andric   if (address_type)
13970b57cec5SDimitry Andric     *address_type = eAddressTypeInvalid;
13980b57cec5SDimitry Andric   return LLDB_INVALID_ADDRESS;
13990b57cec5SDimitry Andric }
14000b57cec5SDimitry Andric 
GetPointerValue(AddressType * address_type)14010b57cec5SDimitry Andric addr_t ValueObject::GetPointerValue(AddressType *address_type) {
14020b57cec5SDimitry Andric   addr_t address = LLDB_INVALID_ADDRESS;
14030b57cec5SDimitry Andric   if (address_type)
14040b57cec5SDimitry Andric     *address_type = eAddressTypeInvalid;
14050b57cec5SDimitry Andric 
14060b57cec5SDimitry Andric   if (!UpdateValueIfNeeded(false))
14070b57cec5SDimitry Andric     return address;
14080b57cec5SDimitry Andric 
14090b57cec5SDimitry Andric   switch (m_value.GetValueType()) {
1410fe6060f1SDimitry Andric   case Value::ValueType::Invalid:
1411fe6060f1SDimitry Andric     return LLDB_INVALID_ADDRESS;
1412fe6060f1SDimitry Andric   case Value::ValueType::Scalar:
14130b57cec5SDimitry Andric     address = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
14140b57cec5SDimitry Andric     break;
14150b57cec5SDimitry Andric 
1416fe6060f1SDimitry Andric   case Value::ValueType::HostAddress:
1417fe6060f1SDimitry Andric   case Value::ValueType::LoadAddress:
1418fe6060f1SDimitry Andric   case Value::ValueType::FileAddress: {
14190b57cec5SDimitry Andric     lldb::offset_t data_offset = 0;
14205ffd83dbSDimitry Andric     address = m_data.GetAddress(&data_offset);
14210b57cec5SDimitry Andric   } break;
14220b57cec5SDimitry Andric   }
14230b57cec5SDimitry Andric 
14240b57cec5SDimitry Andric   if (address_type)
14250b57cec5SDimitry Andric     *address_type = GetAddressTypeOfChildren();
14260b57cec5SDimitry Andric 
14270b57cec5SDimitry Andric   return address;
14280b57cec5SDimitry Andric }
14290b57cec5SDimitry Andric 
SetValueFromCString(const char * value_str,Status & error)14300b57cec5SDimitry Andric bool ValueObject::SetValueFromCString(const char *value_str, Status &error) {
14310b57cec5SDimitry Andric   error.Clear();
14320b57cec5SDimitry Andric   // Make sure our value is up to date first so that our location and location
14330b57cec5SDimitry Andric   // type is valid.
14340b57cec5SDimitry Andric   if (!UpdateValueIfNeeded(false)) {
14350b57cec5SDimitry Andric     error.SetErrorString("unable to read value");
14360b57cec5SDimitry Andric     return false;
14370b57cec5SDimitry Andric   }
14380b57cec5SDimitry Andric 
14390b57cec5SDimitry Andric   uint64_t count = 0;
14400b57cec5SDimitry Andric   const Encoding encoding = GetCompilerType().GetEncoding(count);
14410b57cec5SDimitry Andric 
144281ad6265SDimitry Andric   const size_t byte_size = GetByteSize().value_or(0);
14430b57cec5SDimitry Andric 
14440b57cec5SDimitry Andric   Value::ValueType value_type = m_value.GetValueType();
14450b57cec5SDimitry Andric 
1446fe6060f1SDimitry Andric   if (value_type == Value::ValueType::Scalar) {
14470b57cec5SDimitry Andric     // If the value is already a scalar, then let the scalar change itself:
14480b57cec5SDimitry Andric     m_value.GetScalar().SetValueFromCString(value_str, encoding, byte_size);
14490b57cec5SDimitry Andric   } else if (byte_size <= 16) {
14500b57cec5SDimitry Andric     // If the value fits in a scalar, then make a new scalar and again let the
14510b57cec5SDimitry Andric     // scalar code do the conversion, then figure out where to put the new
14520b57cec5SDimitry Andric     // value.
14530b57cec5SDimitry Andric     Scalar new_scalar;
14540b57cec5SDimitry Andric     error = new_scalar.SetValueFromCString(value_str, encoding, byte_size);
14550b57cec5SDimitry Andric     if (error.Success()) {
14560b57cec5SDimitry Andric       switch (value_type) {
1457fe6060f1SDimitry Andric       case Value::ValueType::LoadAddress: {
14580b57cec5SDimitry Andric         // If it is a load address, then the scalar value is the storage
14590b57cec5SDimitry Andric         // location of the data, and we have to shove this value down to that
14600b57cec5SDimitry Andric         // load location.
14610b57cec5SDimitry Andric         ExecutionContext exe_ctx(GetExecutionContextRef());
14620b57cec5SDimitry Andric         Process *process = exe_ctx.GetProcessPtr();
14630b57cec5SDimitry Andric         if (process) {
14640b57cec5SDimitry Andric           addr_t target_addr =
14650b57cec5SDimitry Andric               m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
14660b57cec5SDimitry Andric           size_t bytes_written = process->WriteScalarToMemory(
14670b57cec5SDimitry Andric               target_addr, new_scalar, byte_size, error);
14680b57cec5SDimitry Andric           if (!error.Success())
14690b57cec5SDimitry Andric             return false;
14700b57cec5SDimitry Andric           if (bytes_written != byte_size) {
14710b57cec5SDimitry Andric             error.SetErrorString("unable to write value to memory");
14720b57cec5SDimitry Andric             return false;
14730b57cec5SDimitry Andric           }
14740b57cec5SDimitry Andric         }
14750b57cec5SDimitry Andric       } break;
1476fe6060f1SDimitry Andric       case Value::ValueType::HostAddress: {
14770b57cec5SDimitry Andric         // If it is a host address, then we stuff the scalar as a DataBuffer
14780b57cec5SDimitry Andric         // into the Value's data.
14790b57cec5SDimitry Andric         DataExtractor new_data;
14800b57cec5SDimitry Andric         new_data.SetByteOrder(m_data.GetByteOrder());
14810b57cec5SDimitry Andric 
14820b57cec5SDimitry Andric         DataBufferSP buffer_sp(new DataBufferHeap(byte_size, 0));
14830b57cec5SDimitry Andric         m_data.SetData(buffer_sp, 0);
14840b57cec5SDimitry Andric         bool success = new_scalar.GetData(new_data);
14850b57cec5SDimitry Andric         if (success) {
14860b57cec5SDimitry Andric           new_data.CopyByteOrderedData(
14870b57cec5SDimitry Andric               0, byte_size, const_cast<uint8_t *>(m_data.GetDataStart()),
14880b57cec5SDimitry Andric               byte_size, m_data.GetByteOrder());
14890b57cec5SDimitry Andric         }
14900b57cec5SDimitry Andric         m_value.GetScalar() = (uintptr_t)m_data.GetDataStart();
14910b57cec5SDimitry Andric 
14920b57cec5SDimitry Andric       } break;
1493fe6060f1SDimitry Andric       case Value::ValueType::Invalid:
1494fe6060f1SDimitry Andric         error.SetErrorString("invalid location");
1495fe6060f1SDimitry Andric         return false;
1496fe6060f1SDimitry Andric       case Value::ValueType::FileAddress:
1497fe6060f1SDimitry Andric       case Value::ValueType::Scalar:
14980b57cec5SDimitry Andric         break;
14990b57cec5SDimitry Andric       }
15000b57cec5SDimitry Andric     } else {
15010b57cec5SDimitry Andric       return false;
15020b57cec5SDimitry Andric     }
15030b57cec5SDimitry Andric   } else {
15040b57cec5SDimitry Andric     // We don't support setting things bigger than a scalar at present.
15050b57cec5SDimitry Andric     error.SetErrorString("unable to write aggregate data type");
15060b57cec5SDimitry Andric     return false;
15070b57cec5SDimitry Andric   }
15080b57cec5SDimitry Andric 
15090b57cec5SDimitry Andric   // If we have reached this point, then we have successfully changed the
15100b57cec5SDimitry Andric   // value.
15110b57cec5SDimitry Andric   SetNeedsUpdate();
15120b57cec5SDimitry Andric   return true;
15130b57cec5SDimitry Andric }
15140b57cec5SDimitry Andric 
GetDeclaration(Declaration & decl)15150b57cec5SDimitry Andric bool ValueObject::GetDeclaration(Declaration &decl) {
15160b57cec5SDimitry Andric   decl.Clear();
15170b57cec5SDimitry Andric   return false;
15180b57cec5SDimitry Andric }
15190b57cec5SDimitry Andric 
AddSyntheticChild(ConstString key,ValueObject * valobj)15200b57cec5SDimitry Andric void ValueObject::AddSyntheticChild(ConstString key,
15210b57cec5SDimitry Andric                                     ValueObject *valobj) {
15220b57cec5SDimitry Andric   m_synthetic_children[key] = valobj;
15230b57cec5SDimitry Andric }
15240b57cec5SDimitry Andric 
GetSyntheticChild(ConstString key) const15250b57cec5SDimitry Andric ValueObjectSP ValueObject::GetSyntheticChild(ConstString key) const {
15260b57cec5SDimitry Andric   ValueObjectSP synthetic_child_sp;
15270b57cec5SDimitry Andric   std::map<ConstString, ValueObject *>::const_iterator pos =
15280b57cec5SDimitry Andric       m_synthetic_children.find(key);
15290b57cec5SDimitry Andric   if (pos != m_synthetic_children.end())
15300b57cec5SDimitry Andric     synthetic_child_sp = pos->second->GetSP();
15310b57cec5SDimitry Andric   return synthetic_child_sp;
15320b57cec5SDimitry Andric }
15330b57cec5SDimitry Andric 
IsPossibleDynamicType()15340b57cec5SDimitry Andric bool ValueObject::IsPossibleDynamicType() {
15350b57cec5SDimitry Andric   ExecutionContext exe_ctx(GetExecutionContextRef());
15360b57cec5SDimitry Andric   Process *process = exe_ctx.GetProcessPtr();
15370b57cec5SDimitry Andric   if (process)
15380b57cec5SDimitry Andric     return process->IsPossibleDynamicValue(*this);
15390b57cec5SDimitry Andric   else
15400b57cec5SDimitry Andric     return GetCompilerType().IsPossibleDynamicType(nullptr, true, true);
15410b57cec5SDimitry Andric }
15420b57cec5SDimitry Andric 
IsRuntimeSupportValue()15430b57cec5SDimitry Andric bool ValueObject::IsRuntimeSupportValue() {
15440b57cec5SDimitry Andric   Process *process(GetProcessSP().get());
15450b57cec5SDimitry Andric   if (!process)
15460b57cec5SDimitry Andric     return false;
15470b57cec5SDimitry Andric 
1548fe6060f1SDimitry Andric   // We trust that the compiler did the right thing and marked runtime support
15490b57cec5SDimitry Andric   // values as artificial.
15500b57cec5SDimitry Andric   if (!GetVariable() || !GetVariable()->IsArtificial())
15510b57cec5SDimitry Andric     return false;
15520b57cec5SDimitry Andric 
15539dba64beSDimitry Andric   if (auto *runtime = process->GetLanguageRuntime(GetVariable()->GetLanguage()))
15545ffd83dbSDimitry Andric     if (runtime->IsAllowedRuntimeValue(GetName()))
15550b57cec5SDimitry Andric       return false;
15560b57cec5SDimitry Andric 
15570b57cec5SDimitry Andric   return true;
15580b57cec5SDimitry Andric }
15590b57cec5SDimitry Andric 
IsNilReference()15600b57cec5SDimitry Andric bool ValueObject::IsNilReference() {
15610b57cec5SDimitry Andric   if (Language *language = Language::FindPlugin(GetObjectRuntimeLanguage())) {
15620b57cec5SDimitry Andric     return language->IsNilReference(*this);
15630b57cec5SDimitry Andric   }
15640b57cec5SDimitry Andric   return false;
15650b57cec5SDimitry Andric }
15660b57cec5SDimitry Andric 
IsUninitializedReference()15670b57cec5SDimitry Andric bool ValueObject::IsUninitializedReference() {
15680b57cec5SDimitry Andric   if (Language *language = Language::FindPlugin(GetObjectRuntimeLanguage())) {
15690b57cec5SDimitry Andric     return language->IsUninitializedReference(*this);
15700b57cec5SDimitry Andric   }
15710b57cec5SDimitry Andric   return false;
15720b57cec5SDimitry Andric }
15730b57cec5SDimitry Andric 
15740b57cec5SDimitry Andric // This allows you to create an array member using and index that doesn't not
15750b57cec5SDimitry Andric // fall in the normal bounds of the array. Many times structure can be defined
15760b57cec5SDimitry Andric // as: struct Collection {
15770b57cec5SDimitry Andric //     uint32_t item_count;
15780b57cec5SDimitry Andric //     Item item_array[0];
15790b57cec5SDimitry Andric // };
15800b57cec5SDimitry Andric // The size of the "item_array" is 1, but many times in practice there are more
15810b57cec5SDimitry Andric // items in "item_array".
15820b57cec5SDimitry Andric 
GetSyntheticArrayMember(size_t index,bool can_create)15830b57cec5SDimitry Andric ValueObjectSP ValueObject::GetSyntheticArrayMember(size_t index,
15840b57cec5SDimitry Andric                                                    bool can_create) {
1585*a58f00eaSDimitry Andric   if (!IsPointerType() && !IsArrayType())
1586*a58f00eaSDimitry Andric     return ValueObjectSP();
1587*a58f00eaSDimitry Andric 
1588e8d8bef9SDimitry Andric   std::string index_str = llvm::formatv("[{0}]", index);
15890b57cec5SDimitry Andric   ConstString index_const_str(index_str);
15900b57cec5SDimitry Andric   // Check if we have already created a synthetic array member in this valid
15910b57cec5SDimitry Andric   // object. If we have we will re-use it.
1592*a58f00eaSDimitry Andric   if (auto existing_synthetic_child = GetSyntheticChild(index_const_str))
1593*a58f00eaSDimitry Andric     return existing_synthetic_child;
1594*a58f00eaSDimitry Andric 
15950b57cec5SDimitry Andric   // We haven't made a synthetic array member for INDEX yet, so lets make
15960b57cec5SDimitry Andric   // one and cache it for any future reference.
1597*a58f00eaSDimitry Andric   ValueObject *synthetic_child = CreateChildAtIndex(0, true, index);
15980b57cec5SDimitry Andric 
1599*a58f00eaSDimitry Andric   if (!synthetic_child)
1600*a58f00eaSDimitry Andric     return ValueObjectSP();
1601*a58f00eaSDimitry Andric 
1602*a58f00eaSDimitry Andric   // Cache the synthetic child's value because it's valid.
16030b57cec5SDimitry Andric   AddSyntheticChild(index_const_str, synthetic_child);
1604*a58f00eaSDimitry Andric   auto synthetic_child_sp = synthetic_child->GetSP();
16050b57cec5SDimitry Andric   synthetic_child_sp->SetName(ConstString(index_str));
1606fe6060f1SDimitry Andric   synthetic_child_sp->m_flags.m_is_array_item_for_pointer = true;
16070b57cec5SDimitry Andric   return synthetic_child_sp;
16080b57cec5SDimitry Andric }
16090b57cec5SDimitry Andric 
GetSyntheticBitFieldChild(uint32_t from,uint32_t to,bool can_create)16100b57cec5SDimitry Andric ValueObjectSP ValueObject::GetSyntheticBitFieldChild(uint32_t from, uint32_t to,
16110b57cec5SDimitry Andric                                                      bool can_create) {
1612*a58f00eaSDimitry Andric   if (!IsScalarType())
1613*a58f00eaSDimitry Andric     return ValueObjectSP();
1614*a58f00eaSDimitry Andric 
1615e8d8bef9SDimitry Andric   std::string index_str = llvm::formatv("[{0}-{1}]", from, to);
16160b57cec5SDimitry Andric   ConstString index_const_str(index_str);
1617*a58f00eaSDimitry Andric 
16180b57cec5SDimitry Andric   // Check if we have already created a synthetic array member in this valid
16190b57cec5SDimitry Andric   // object. If we have we will re-use it.
1620*a58f00eaSDimitry Andric   if (auto existing_synthetic_child = GetSyntheticChild(index_const_str))
1621*a58f00eaSDimitry Andric     return existing_synthetic_child;
1622*a58f00eaSDimitry Andric 
16230b57cec5SDimitry Andric   uint32_t bit_field_size = to - from + 1;
16240b57cec5SDimitry Andric   uint32_t bit_field_offset = from;
16250b57cec5SDimitry Andric   if (GetDataExtractor().GetByteOrder() == eByteOrderBig)
16260b57cec5SDimitry Andric     bit_field_offset =
162781ad6265SDimitry Andric         GetByteSize().value_or(0) * 8 - bit_field_size - bit_field_offset;
1628*a58f00eaSDimitry Andric 
16290b57cec5SDimitry Andric   // We haven't made a synthetic array member for INDEX yet, so lets make
16300b57cec5SDimitry Andric   // one and cache it for any future reference.
16310b57cec5SDimitry Andric   ValueObjectChild *synthetic_child = new ValueObjectChild(
1632*a58f00eaSDimitry Andric       *this, GetCompilerType(), index_const_str, GetByteSize().value_or(0), 0,
1633*a58f00eaSDimitry Andric       bit_field_size, bit_field_offset, false, false, eAddressTypeInvalid, 0);
16340b57cec5SDimitry Andric 
1635*a58f00eaSDimitry Andric   if (!synthetic_child)
1636*a58f00eaSDimitry Andric     return ValueObjectSP();
1637*a58f00eaSDimitry Andric 
1638*a58f00eaSDimitry Andric   // Cache the synthetic child's value because it's valid.
16390b57cec5SDimitry Andric   AddSyntheticChild(index_const_str, synthetic_child);
1640*a58f00eaSDimitry Andric   auto synthetic_child_sp = synthetic_child->GetSP();
16410b57cec5SDimitry Andric   synthetic_child_sp->SetName(ConstString(index_str));
1642fe6060f1SDimitry Andric   synthetic_child_sp->m_flags.m_is_bitfield_for_scalar = true;
16430b57cec5SDimitry Andric   return synthetic_child_sp;
16440b57cec5SDimitry Andric }
16450b57cec5SDimitry Andric 
GetSyntheticChildAtOffset(uint32_t offset,const CompilerType & type,bool can_create,ConstString name_const_str)16460b57cec5SDimitry Andric ValueObjectSP ValueObject::GetSyntheticChildAtOffset(
16470b57cec5SDimitry Andric     uint32_t offset, const CompilerType &type, bool can_create,
16480b57cec5SDimitry Andric     ConstString name_const_str) {
16490b57cec5SDimitry Andric 
16500b57cec5SDimitry Andric   ValueObjectSP synthetic_child_sp;
16510b57cec5SDimitry Andric 
1652*a58f00eaSDimitry Andric   if (name_const_str.IsEmpty())
1653e8d8bef9SDimitry Andric     name_const_str.SetString("@" + std::to_string(offset));
16540b57cec5SDimitry Andric 
16550b57cec5SDimitry Andric   // Check if we have already created a synthetic array member in this valid
16560b57cec5SDimitry Andric   // object. If we have we will re-use it.
16570b57cec5SDimitry Andric   synthetic_child_sp = GetSyntheticChild(name_const_str);
16580b57cec5SDimitry Andric 
16590b57cec5SDimitry Andric   if (synthetic_child_sp.get())
16600b57cec5SDimitry Andric     return synthetic_child_sp;
16610b57cec5SDimitry Andric 
16620b57cec5SDimitry Andric   if (!can_create)
1663*a58f00eaSDimitry Andric     return ValueObjectSP();
16640b57cec5SDimitry Andric 
16650b57cec5SDimitry Andric   ExecutionContext exe_ctx(GetExecutionContextRef());
1666bdd1243dSDimitry Andric   std::optional<uint64_t> size =
16670b57cec5SDimitry Andric       type.GetByteSize(exe_ctx.GetBestExecutionContextScope());
16680b57cec5SDimitry Andric   if (!size)
1669*a58f00eaSDimitry Andric     return ValueObjectSP();
16700b57cec5SDimitry Andric   ValueObjectChild *synthetic_child =
16710b57cec5SDimitry Andric       new ValueObjectChild(*this, type, name_const_str, *size, offset, 0, 0,
16720b57cec5SDimitry Andric                            false, false, eAddressTypeInvalid, 0);
16730b57cec5SDimitry Andric   if (synthetic_child) {
16740b57cec5SDimitry Andric     AddSyntheticChild(name_const_str, synthetic_child);
16750b57cec5SDimitry Andric     synthetic_child_sp = synthetic_child->GetSP();
16760b57cec5SDimitry Andric     synthetic_child_sp->SetName(name_const_str);
1677fe6060f1SDimitry Andric     synthetic_child_sp->m_flags.m_is_child_at_offset = true;
16780b57cec5SDimitry Andric   }
16790b57cec5SDimitry Andric   return synthetic_child_sp;
16800b57cec5SDimitry Andric }
16810b57cec5SDimitry Andric 
GetSyntheticBase(uint32_t offset,const CompilerType & type,bool can_create,ConstString name_const_str)16820b57cec5SDimitry Andric ValueObjectSP ValueObject::GetSyntheticBase(uint32_t offset,
16830b57cec5SDimitry Andric                                             const CompilerType &type,
16840b57cec5SDimitry Andric                                             bool can_create,
16850b57cec5SDimitry Andric                                             ConstString name_const_str) {
16860b57cec5SDimitry Andric   ValueObjectSP synthetic_child_sp;
16870b57cec5SDimitry Andric 
16880b57cec5SDimitry Andric   if (name_const_str.IsEmpty()) {
16890b57cec5SDimitry Andric     char name_str[128];
16900b57cec5SDimitry Andric     snprintf(name_str, sizeof(name_str), "base%s@%i",
16910b57cec5SDimitry Andric              type.GetTypeName().AsCString("<unknown>"), offset);
16920b57cec5SDimitry Andric     name_const_str.SetCString(name_str);
16930b57cec5SDimitry Andric   }
16940b57cec5SDimitry Andric 
16950b57cec5SDimitry Andric   // Check if we have already created a synthetic array member in this valid
16960b57cec5SDimitry Andric   // object. If we have we will re-use it.
16970b57cec5SDimitry Andric   synthetic_child_sp = GetSyntheticChild(name_const_str);
16980b57cec5SDimitry Andric 
16990b57cec5SDimitry Andric   if (synthetic_child_sp.get())
17000b57cec5SDimitry Andric     return synthetic_child_sp;
17010b57cec5SDimitry Andric 
17020b57cec5SDimitry Andric   if (!can_create)
1703*a58f00eaSDimitry Andric     return ValueObjectSP();
17040b57cec5SDimitry Andric 
17050b57cec5SDimitry Andric   const bool is_base_class = true;
17060b57cec5SDimitry Andric 
17070b57cec5SDimitry Andric   ExecutionContext exe_ctx(GetExecutionContextRef());
1708bdd1243dSDimitry Andric   std::optional<uint64_t> size =
17090b57cec5SDimitry Andric       type.GetByteSize(exe_ctx.GetBestExecutionContextScope());
17100b57cec5SDimitry Andric   if (!size)
1711*a58f00eaSDimitry Andric     return ValueObjectSP();
17120b57cec5SDimitry Andric   ValueObjectChild *synthetic_child =
17130b57cec5SDimitry Andric       new ValueObjectChild(*this, type, name_const_str, *size, offset, 0, 0,
17140b57cec5SDimitry Andric                            is_base_class, false, eAddressTypeInvalid, 0);
17150b57cec5SDimitry Andric   if (synthetic_child) {
17160b57cec5SDimitry Andric     AddSyntheticChild(name_const_str, synthetic_child);
17170b57cec5SDimitry Andric     synthetic_child_sp = synthetic_child->GetSP();
17180b57cec5SDimitry Andric     synthetic_child_sp->SetName(name_const_str);
17190b57cec5SDimitry Andric   }
17200b57cec5SDimitry Andric   return synthetic_child_sp;
17210b57cec5SDimitry Andric }
17220b57cec5SDimitry Andric 
17230b57cec5SDimitry Andric // your expression path needs to have a leading . or -> (unless it somehow
17240b57cec5SDimitry Andric // "looks like" an array, in which case it has a leading [ symbol). while the [
17250b57cec5SDimitry Andric // is meaningful and should be shown to the user, . and -> are just parser
17260b57cec5SDimitry Andric // design, but by no means added information for the user.. strip them off
SkipLeadingExpressionPathSeparators(const char * expression)17270b57cec5SDimitry Andric static const char *SkipLeadingExpressionPathSeparators(const char *expression) {
17280b57cec5SDimitry Andric   if (!expression || !expression[0])
17290b57cec5SDimitry Andric     return expression;
17300b57cec5SDimitry Andric   if (expression[0] == '.')
17310b57cec5SDimitry Andric     return expression + 1;
17320b57cec5SDimitry Andric   if (expression[0] == '-' && expression[1] == '>')
17330b57cec5SDimitry Andric     return expression + 2;
17340b57cec5SDimitry Andric   return expression;
17350b57cec5SDimitry Andric }
17360b57cec5SDimitry Andric 
17370b57cec5SDimitry Andric ValueObjectSP
GetSyntheticExpressionPathChild(const char * expression,bool can_create)17380b57cec5SDimitry Andric ValueObject::GetSyntheticExpressionPathChild(const char *expression,
17390b57cec5SDimitry Andric                                              bool can_create) {
17400b57cec5SDimitry Andric   ConstString name_const_string(expression);
17410b57cec5SDimitry Andric   // Check if we have already created a synthetic array member in this valid
17420b57cec5SDimitry Andric   // object. If we have we will re-use it.
1743*a58f00eaSDimitry Andric   if (auto existing_synthetic_child = GetSyntheticChild(name_const_string))
1744*a58f00eaSDimitry Andric     return existing_synthetic_child;
1745*a58f00eaSDimitry Andric 
17460b57cec5SDimitry Andric   // We haven't made a synthetic array member for expression yet, so lets
17470b57cec5SDimitry Andric   // make one and cache it for any future reference.
1748*a58f00eaSDimitry Andric   auto path_options = GetValueForExpressionPathOptions();
1749*a58f00eaSDimitry Andric   path_options.SetSyntheticChildrenTraversal(
1750*a58f00eaSDimitry Andric       GetValueForExpressionPathOptions::SyntheticChildrenTraversal::None);
1751*a58f00eaSDimitry Andric   auto synthetic_child =
1752*a58f00eaSDimitry Andric       GetValueForExpressionPath(expression, nullptr, nullptr, path_options);
17530b57cec5SDimitry Andric 
1754*a58f00eaSDimitry Andric   if (!synthetic_child)
1755*a58f00eaSDimitry Andric     return ValueObjectSP();
1756*a58f00eaSDimitry Andric 
1757*a58f00eaSDimitry Andric   // Cache the synthetic child's value because it's valid.
17580b57cec5SDimitry Andric   // FIXME: this causes a "real" child to end up with its name changed to
17590b57cec5SDimitry Andric   // the contents of expression
1760*a58f00eaSDimitry Andric   AddSyntheticChild(name_const_string, synthetic_child.get());
1761*a58f00eaSDimitry Andric   synthetic_child->SetName(
17620b57cec5SDimitry Andric       ConstString(SkipLeadingExpressionPathSeparators(expression)));
1763*a58f00eaSDimitry Andric   return synthetic_child;
17640b57cec5SDimitry Andric }
17650b57cec5SDimitry Andric 
CalculateSyntheticValue()17665ffd83dbSDimitry Andric void ValueObject::CalculateSyntheticValue() {
17670b57cec5SDimitry Andric   TargetSP target_sp(GetTargetSP());
17680b57cec5SDimitry Andric   if (target_sp && !target_sp->GetEnableSyntheticValue()) {
17690b57cec5SDimitry Andric     m_synthetic_value = nullptr;
17700b57cec5SDimitry Andric     return;
17710b57cec5SDimitry Andric   }
17720b57cec5SDimitry Andric 
17730b57cec5SDimitry Andric   lldb::SyntheticChildrenSP current_synth_sp(m_synthetic_children_sp);
17740b57cec5SDimitry Andric 
17750b57cec5SDimitry Andric   if (!UpdateFormatsIfNeeded() && m_synthetic_value)
17760b57cec5SDimitry Andric     return;
17770b57cec5SDimitry Andric 
17780b57cec5SDimitry Andric   if (m_synthetic_children_sp.get() == nullptr)
17790b57cec5SDimitry Andric     return;
17800b57cec5SDimitry Andric 
17810b57cec5SDimitry Andric   if (current_synth_sp == m_synthetic_children_sp && m_synthetic_value)
17820b57cec5SDimitry Andric     return;
17830b57cec5SDimitry Andric 
17840b57cec5SDimitry Andric   m_synthetic_value = new ValueObjectSynthetic(*this, m_synthetic_children_sp);
17850b57cec5SDimitry Andric }
17860b57cec5SDimitry Andric 
CalculateDynamicValue(DynamicValueType use_dynamic)17870b57cec5SDimitry Andric void ValueObject::CalculateDynamicValue(DynamicValueType use_dynamic) {
17880b57cec5SDimitry Andric   if (use_dynamic == eNoDynamicValues)
17890b57cec5SDimitry Andric     return;
17900b57cec5SDimitry Andric 
17910b57cec5SDimitry Andric   if (!m_dynamic_value && !IsDynamic()) {
17920b57cec5SDimitry Andric     ExecutionContext exe_ctx(GetExecutionContextRef());
17930b57cec5SDimitry Andric     Process *process = exe_ctx.GetProcessPtr();
17940b57cec5SDimitry Andric     if (process && process->IsPossibleDynamicValue(*this)) {
17950b57cec5SDimitry Andric       ClearDynamicTypeInformation();
17960b57cec5SDimitry Andric       m_dynamic_value = new ValueObjectDynamicValue(*this, use_dynamic);
17970b57cec5SDimitry Andric     }
17980b57cec5SDimitry Andric   }
17990b57cec5SDimitry Andric }
18000b57cec5SDimitry Andric 
GetDynamicValue(DynamicValueType use_dynamic)18010b57cec5SDimitry Andric ValueObjectSP ValueObject::GetDynamicValue(DynamicValueType use_dynamic) {
18020b57cec5SDimitry Andric   if (use_dynamic == eNoDynamicValues)
18030b57cec5SDimitry Andric     return ValueObjectSP();
18040b57cec5SDimitry Andric 
18050b57cec5SDimitry Andric   if (!IsDynamic() && m_dynamic_value == nullptr) {
18060b57cec5SDimitry Andric     CalculateDynamicValue(use_dynamic);
18070b57cec5SDimitry Andric   }
1808fe013be4SDimitry Andric   if (m_dynamic_value && m_dynamic_value->GetError().Success())
18090b57cec5SDimitry Andric     return m_dynamic_value->GetSP();
18100b57cec5SDimitry Andric   else
18110b57cec5SDimitry Andric     return ValueObjectSP();
18120b57cec5SDimitry Andric }
18130b57cec5SDimitry Andric 
GetSyntheticValue()18145ffd83dbSDimitry Andric ValueObjectSP ValueObject::GetSyntheticValue() {
18155ffd83dbSDimitry Andric   CalculateSyntheticValue();
18160b57cec5SDimitry Andric 
18170b57cec5SDimitry Andric   if (m_synthetic_value)
18180b57cec5SDimitry Andric     return m_synthetic_value->GetSP();
18190b57cec5SDimitry Andric   else
18200b57cec5SDimitry Andric     return ValueObjectSP();
18210b57cec5SDimitry Andric }
18220b57cec5SDimitry Andric 
HasSyntheticValue()18230b57cec5SDimitry Andric bool ValueObject::HasSyntheticValue() {
18240b57cec5SDimitry Andric   UpdateFormatsIfNeeded();
18250b57cec5SDimitry Andric 
18260b57cec5SDimitry Andric   if (m_synthetic_children_sp.get() == nullptr)
18270b57cec5SDimitry Andric     return false;
18280b57cec5SDimitry Andric 
18295ffd83dbSDimitry Andric   CalculateSyntheticValue();
18300b57cec5SDimitry Andric 
18310b57cec5SDimitry Andric   return m_synthetic_value != nullptr;
18320b57cec5SDimitry Andric }
18330b57cec5SDimitry Andric 
GetNonBaseClassParent()18340b57cec5SDimitry Andric ValueObject *ValueObject::GetNonBaseClassParent() {
18350b57cec5SDimitry Andric   if (GetParent()) {
18360b57cec5SDimitry Andric     if (GetParent()->IsBaseClass())
18370b57cec5SDimitry Andric       return GetParent()->GetNonBaseClassParent();
18380b57cec5SDimitry Andric     else
18390b57cec5SDimitry Andric       return GetParent();
18400b57cec5SDimitry Andric   }
18410b57cec5SDimitry Andric   return nullptr;
18420b57cec5SDimitry Andric }
18430b57cec5SDimitry Andric 
IsBaseClass(uint32_t & depth)18440b57cec5SDimitry Andric bool ValueObject::IsBaseClass(uint32_t &depth) {
18450b57cec5SDimitry Andric   if (!IsBaseClass()) {
18460b57cec5SDimitry Andric     depth = 0;
18470b57cec5SDimitry Andric     return false;
18480b57cec5SDimitry Andric   }
18490b57cec5SDimitry Andric   if (GetParent()) {
18500b57cec5SDimitry Andric     GetParent()->IsBaseClass(depth);
18510b57cec5SDimitry Andric     depth = depth + 1;
18520b57cec5SDimitry Andric     return true;
18530b57cec5SDimitry Andric   }
18540b57cec5SDimitry Andric   // TODO: a base of no parent? weird..
18550b57cec5SDimitry Andric   depth = 1;
18560b57cec5SDimitry Andric   return true;
18570b57cec5SDimitry Andric }
18580b57cec5SDimitry Andric 
GetExpressionPath(Stream & s,GetExpressionPathFormat epformat)18595ffd83dbSDimitry Andric void ValueObject::GetExpressionPath(Stream &s,
18600b57cec5SDimitry Andric                                     GetExpressionPathFormat epformat) {
18610b57cec5SDimitry Andric   // synthetic children do not actually "exist" as part of the hierarchy, and
18620b57cec5SDimitry Andric   // sometimes they are consed up in ways that don't make sense from an
18630b57cec5SDimitry Andric   // underlying language/API standpoint. So, use a special code path here to
18640b57cec5SDimitry Andric   // return something that can hopefully be used in expression
1865fe6060f1SDimitry Andric   if (m_flags.m_is_synthetic_children_generated) {
18660b57cec5SDimitry Andric     UpdateValueIfNeeded();
18670b57cec5SDimitry Andric 
1868fe6060f1SDimitry Andric     if (m_value.GetValueType() == Value::ValueType::LoadAddress) {
18690b57cec5SDimitry Andric       if (IsPointerOrReferenceType()) {
18700b57cec5SDimitry Andric         s.Printf("((%s)0x%" PRIx64 ")", GetTypeName().AsCString("void"),
18710b57cec5SDimitry Andric                  GetValueAsUnsigned(0));
18720b57cec5SDimitry Andric         return;
18730b57cec5SDimitry Andric       } else {
18740b57cec5SDimitry Andric         uint64_t load_addr =
18750b57cec5SDimitry Andric             m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
18760b57cec5SDimitry Andric         if (load_addr != LLDB_INVALID_ADDRESS) {
18770b57cec5SDimitry Andric           s.Printf("(*( (%s *)0x%" PRIx64 "))", GetTypeName().AsCString("void"),
18780b57cec5SDimitry Andric                    load_addr);
18790b57cec5SDimitry Andric           return;
18800b57cec5SDimitry Andric         }
18810b57cec5SDimitry Andric       }
18820b57cec5SDimitry Andric     }
18830b57cec5SDimitry Andric 
18840b57cec5SDimitry Andric     if (CanProvideValue()) {
18850b57cec5SDimitry Andric       s.Printf("((%s)%s)", GetTypeName().AsCString("void"),
18860b57cec5SDimitry Andric                GetValueAsCString());
18870b57cec5SDimitry Andric       return;
18880b57cec5SDimitry Andric     }
18890b57cec5SDimitry Andric 
18900b57cec5SDimitry Andric     return;
18910b57cec5SDimitry Andric   }
18920b57cec5SDimitry Andric 
18930b57cec5SDimitry Andric   const bool is_deref_of_parent = IsDereferenceOfParent();
18940b57cec5SDimitry Andric 
18950b57cec5SDimitry Andric   if (is_deref_of_parent &&
18960b57cec5SDimitry Andric       epformat == eGetExpressionPathFormatDereferencePointers) {
18970b57cec5SDimitry Andric     // this is the original format of GetExpressionPath() producing code like
18980b57cec5SDimitry Andric     // *(a_ptr).memberName, which is entirely fine, until you put this into
18990b57cec5SDimitry Andric     // StackFrame::GetValueForVariableExpressionPath() which prefers to see
19000b57cec5SDimitry Andric     // a_ptr->memberName. the eHonorPointers mode is meant to produce strings
19010b57cec5SDimitry Andric     // in this latter format
19020b57cec5SDimitry Andric     s.PutCString("*(");
19030b57cec5SDimitry Andric   }
19040b57cec5SDimitry Andric 
19050b57cec5SDimitry Andric   ValueObject *parent = GetParent();
19060b57cec5SDimitry Andric 
19070b57cec5SDimitry Andric   if (parent)
19085ffd83dbSDimitry Andric     parent->GetExpressionPath(s, epformat);
19090b57cec5SDimitry Andric 
19100b57cec5SDimitry Andric   // if we are a deref_of_parent just because we are synthetic array members
19110b57cec5SDimitry Andric   // made up to allow ptr[%d] syntax to work in variable printing, then add our
19120b57cec5SDimitry Andric   // name ([%d]) to the expression path
1913fe6060f1SDimitry Andric   if (m_flags.m_is_array_item_for_pointer &&
19140b57cec5SDimitry Andric       epformat == eGetExpressionPathFormatHonorPointers)
19155ffd83dbSDimitry Andric     s.PutCString(m_name.GetStringRef());
19160b57cec5SDimitry Andric 
19170b57cec5SDimitry Andric   if (!IsBaseClass()) {
19180b57cec5SDimitry Andric     if (!is_deref_of_parent) {
19190b57cec5SDimitry Andric       ValueObject *non_base_class_parent = GetNonBaseClassParent();
19200b57cec5SDimitry Andric       if (non_base_class_parent &&
19210b57cec5SDimitry Andric           !non_base_class_parent->GetName().IsEmpty()) {
19220b57cec5SDimitry Andric         CompilerType non_base_class_parent_compiler_type =
19230b57cec5SDimitry Andric             non_base_class_parent->GetCompilerType();
19240b57cec5SDimitry Andric         if (non_base_class_parent_compiler_type) {
19250b57cec5SDimitry Andric           if (parent && parent->IsDereferenceOfParent() &&
19260b57cec5SDimitry Andric               epformat == eGetExpressionPathFormatHonorPointers) {
19270b57cec5SDimitry Andric             s.PutCString("->");
19280b57cec5SDimitry Andric           } else {
19290b57cec5SDimitry Andric             const uint32_t non_base_class_parent_type_info =
19300b57cec5SDimitry Andric                 non_base_class_parent_compiler_type.GetTypeInfo();
19310b57cec5SDimitry Andric 
19320b57cec5SDimitry Andric             if (non_base_class_parent_type_info & eTypeIsPointer) {
19330b57cec5SDimitry Andric               s.PutCString("->");
19340b57cec5SDimitry Andric             } else if ((non_base_class_parent_type_info & eTypeHasChildren) &&
19350b57cec5SDimitry Andric                        !(non_base_class_parent_type_info & eTypeIsArray)) {
19360b57cec5SDimitry Andric               s.PutChar('.');
19370b57cec5SDimitry Andric             }
19380b57cec5SDimitry Andric           }
19390b57cec5SDimitry Andric         }
19400b57cec5SDimitry Andric       }
19410b57cec5SDimitry Andric 
19420b57cec5SDimitry Andric       const char *name = GetName().GetCString();
19435ffd83dbSDimitry Andric       if (name)
19440b57cec5SDimitry Andric         s.PutCString(name);
19450b57cec5SDimitry Andric     }
19460b57cec5SDimitry Andric   }
19470b57cec5SDimitry Andric 
19480b57cec5SDimitry Andric   if (is_deref_of_parent &&
19490b57cec5SDimitry Andric       epformat == eGetExpressionPathFormatDereferencePointers) {
19500b57cec5SDimitry Andric     s.PutChar(')');
19510b57cec5SDimitry Andric   }
19520b57cec5SDimitry Andric }
19530b57cec5SDimitry Andric 
GetValueForExpressionPath(llvm::StringRef expression,ExpressionPathScanEndReason * reason_to_stop,ExpressionPathEndResultType * final_value_type,const GetValueForExpressionPathOptions & options,ExpressionPathAftermath * final_task_on_target)19540b57cec5SDimitry Andric ValueObjectSP ValueObject::GetValueForExpressionPath(
19550b57cec5SDimitry Andric     llvm::StringRef expression, ExpressionPathScanEndReason *reason_to_stop,
19560b57cec5SDimitry Andric     ExpressionPathEndResultType *final_value_type,
19570b57cec5SDimitry Andric     const GetValueForExpressionPathOptions &options,
19580b57cec5SDimitry Andric     ExpressionPathAftermath *final_task_on_target) {
19590b57cec5SDimitry Andric 
1960*a58f00eaSDimitry Andric   auto dummy_stop_reason = eExpressionPathScanEndReasonUnknown;
1961*a58f00eaSDimitry Andric   auto dummy_value_type = eExpressionPathEndResultTypeInvalid;
1962*a58f00eaSDimitry Andric   auto dummy_final_task = eExpressionPathAftermathNothing;
19630b57cec5SDimitry Andric 
1964*a58f00eaSDimitry Andric   auto proxy_stop_reason = reason_to_stop ? reason_to_stop : &dummy_stop_reason;
1965*a58f00eaSDimitry Andric   auto proxy_value_type =
1966*a58f00eaSDimitry Andric       final_value_type ? final_value_type : &dummy_value_type;
1967*a58f00eaSDimitry Andric   auto proxy_final_task =
1968*a58f00eaSDimitry Andric       final_task_on_target ? final_task_on_target : &dummy_final_task;
19690b57cec5SDimitry Andric 
1970*a58f00eaSDimitry Andric   auto ret_value = GetValueForExpressionPath_Impl(expression, proxy_stop_reason,
1971*a58f00eaSDimitry Andric                                                   proxy_value_type, options,
1972*a58f00eaSDimitry Andric                                                   proxy_final_task);
19730b57cec5SDimitry Andric 
1974*a58f00eaSDimitry Andric   // The caller knows nothing happened if `final_task_on_target` doesn't change.
1975*a58f00eaSDimitry Andric   if (!ret_value || (*proxy_value_type) != eExpressionPathEndResultTypePlain ||
1976*a58f00eaSDimitry Andric       !final_task_on_target)
19770b57cec5SDimitry Andric     return ValueObjectSP();
1978*a58f00eaSDimitry Andric 
1979*a58f00eaSDimitry Andric   ExpressionPathAftermath &final_task_on_target_ref = (*final_task_on_target);
1980*a58f00eaSDimitry Andric   ExpressionPathScanEndReason stop_reason_for_error;
19810b57cec5SDimitry Andric   Status error;
1982*a58f00eaSDimitry Andric   // The method can only dereference and take the address of plain objects.
1983*a58f00eaSDimitry Andric   switch (final_task_on_target_ref) {
1984*a58f00eaSDimitry Andric   case eExpressionPathAftermathNothing:
1985*a58f00eaSDimitry Andric     return ret_value;
1986*a58f00eaSDimitry Andric 
1987*a58f00eaSDimitry Andric   case eExpressionPathAftermathDereference:
1988*a58f00eaSDimitry Andric     ret_value = ret_value->Dereference(error);
1989*a58f00eaSDimitry Andric     stop_reason_for_error = eExpressionPathScanEndReasonDereferencingFailed;
1990*a58f00eaSDimitry Andric     break;
1991*a58f00eaSDimitry Andric 
1992*a58f00eaSDimitry Andric   case eExpressionPathAftermathTakeAddress:
1993*a58f00eaSDimitry Andric     ret_value = ret_value->AddressOf(error);
1994*a58f00eaSDimitry Andric     stop_reason_for_error = eExpressionPathScanEndReasonTakingAddressFailed;
1995*a58f00eaSDimitry Andric     break;
1996*a58f00eaSDimitry Andric   }
1997*a58f00eaSDimitry Andric 
1998*a58f00eaSDimitry Andric   if (ret_value && error.Success()) {
1999*a58f00eaSDimitry Andric     final_task_on_target_ref = eExpressionPathAftermathNothing;
2000*a58f00eaSDimitry Andric     return ret_value;
2001*a58f00eaSDimitry Andric   }
2002*a58f00eaSDimitry Andric 
20030b57cec5SDimitry Andric   if (reason_to_stop)
2004*a58f00eaSDimitry Andric     *reason_to_stop = stop_reason_for_error;
2005*a58f00eaSDimitry Andric 
20060b57cec5SDimitry Andric   if (final_value_type)
2007*a58f00eaSDimitry Andric     *final_value_type = eExpressionPathEndResultTypeInvalid;
20080b57cec5SDimitry Andric   return ValueObjectSP();
20090b57cec5SDimitry Andric }
20100b57cec5SDimitry Andric 
GetValueForExpressionPath_Impl(llvm::StringRef expression,ExpressionPathScanEndReason * reason_to_stop,ExpressionPathEndResultType * final_result,const GetValueForExpressionPathOptions & options,ExpressionPathAftermath * what_next)20110b57cec5SDimitry Andric ValueObjectSP ValueObject::GetValueForExpressionPath_Impl(
20120b57cec5SDimitry Andric     llvm::StringRef expression, ExpressionPathScanEndReason *reason_to_stop,
20130b57cec5SDimitry Andric     ExpressionPathEndResultType *final_result,
20140b57cec5SDimitry Andric     const GetValueForExpressionPathOptions &options,
20150b57cec5SDimitry Andric     ExpressionPathAftermath *what_next) {
20160b57cec5SDimitry Andric   ValueObjectSP root = GetSP();
20170b57cec5SDimitry Andric 
20180b57cec5SDimitry Andric   if (!root)
20190b57cec5SDimitry Andric     return nullptr;
20200b57cec5SDimitry Andric 
20210b57cec5SDimitry Andric   llvm::StringRef remainder = expression;
20220b57cec5SDimitry Andric 
20230b57cec5SDimitry Andric   while (true) {
20240b57cec5SDimitry Andric     llvm::StringRef temp_expression = remainder;
20250b57cec5SDimitry Andric 
20260b57cec5SDimitry Andric     CompilerType root_compiler_type = root->GetCompilerType();
20270b57cec5SDimitry Andric     CompilerType pointee_compiler_type;
20280b57cec5SDimitry Andric     Flags pointee_compiler_type_info;
20290b57cec5SDimitry Andric 
20300b57cec5SDimitry Andric     Flags root_compiler_type_info(
20310b57cec5SDimitry Andric         root_compiler_type.GetTypeInfo(&pointee_compiler_type));
20320b57cec5SDimitry Andric     if (pointee_compiler_type)
20330b57cec5SDimitry Andric       pointee_compiler_type_info.Reset(pointee_compiler_type.GetTypeInfo());
20340b57cec5SDimitry Andric 
20350b57cec5SDimitry Andric     if (temp_expression.empty()) {
20360b57cec5SDimitry Andric       *reason_to_stop = ValueObject::eExpressionPathScanEndReasonEndOfString;
20370b57cec5SDimitry Andric       return root;
20380b57cec5SDimitry Andric     }
20390b57cec5SDimitry Andric 
20400b57cec5SDimitry Andric     switch (temp_expression.front()) {
20410b57cec5SDimitry Andric     case '-': {
20420b57cec5SDimitry Andric       temp_expression = temp_expression.drop_front();
20430b57cec5SDimitry Andric       if (options.m_check_dot_vs_arrow_syntax &&
20440b57cec5SDimitry Andric           root_compiler_type_info.Test(eTypeIsPointer)) // if you are trying to
20450b57cec5SDimitry Andric                                                         // use -> on a
20460b57cec5SDimitry Andric                                                         // non-pointer and I
20470b57cec5SDimitry Andric                                                         // must catch the error
20480b57cec5SDimitry Andric       {
20490b57cec5SDimitry Andric         *reason_to_stop =
20500b57cec5SDimitry Andric             ValueObject::eExpressionPathScanEndReasonArrowInsteadOfDot;
20510b57cec5SDimitry Andric         *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
20520b57cec5SDimitry Andric         return ValueObjectSP();
20530b57cec5SDimitry Andric       }
20540b57cec5SDimitry Andric       if (root_compiler_type_info.Test(eTypeIsObjC) && // if yo are trying to
20550b57cec5SDimitry Andric                                                        // extract an ObjC IVar
20560b57cec5SDimitry Andric                                                        // when this is forbidden
20570b57cec5SDimitry Andric           root_compiler_type_info.Test(eTypeIsPointer) &&
20580b57cec5SDimitry Andric           options.m_no_fragile_ivar) {
20590b57cec5SDimitry Andric         *reason_to_stop =
20600b57cec5SDimitry Andric             ValueObject::eExpressionPathScanEndReasonFragileIVarNotAllowed;
20610b57cec5SDimitry Andric         *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
20620b57cec5SDimitry Andric         return ValueObjectSP();
20630b57cec5SDimitry Andric       }
2064c9157d92SDimitry Andric       if (!temp_expression.starts_with(">")) {
20650b57cec5SDimitry Andric         *reason_to_stop =
20660b57cec5SDimitry Andric             ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol;
20670b57cec5SDimitry Andric         *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
20680b57cec5SDimitry Andric         return ValueObjectSP();
20690b57cec5SDimitry Andric       }
20700b57cec5SDimitry Andric     }
2071bdd1243dSDimitry Andric       [[fallthrough]];
20720b57cec5SDimitry Andric     case '.': // or fallthrough from ->
20730b57cec5SDimitry Andric     {
20740b57cec5SDimitry Andric       if (options.m_check_dot_vs_arrow_syntax &&
20750b57cec5SDimitry Andric           temp_expression.front() == '.' &&
20760b57cec5SDimitry Andric           root_compiler_type_info.Test(eTypeIsPointer)) // if you are trying to
20770b57cec5SDimitry Andric                                                         // use . on a pointer
20780b57cec5SDimitry Andric                                                         // and I must catch the
20790b57cec5SDimitry Andric                                                         // error
20800b57cec5SDimitry Andric       {
20810b57cec5SDimitry Andric         *reason_to_stop =
20820b57cec5SDimitry Andric             ValueObject::eExpressionPathScanEndReasonDotInsteadOfArrow;
20830b57cec5SDimitry Andric         *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
20840b57cec5SDimitry Andric         return nullptr;
20850b57cec5SDimitry Andric       }
20860b57cec5SDimitry Andric       temp_expression = temp_expression.drop_front(); // skip . or >
20870b57cec5SDimitry Andric 
20880b57cec5SDimitry Andric       size_t next_sep_pos = temp_expression.find_first_of("-.[", 1);
20890b57cec5SDimitry Andric       if (next_sep_pos == llvm::StringRef::npos) // if no other separator just
20900b57cec5SDimitry Andric                                                  // expand this last layer
20910b57cec5SDimitry Andric       {
2092c9157d92SDimitry Andric         llvm::StringRef child_name = temp_expression;
20930b57cec5SDimitry Andric         ValueObjectSP child_valobj_sp =
2094fe013be4SDimitry Andric             root->GetChildMemberWithName(child_name);
20950b57cec5SDimitry Andric 
20960b57cec5SDimitry Andric         if (child_valobj_sp.get()) // we know we are done, so just return
20970b57cec5SDimitry Andric         {
20980b57cec5SDimitry Andric           *reason_to_stop =
20990b57cec5SDimitry Andric               ValueObject::eExpressionPathScanEndReasonEndOfString;
21000b57cec5SDimitry Andric           *final_result = ValueObject::eExpressionPathEndResultTypePlain;
21010b57cec5SDimitry Andric           return child_valobj_sp;
21020b57cec5SDimitry Andric         } else {
21030b57cec5SDimitry Andric           switch (options.m_synthetic_children_traversal) {
21040b57cec5SDimitry Andric           case GetValueForExpressionPathOptions::SyntheticChildrenTraversal::
21050b57cec5SDimitry Andric               None:
21060b57cec5SDimitry Andric             break;
21070b57cec5SDimitry Andric           case GetValueForExpressionPathOptions::SyntheticChildrenTraversal::
21080b57cec5SDimitry Andric               FromSynthetic:
21090b57cec5SDimitry Andric             if (root->IsSynthetic()) {
21100b57cec5SDimitry Andric               child_valobj_sp = root->GetNonSyntheticValue();
21110b57cec5SDimitry Andric               if (child_valobj_sp.get())
21120b57cec5SDimitry Andric                 child_valobj_sp =
2113fe013be4SDimitry Andric                     child_valobj_sp->GetChildMemberWithName(child_name);
21140b57cec5SDimitry Andric             }
21150b57cec5SDimitry Andric             break;
21160b57cec5SDimitry Andric           case GetValueForExpressionPathOptions::SyntheticChildrenTraversal::
21170b57cec5SDimitry Andric               ToSynthetic:
21180b57cec5SDimitry Andric             if (!root->IsSynthetic()) {
21190b57cec5SDimitry Andric               child_valobj_sp = root->GetSyntheticValue();
21200b57cec5SDimitry Andric               if (child_valobj_sp.get())
21210b57cec5SDimitry Andric                 child_valobj_sp =
2122fe013be4SDimitry Andric                     child_valobj_sp->GetChildMemberWithName(child_name);
21230b57cec5SDimitry Andric             }
21240b57cec5SDimitry Andric             break;
21250b57cec5SDimitry Andric           case GetValueForExpressionPathOptions::SyntheticChildrenTraversal::
21260b57cec5SDimitry Andric               Both:
21270b57cec5SDimitry Andric             if (root->IsSynthetic()) {
21280b57cec5SDimitry Andric               child_valobj_sp = root->GetNonSyntheticValue();
21290b57cec5SDimitry Andric               if (child_valobj_sp.get())
21300b57cec5SDimitry Andric                 child_valobj_sp =
2131fe013be4SDimitry Andric                     child_valobj_sp->GetChildMemberWithName(child_name);
21320b57cec5SDimitry Andric             } else {
21330b57cec5SDimitry Andric               child_valobj_sp = root->GetSyntheticValue();
21340b57cec5SDimitry Andric               if (child_valobj_sp.get())
21350b57cec5SDimitry Andric                 child_valobj_sp =
2136fe013be4SDimitry Andric                     child_valobj_sp->GetChildMemberWithName(child_name);
21370b57cec5SDimitry Andric             }
21380b57cec5SDimitry Andric             break;
21390b57cec5SDimitry Andric           }
21400b57cec5SDimitry Andric         }
21410b57cec5SDimitry Andric 
21420b57cec5SDimitry Andric         // if we are here and options.m_no_synthetic_children is true,
21430b57cec5SDimitry Andric         // child_valobj_sp is going to be a NULL SP, so we hit the "else"
21440b57cec5SDimitry Andric         // branch, and return an error
21450b57cec5SDimitry Andric         if (child_valobj_sp.get()) // if it worked, just return
21460b57cec5SDimitry Andric         {
21470b57cec5SDimitry Andric           *reason_to_stop =
21480b57cec5SDimitry Andric               ValueObject::eExpressionPathScanEndReasonEndOfString;
21490b57cec5SDimitry Andric           *final_result = ValueObject::eExpressionPathEndResultTypePlain;
21500b57cec5SDimitry Andric           return child_valobj_sp;
21510b57cec5SDimitry Andric         } else {
21520b57cec5SDimitry Andric           *reason_to_stop =
21530b57cec5SDimitry Andric               ValueObject::eExpressionPathScanEndReasonNoSuchChild;
21540b57cec5SDimitry Andric           *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
21550b57cec5SDimitry Andric           return nullptr;
21560b57cec5SDimitry Andric         }
21570b57cec5SDimitry Andric       } else // other layers do expand
21580b57cec5SDimitry Andric       {
21590b57cec5SDimitry Andric         llvm::StringRef next_separator = temp_expression.substr(next_sep_pos);
2160c9157d92SDimitry Andric         llvm::StringRef child_name = temp_expression.slice(0, next_sep_pos);
21610b57cec5SDimitry Andric 
21620b57cec5SDimitry Andric         ValueObjectSP child_valobj_sp =
2163fe013be4SDimitry Andric             root->GetChildMemberWithName(child_name);
21640b57cec5SDimitry Andric         if (child_valobj_sp.get()) // store the new root and move on
21650b57cec5SDimitry Andric         {
21660b57cec5SDimitry Andric           root = child_valobj_sp;
21670b57cec5SDimitry Andric           remainder = next_separator;
21680b57cec5SDimitry Andric           *final_result = ValueObject::eExpressionPathEndResultTypePlain;
21690b57cec5SDimitry Andric           continue;
21700b57cec5SDimitry Andric         } else {
21710b57cec5SDimitry Andric           switch (options.m_synthetic_children_traversal) {
21720b57cec5SDimitry Andric           case GetValueForExpressionPathOptions::SyntheticChildrenTraversal::
21730b57cec5SDimitry Andric               None:
21740b57cec5SDimitry Andric             break;
21750b57cec5SDimitry Andric           case GetValueForExpressionPathOptions::SyntheticChildrenTraversal::
21760b57cec5SDimitry Andric               FromSynthetic:
21770b57cec5SDimitry Andric             if (root->IsSynthetic()) {
21780b57cec5SDimitry Andric               child_valobj_sp = root->GetNonSyntheticValue();
21790b57cec5SDimitry Andric               if (child_valobj_sp.get())
21800b57cec5SDimitry Andric                 child_valobj_sp =
2181fe013be4SDimitry Andric                     child_valobj_sp->GetChildMemberWithName(child_name);
21820b57cec5SDimitry Andric             }
21830b57cec5SDimitry Andric             break;
21840b57cec5SDimitry Andric           case GetValueForExpressionPathOptions::SyntheticChildrenTraversal::
21850b57cec5SDimitry Andric               ToSynthetic:
21860b57cec5SDimitry Andric             if (!root->IsSynthetic()) {
21870b57cec5SDimitry Andric               child_valobj_sp = root->GetSyntheticValue();
21880b57cec5SDimitry Andric               if (child_valobj_sp.get())
21890b57cec5SDimitry Andric                 child_valobj_sp =
2190fe013be4SDimitry Andric                     child_valobj_sp->GetChildMemberWithName(child_name);
21910b57cec5SDimitry Andric             }
21920b57cec5SDimitry Andric             break;
21930b57cec5SDimitry Andric           case GetValueForExpressionPathOptions::SyntheticChildrenTraversal::
21940b57cec5SDimitry Andric               Both:
21950b57cec5SDimitry Andric             if (root->IsSynthetic()) {
21960b57cec5SDimitry Andric               child_valobj_sp = root->GetNonSyntheticValue();
21970b57cec5SDimitry Andric               if (child_valobj_sp.get())
21980b57cec5SDimitry Andric                 child_valobj_sp =
2199fe013be4SDimitry Andric                     child_valobj_sp->GetChildMemberWithName(child_name);
22000b57cec5SDimitry Andric             } else {
22010b57cec5SDimitry Andric               child_valobj_sp = root->GetSyntheticValue();
22020b57cec5SDimitry Andric               if (child_valobj_sp.get())
22030b57cec5SDimitry Andric                 child_valobj_sp =
2204fe013be4SDimitry Andric                     child_valobj_sp->GetChildMemberWithName(child_name);
22050b57cec5SDimitry Andric             }
22060b57cec5SDimitry Andric             break;
22070b57cec5SDimitry Andric           }
22080b57cec5SDimitry Andric         }
22090b57cec5SDimitry Andric 
22100b57cec5SDimitry Andric         // if we are here and options.m_no_synthetic_children is true,
22110b57cec5SDimitry Andric         // child_valobj_sp is going to be a NULL SP, so we hit the "else"
22120b57cec5SDimitry Andric         // branch, and return an error
22130b57cec5SDimitry Andric         if (child_valobj_sp.get()) // if it worked, move on
22140b57cec5SDimitry Andric         {
22150b57cec5SDimitry Andric           root = child_valobj_sp;
22160b57cec5SDimitry Andric           remainder = next_separator;
22170b57cec5SDimitry Andric           *final_result = ValueObject::eExpressionPathEndResultTypePlain;
22180b57cec5SDimitry Andric           continue;
22190b57cec5SDimitry Andric         } else {
22200b57cec5SDimitry Andric           *reason_to_stop =
22210b57cec5SDimitry Andric               ValueObject::eExpressionPathScanEndReasonNoSuchChild;
22220b57cec5SDimitry Andric           *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
22230b57cec5SDimitry Andric           return nullptr;
22240b57cec5SDimitry Andric         }
22250b57cec5SDimitry Andric       }
22260b57cec5SDimitry Andric       break;
22270b57cec5SDimitry Andric     }
22280b57cec5SDimitry Andric     case '[': {
22290b57cec5SDimitry Andric       if (!root_compiler_type_info.Test(eTypeIsArray) &&
22300b57cec5SDimitry Andric           !root_compiler_type_info.Test(eTypeIsPointer) &&
22310b57cec5SDimitry Andric           !root_compiler_type_info.Test(
22320b57cec5SDimitry Andric               eTypeIsVector)) // if this is not a T[] nor a T*
22330b57cec5SDimitry Andric       {
22340b57cec5SDimitry Andric         if (!root_compiler_type_info.Test(
22350b57cec5SDimitry Andric                 eTypeIsScalar)) // if this is not even a scalar...
22360b57cec5SDimitry Andric         {
22370b57cec5SDimitry Andric           if (options.m_synthetic_children_traversal ==
22380b57cec5SDimitry Andric               GetValueForExpressionPathOptions::SyntheticChildrenTraversal::
22390b57cec5SDimitry Andric                   None) // ...only chance left is synthetic
22400b57cec5SDimitry Andric           {
22410b57cec5SDimitry Andric             *reason_to_stop =
22420b57cec5SDimitry Andric                 ValueObject::eExpressionPathScanEndReasonRangeOperatorInvalid;
22430b57cec5SDimitry Andric             *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
22440b57cec5SDimitry Andric             return ValueObjectSP();
22450b57cec5SDimitry Andric           }
22460b57cec5SDimitry Andric         } else if (!options.m_allow_bitfields_syntax) // if this is a scalar,
22470b57cec5SDimitry Andric                                                       // check that we can
22480b57cec5SDimitry Andric                                                       // expand bitfields
22490b57cec5SDimitry Andric         {
22500b57cec5SDimitry Andric           *reason_to_stop =
22510b57cec5SDimitry Andric               ValueObject::eExpressionPathScanEndReasonRangeOperatorNotAllowed;
22520b57cec5SDimitry Andric           *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
22530b57cec5SDimitry Andric           return ValueObjectSP();
22540b57cec5SDimitry Andric         }
22550b57cec5SDimitry Andric       }
22560b57cec5SDimitry Andric       if (temp_expression[1] ==
22570b57cec5SDimitry Andric           ']') // if this is an unbounded range it only works for arrays
22580b57cec5SDimitry Andric       {
22590b57cec5SDimitry Andric         if (!root_compiler_type_info.Test(eTypeIsArray)) {
22600b57cec5SDimitry Andric           *reason_to_stop =
22610b57cec5SDimitry Andric               ValueObject::eExpressionPathScanEndReasonEmptyRangeNotAllowed;
22620b57cec5SDimitry Andric           *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
22630b57cec5SDimitry Andric           return nullptr;
22640b57cec5SDimitry Andric         } else // even if something follows, we cannot expand unbounded ranges,
22650b57cec5SDimitry Andric                // just let the caller do it
22660b57cec5SDimitry Andric         {
22670b57cec5SDimitry Andric           *reason_to_stop =
22680b57cec5SDimitry Andric               ValueObject::eExpressionPathScanEndReasonArrayRangeOperatorMet;
22690b57cec5SDimitry Andric           *final_result =
22700b57cec5SDimitry Andric               ValueObject::eExpressionPathEndResultTypeUnboundedRange;
22710b57cec5SDimitry Andric           return root;
22720b57cec5SDimitry Andric         }
22730b57cec5SDimitry Andric       }
22740b57cec5SDimitry Andric 
22750b57cec5SDimitry Andric       size_t close_bracket_position = temp_expression.find(']', 1);
22760b57cec5SDimitry Andric       if (close_bracket_position ==
22770b57cec5SDimitry Andric           llvm::StringRef::npos) // if there is no ], this is a syntax error
22780b57cec5SDimitry Andric       {
22790b57cec5SDimitry Andric         *reason_to_stop =
22800b57cec5SDimitry Andric             ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol;
22810b57cec5SDimitry Andric         *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
22820b57cec5SDimitry Andric         return nullptr;
22830b57cec5SDimitry Andric       }
22840b57cec5SDimitry Andric 
22850b57cec5SDimitry Andric       llvm::StringRef bracket_expr =
22860b57cec5SDimitry Andric           temp_expression.slice(1, close_bracket_position);
22870b57cec5SDimitry Andric 
22880b57cec5SDimitry Andric       // If this was an empty expression it would have been caught by the if
22890b57cec5SDimitry Andric       // above.
22900b57cec5SDimitry Andric       assert(!bracket_expr.empty());
22910b57cec5SDimitry Andric 
22920b57cec5SDimitry Andric       if (!bracket_expr.contains('-')) {
22930b57cec5SDimitry Andric         // if no separator, this is of the form [N].  Note that this cannot be
22940b57cec5SDimitry Andric         // an unbounded range of the form [], because that case was handled
22950b57cec5SDimitry Andric         // above with an unconditional return.
22960b57cec5SDimitry Andric         unsigned long index = 0;
22970b57cec5SDimitry Andric         if (bracket_expr.getAsInteger(0, index)) {
22980b57cec5SDimitry Andric           *reason_to_stop =
22990b57cec5SDimitry Andric               ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol;
23000b57cec5SDimitry Andric           *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
23010b57cec5SDimitry Andric           return nullptr;
23020b57cec5SDimitry Andric         }
23030b57cec5SDimitry Andric 
23040b57cec5SDimitry Andric         // from here on we do have a valid index
23050b57cec5SDimitry Andric         if (root_compiler_type_info.Test(eTypeIsArray)) {
2306fe013be4SDimitry Andric           ValueObjectSP child_valobj_sp = root->GetChildAtIndex(index);
23070b57cec5SDimitry Andric           if (!child_valobj_sp)
23080b57cec5SDimitry Andric             child_valobj_sp = root->GetSyntheticArrayMember(index, true);
23090b57cec5SDimitry Andric           if (!child_valobj_sp)
23100b57cec5SDimitry Andric             if (root->HasSyntheticValue() &&
23110b57cec5SDimitry Andric                 root->GetSyntheticValue()->GetNumChildren() > index)
23120b57cec5SDimitry Andric               child_valobj_sp =
2313fe013be4SDimitry Andric                   root->GetSyntheticValue()->GetChildAtIndex(index);
23140b57cec5SDimitry Andric           if (child_valobj_sp) {
23150b57cec5SDimitry Andric             root = child_valobj_sp;
23160b57cec5SDimitry Andric             remainder =
23170b57cec5SDimitry Andric                 temp_expression.substr(close_bracket_position + 1); // skip ]
23180b57cec5SDimitry Andric             *final_result = ValueObject::eExpressionPathEndResultTypePlain;
23190b57cec5SDimitry Andric             continue;
23200b57cec5SDimitry Andric           } else {
23210b57cec5SDimitry Andric             *reason_to_stop =
23220b57cec5SDimitry Andric                 ValueObject::eExpressionPathScanEndReasonNoSuchChild;
23230b57cec5SDimitry Andric             *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
23240b57cec5SDimitry Andric             return nullptr;
23250b57cec5SDimitry Andric           }
23260b57cec5SDimitry Andric         } else if (root_compiler_type_info.Test(eTypeIsPointer)) {
23270b57cec5SDimitry Andric           if (*what_next ==
23280b57cec5SDimitry Andric                   ValueObject::
23290b57cec5SDimitry Andric                       eExpressionPathAftermathDereference && // if this is a
23300b57cec5SDimitry Andric                                                              // ptr-to-scalar, I
23310b57cec5SDimitry Andric                                                              // am accessing it
23320b57cec5SDimitry Andric                                                              // by index and I
23330b57cec5SDimitry Andric                                                              // would have
23340b57cec5SDimitry Andric                                                              // deref'ed anyway,
23350b57cec5SDimitry Andric                                                              // then do it now
23360b57cec5SDimitry Andric                                                              // and use this as
23370b57cec5SDimitry Andric                                                              // a bitfield
23380b57cec5SDimitry Andric               pointee_compiler_type_info.Test(eTypeIsScalar)) {
23390b57cec5SDimitry Andric             Status error;
23400b57cec5SDimitry Andric             root = root->Dereference(error);
23410b57cec5SDimitry Andric             if (error.Fail() || !root) {
23420b57cec5SDimitry Andric               *reason_to_stop =
23430b57cec5SDimitry Andric                   ValueObject::eExpressionPathScanEndReasonDereferencingFailed;
23440b57cec5SDimitry Andric               *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
23450b57cec5SDimitry Andric               return nullptr;
23460b57cec5SDimitry Andric             } else {
23470b57cec5SDimitry Andric               *what_next = eExpressionPathAftermathNothing;
23480b57cec5SDimitry Andric               continue;
23490b57cec5SDimitry Andric             }
23500b57cec5SDimitry Andric           } else {
23510b57cec5SDimitry Andric             if (root->GetCompilerType().GetMinimumLanguage() ==
23520b57cec5SDimitry Andric                     eLanguageTypeObjC &&
23530b57cec5SDimitry Andric                 pointee_compiler_type_info.AllClear(eTypeIsPointer) &&
23540b57cec5SDimitry Andric                 root->HasSyntheticValue() &&
23550b57cec5SDimitry Andric                 (options.m_synthetic_children_traversal ==
23560b57cec5SDimitry Andric                      GetValueForExpressionPathOptions::
23570b57cec5SDimitry Andric                          SyntheticChildrenTraversal::ToSynthetic ||
23580b57cec5SDimitry Andric                  options.m_synthetic_children_traversal ==
23590b57cec5SDimitry Andric                      GetValueForExpressionPathOptions::
23600b57cec5SDimitry Andric                          SyntheticChildrenTraversal::Both)) {
2361fe013be4SDimitry Andric               root = root->GetSyntheticValue()->GetChildAtIndex(index);
23620b57cec5SDimitry Andric             } else
23630b57cec5SDimitry Andric               root = root->GetSyntheticArrayMember(index, true);
23640b57cec5SDimitry Andric             if (!root) {
23650b57cec5SDimitry Andric               *reason_to_stop =
23660b57cec5SDimitry Andric                   ValueObject::eExpressionPathScanEndReasonNoSuchChild;
23670b57cec5SDimitry Andric               *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
23680b57cec5SDimitry Andric               return nullptr;
23690b57cec5SDimitry Andric             } else {
23700b57cec5SDimitry Andric               remainder =
23710b57cec5SDimitry Andric                   temp_expression.substr(close_bracket_position + 1); // skip ]
23720b57cec5SDimitry Andric               *final_result = ValueObject::eExpressionPathEndResultTypePlain;
23730b57cec5SDimitry Andric               continue;
23740b57cec5SDimitry Andric             }
23750b57cec5SDimitry Andric           }
23760b57cec5SDimitry Andric         } else if (root_compiler_type_info.Test(eTypeIsScalar)) {
23770b57cec5SDimitry Andric           root = root->GetSyntheticBitFieldChild(index, index, true);
23780b57cec5SDimitry Andric           if (!root) {
23790b57cec5SDimitry Andric             *reason_to_stop =
23800b57cec5SDimitry Andric                 ValueObject::eExpressionPathScanEndReasonNoSuchChild;
23810b57cec5SDimitry Andric             *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
23820b57cec5SDimitry Andric             return nullptr;
23830b57cec5SDimitry Andric           } else // we do not know how to expand members of bitfields, so we
23840b57cec5SDimitry Andric                  // just return and let the caller do any further processing
23850b57cec5SDimitry Andric           {
23860b57cec5SDimitry Andric             *reason_to_stop = ValueObject::
23870b57cec5SDimitry Andric                 eExpressionPathScanEndReasonBitfieldRangeOperatorMet;
23880b57cec5SDimitry Andric             *final_result = ValueObject::eExpressionPathEndResultTypeBitfield;
23890b57cec5SDimitry Andric             return root;
23900b57cec5SDimitry Andric           }
23910b57cec5SDimitry Andric         } else if (root_compiler_type_info.Test(eTypeIsVector)) {
2392fe013be4SDimitry Andric           root = root->GetChildAtIndex(index);
23930b57cec5SDimitry Andric           if (!root) {
23940b57cec5SDimitry Andric             *reason_to_stop =
23950b57cec5SDimitry Andric                 ValueObject::eExpressionPathScanEndReasonNoSuchChild;
23960b57cec5SDimitry Andric             *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
23970b57cec5SDimitry Andric             return ValueObjectSP();
23980b57cec5SDimitry Andric           } else {
23990b57cec5SDimitry Andric             remainder =
24000b57cec5SDimitry Andric                 temp_expression.substr(close_bracket_position + 1); // skip ]
24010b57cec5SDimitry Andric             *final_result = ValueObject::eExpressionPathEndResultTypePlain;
24020b57cec5SDimitry Andric             continue;
24030b57cec5SDimitry Andric           }
24040b57cec5SDimitry Andric         } else if (options.m_synthetic_children_traversal ==
24050b57cec5SDimitry Andric                        GetValueForExpressionPathOptions::
24060b57cec5SDimitry Andric                            SyntheticChildrenTraversal::ToSynthetic ||
24070b57cec5SDimitry Andric                    options.m_synthetic_children_traversal ==
24080b57cec5SDimitry Andric                        GetValueForExpressionPathOptions::
24090b57cec5SDimitry Andric                            SyntheticChildrenTraversal::Both) {
24100b57cec5SDimitry Andric           if (root->HasSyntheticValue())
24110b57cec5SDimitry Andric             root = root->GetSyntheticValue();
24120b57cec5SDimitry Andric           else if (!root->IsSynthetic()) {
24130b57cec5SDimitry Andric             *reason_to_stop =
24140b57cec5SDimitry Andric                 ValueObject::eExpressionPathScanEndReasonSyntheticValueMissing;
24150b57cec5SDimitry Andric             *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
24160b57cec5SDimitry Andric             return nullptr;
24170b57cec5SDimitry Andric           }
24180b57cec5SDimitry Andric           // if we are here, then root itself is a synthetic VO.. should be
24190b57cec5SDimitry Andric           // good to go
24200b57cec5SDimitry Andric 
24210b57cec5SDimitry Andric           if (!root) {
24220b57cec5SDimitry Andric             *reason_to_stop =
24230b57cec5SDimitry Andric                 ValueObject::eExpressionPathScanEndReasonSyntheticValueMissing;
24240b57cec5SDimitry Andric             *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
24250b57cec5SDimitry Andric             return nullptr;
24260b57cec5SDimitry Andric           }
2427fe013be4SDimitry Andric           root = root->GetChildAtIndex(index);
24280b57cec5SDimitry Andric           if (!root) {
24290b57cec5SDimitry Andric             *reason_to_stop =
24300b57cec5SDimitry Andric                 ValueObject::eExpressionPathScanEndReasonNoSuchChild;
24310b57cec5SDimitry Andric             *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
24320b57cec5SDimitry Andric             return nullptr;
24330b57cec5SDimitry Andric           } else {
24340b57cec5SDimitry Andric             remainder =
24350b57cec5SDimitry Andric                 temp_expression.substr(close_bracket_position + 1); // skip ]
24360b57cec5SDimitry Andric             *final_result = ValueObject::eExpressionPathEndResultTypePlain;
24370b57cec5SDimitry Andric             continue;
24380b57cec5SDimitry Andric           }
24390b57cec5SDimitry Andric         } else {
24400b57cec5SDimitry Andric           *reason_to_stop =
24410b57cec5SDimitry Andric               ValueObject::eExpressionPathScanEndReasonNoSuchChild;
24420b57cec5SDimitry Andric           *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
24430b57cec5SDimitry Andric           return nullptr;
24440b57cec5SDimitry Andric         }
24450b57cec5SDimitry Andric       } else {
24460b57cec5SDimitry Andric         // we have a low and a high index
24470b57cec5SDimitry Andric         llvm::StringRef sleft, sright;
24480b57cec5SDimitry Andric         unsigned long low_index, high_index;
24490b57cec5SDimitry Andric         std::tie(sleft, sright) = bracket_expr.split('-');
24500b57cec5SDimitry Andric         if (sleft.getAsInteger(0, low_index) ||
24510b57cec5SDimitry Andric             sright.getAsInteger(0, high_index)) {
24520b57cec5SDimitry Andric           *reason_to_stop =
24530b57cec5SDimitry Andric               ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol;
24540b57cec5SDimitry Andric           *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
24550b57cec5SDimitry Andric           return nullptr;
24560b57cec5SDimitry Andric         }
24570b57cec5SDimitry Andric 
24580b57cec5SDimitry Andric         if (low_index > high_index) // swap indices if required
24590b57cec5SDimitry Andric           std::swap(low_index, high_index);
24600b57cec5SDimitry Andric 
24610b57cec5SDimitry Andric         if (root_compiler_type_info.Test(
24620b57cec5SDimitry Andric                 eTypeIsScalar)) // expansion only works for scalars
24630b57cec5SDimitry Andric         {
24640b57cec5SDimitry Andric           root = root->GetSyntheticBitFieldChild(low_index, high_index, true);
24650b57cec5SDimitry Andric           if (!root) {
24660b57cec5SDimitry Andric             *reason_to_stop =
24670b57cec5SDimitry Andric                 ValueObject::eExpressionPathScanEndReasonNoSuchChild;
24680b57cec5SDimitry Andric             *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
24690b57cec5SDimitry Andric             return nullptr;
24700b57cec5SDimitry Andric           } else {
24710b57cec5SDimitry Andric             *reason_to_stop = ValueObject::
24720b57cec5SDimitry Andric                 eExpressionPathScanEndReasonBitfieldRangeOperatorMet;
24730b57cec5SDimitry Andric             *final_result = ValueObject::eExpressionPathEndResultTypeBitfield;
24740b57cec5SDimitry Andric             return root;
24750b57cec5SDimitry Andric           }
24760b57cec5SDimitry Andric         } else if (root_compiler_type_info.Test(
24770b57cec5SDimitry Andric                        eTypeIsPointer) && // if this is a ptr-to-scalar, I am
24780b57cec5SDimitry Andric                                           // accessing it by index and I would
24790b57cec5SDimitry Andric                                           // have deref'ed anyway, then do it
24800b57cec5SDimitry Andric                                           // now and use this as a bitfield
24810b57cec5SDimitry Andric                    *what_next ==
24820b57cec5SDimitry Andric                        ValueObject::eExpressionPathAftermathDereference &&
24830b57cec5SDimitry Andric                    pointee_compiler_type_info.Test(eTypeIsScalar)) {
24840b57cec5SDimitry Andric           Status error;
24850b57cec5SDimitry Andric           root = root->Dereference(error);
24860b57cec5SDimitry Andric           if (error.Fail() || !root) {
24870b57cec5SDimitry Andric             *reason_to_stop =
24880b57cec5SDimitry Andric                 ValueObject::eExpressionPathScanEndReasonDereferencingFailed;
24890b57cec5SDimitry Andric             *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
24900b57cec5SDimitry Andric             return nullptr;
24910b57cec5SDimitry Andric           } else {
24920b57cec5SDimitry Andric             *what_next = ValueObject::eExpressionPathAftermathNothing;
24930b57cec5SDimitry Andric             continue;
24940b57cec5SDimitry Andric           }
24950b57cec5SDimitry Andric         } else {
24960b57cec5SDimitry Andric           *reason_to_stop =
24970b57cec5SDimitry Andric               ValueObject::eExpressionPathScanEndReasonArrayRangeOperatorMet;
24980b57cec5SDimitry Andric           *final_result = ValueObject::eExpressionPathEndResultTypeBoundedRange;
24990b57cec5SDimitry Andric           return root;
25000b57cec5SDimitry Andric         }
25010b57cec5SDimitry Andric       }
25020b57cec5SDimitry Andric       break;
25030b57cec5SDimitry Andric     }
25040b57cec5SDimitry Andric     default: // some non-separator is in the way
25050b57cec5SDimitry Andric     {
25060b57cec5SDimitry Andric       *reason_to_stop =
25070b57cec5SDimitry Andric           ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol;
25080b57cec5SDimitry Andric       *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
25090b57cec5SDimitry Andric       return nullptr;
25100b57cec5SDimitry Andric     }
25110b57cec5SDimitry Andric     }
25120b57cec5SDimitry Andric   }
25130b57cec5SDimitry Andric }
25140b57cec5SDimitry Andric 
Dump(Stream & s)25150b57cec5SDimitry Andric void ValueObject::Dump(Stream &s) { Dump(s, DumpValueObjectOptions(*this)); }
25160b57cec5SDimitry Andric 
Dump(Stream & s,const DumpValueObjectOptions & options)25170b57cec5SDimitry Andric void ValueObject::Dump(Stream &s, const DumpValueObjectOptions &options) {
25180b57cec5SDimitry Andric   ValueObjectPrinter printer(this, &s, options);
25190b57cec5SDimitry Andric   printer.PrintValueObject();
25200b57cec5SDimitry Andric }
25210b57cec5SDimitry Andric 
CreateConstantValue(ConstString name)25220b57cec5SDimitry Andric ValueObjectSP ValueObject::CreateConstantValue(ConstString name) {
25230b57cec5SDimitry Andric   ValueObjectSP valobj_sp;
25240b57cec5SDimitry Andric 
25250b57cec5SDimitry Andric   if (UpdateValueIfNeeded(false) && m_error.Success()) {
25260b57cec5SDimitry Andric     ExecutionContext exe_ctx(GetExecutionContextRef());
25270b57cec5SDimitry Andric 
25280b57cec5SDimitry Andric     DataExtractor data;
25290b57cec5SDimitry Andric     data.SetByteOrder(m_data.GetByteOrder());
25300b57cec5SDimitry Andric     data.SetAddressByteSize(m_data.GetAddressByteSize());
25310b57cec5SDimitry Andric 
25320b57cec5SDimitry Andric     if (IsBitfield()) {
25330b57cec5SDimitry Andric       Value v(Scalar(GetValueAsUnsigned(UINT64_MAX)));
25349dba64beSDimitry Andric       m_error = v.GetValueAsData(&exe_ctx, data, GetModule().get());
25350b57cec5SDimitry Andric     } else
25369dba64beSDimitry Andric       m_error = m_value.GetValueAsData(&exe_ctx, data, GetModule().get());
25370b57cec5SDimitry Andric 
25380b57cec5SDimitry Andric     valobj_sp = ValueObjectConstResult::Create(
25390b57cec5SDimitry Andric         exe_ctx.GetBestExecutionContextScope(), GetCompilerType(), name, data,
25400b57cec5SDimitry Andric         GetAddressOf());
25410b57cec5SDimitry Andric   }
25420b57cec5SDimitry Andric 
25430b57cec5SDimitry Andric   if (!valobj_sp) {
25440b57cec5SDimitry Andric     ExecutionContext exe_ctx(GetExecutionContextRef());
25450b57cec5SDimitry Andric     valobj_sp = ValueObjectConstResult::Create(
25460b57cec5SDimitry Andric         exe_ctx.GetBestExecutionContextScope(), m_error);
25470b57cec5SDimitry Andric   }
25480b57cec5SDimitry Andric   return valobj_sp;
25490b57cec5SDimitry Andric }
25500b57cec5SDimitry Andric 
GetQualifiedRepresentationIfAvailable(lldb::DynamicValueType dynValue,bool synthValue)25510b57cec5SDimitry Andric ValueObjectSP ValueObject::GetQualifiedRepresentationIfAvailable(
25520b57cec5SDimitry Andric     lldb::DynamicValueType dynValue, bool synthValue) {
2553c9157d92SDimitry Andric   ValueObjectSP result_sp;
25540b57cec5SDimitry Andric   switch (dynValue) {
25550b57cec5SDimitry Andric   case lldb::eDynamicCanRunTarget:
25560b57cec5SDimitry Andric   case lldb::eDynamicDontRunTarget: {
2557c9157d92SDimitry Andric     if (!IsDynamic())
2558c9157d92SDimitry Andric       result_sp = GetDynamicValue(dynValue);
25590b57cec5SDimitry Andric   } break;
25600b57cec5SDimitry Andric   case lldb::eNoDynamicValues: {
2561c9157d92SDimitry Andric     if (IsDynamic())
2562c9157d92SDimitry Andric       result_sp = GetStaticValue();
25630b57cec5SDimitry Andric   } break;
25640b57cec5SDimitry Andric   }
2565c9157d92SDimitry Andric   if (!result_sp)
2566c9157d92SDimitry Andric     result_sp = GetSP();
2567c9157d92SDimitry Andric   assert(result_sp);
25680b57cec5SDimitry Andric 
2569c9157d92SDimitry Andric   bool is_synthetic = result_sp->IsSynthetic();
2570c9157d92SDimitry Andric   if (synthValue && !is_synthetic) {
2571c9157d92SDimitry Andric     if (auto synth_sp = result_sp->GetSyntheticValue())
2572c9157d92SDimitry Andric       return synth_sp;
25730b57cec5SDimitry Andric   }
2574c9157d92SDimitry Andric   if (!synthValue && is_synthetic) {
2575c9157d92SDimitry Andric     if (auto non_synth_sp = result_sp->GetNonSyntheticValue())
2576c9157d92SDimitry Andric       return non_synth_sp;
25770b57cec5SDimitry Andric   }
25780b57cec5SDimitry Andric 
25790b57cec5SDimitry Andric   return result_sp;
25800b57cec5SDimitry Andric }
25810b57cec5SDimitry Andric 
Dereference(Status & error)25820b57cec5SDimitry Andric ValueObjectSP ValueObject::Dereference(Status &error) {
25830b57cec5SDimitry Andric   if (m_deref_valobj)
25840b57cec5SDimitry Andric     return m_deref_valobj->GetSP();
25850b57cec5SDimitry Andric 
25860b57cec5SDimitry Andric   const bool is_pointer_or_reference_type = IsPointerOrReferenceType();
25870b57cec5SDimitry Andric   if (is_pointer_or_reference_type) {
25880b57cec5SDimitry Andric     bool omit_empty_base_classes = true;
25890b57cec5SDimitry Andric     bool ignore_array_bounds = false;
25900b57cec5SDimitry Andric 
25910b57cec5SDimitry Andric     std::string child_name_str;
25920b57cec5SDimitry Andric     uint32_t child_byte_size = 0;
25930b57cec5SDimitry Andric     int32_t child_byte_offset = 0;
25940b57cec5SDimitry Andric     uint32_t child_bitfield_bit_size = 0;
25950b57cec5SDimitry Andric     uint32_t child_bitfield_bit_offset = 0;
25960b57cec5SDimitry Andric     bool child_is_base_class = false;
25970b57cec5SDimitry Andric     bool child_is_deref_of_parent = false;
25980b57cec5SDimitry Andric     const bool transparent_pointers = false;
25990b57cec5SDimitry Andric     CompilerType compiler_type = GetCompilerType();
26000b57cec5SDimitry Andric     CompilerType child_compiler_type;
26015ffd83dbSDimitry Andric     uint64_t language_flags = 0;
26020b57cec5SDimitry Andric 
26030b57cec5SDimitry Andric     ExecutionContext exe_ctx(GetExecutionContextRef());
26040b57cec5SDimitry Andric 
26050b57cec5SDimitry Andric     child_compiler_type = compiler_type.GetChildCompilerTypeAtIndex(
26060b57cec5SDimitry Andric         &exe_ctx, 0, transparent_pointers, omit_empty_base_classes,
26070b57cec5SDimitry Andric         ignore_array_bounds, child_name_str, child_byte_size, child_byte_offset,
26080b57cec5SDimitry Andric         child_bitfield_bit_size, child_bitfield_bit_offset, child_is_base_class,
26090b57cec5SDimitry Andric         child_is_deref_of_parent, this, language_flags);
26100b57cec5SDimitry Andric     if (child_compiler_type && child_byte_size) {
26110b57cec5SDimitry Andric       ConstString child_name;
26120b57cec5SDimitry Andric       if (!child_name_str.empty())
26130b57cec5SDimitry Andric         child_name.SetCString(child_name_str.c_str());
26140b57cec5SDimitry Andric 
26150b57cec5SDimitry Andric       m_deref_valobj = new ValueObjectChild(
26160b57cec5SDimitry Andric           *this, child_compiler_type, child_name, child_byte_size,
26170b57cec5SDimitry Andric           child_byte_offset, child_bitfield_bit_size, child_bitfield_bit_offset,
26180b57cec5SDimitry Andric           child_is_base_class, child_is_deref_of_parent, eAddressTypeInvalid,
26190b57cec5SDimitry Andric           language_flags);
26200b57cec5SDimitry Andric     }
26215ffd83dbSDimitry Andric 
26225ffd83dbSDimitry Andric     // In case of incomplete child compiler type, use the pointee type and try
26235ffd83dbSDimitry Andric     // to recreate a new ValueObjectChild using it.
26245ffd83dbSDimitry Andric     if (!m_deref_valobj) {
2625bdd1243dSDimitry Andric       // FIXME(#59012): C++ stdlib formatters break with incomplete types (e.g.
2626bdd1243dSDimitry Andric       // `std::vector<int> &`). Remove ObjC restriction once that's resolved.
2627bdd1243dSDimitry Andric       if (Language::LanguageIsObjC(GetPreferredDisplayLanguage()) &&
2628bdd1243dSDimitry Andric           HasSyntheticValue()) {
26295ffd83dbSDimitry Andric         child_compiler_type = compiler_type.GetPointeeType();
26305ffd83dbSDimitry Andric 
26315ffd83dbSDimitry Andric         if (child_compiler_type) {
26325ffd83dbSDimitry Andric           ConstString child_name;
26335ffd83dbSDimitry Andric           if (!child_name_str.empty())
26345ffd83dbSDimitry Andric             child_name.SetCString(child_name_str.c_str());
26355ffd83dbSDimitry Andric 
26365ffd83dbSDimitry Andric           m_deref_valobj = new ValueObjectChild(
26375ffd83dbSDimitry Andric               *this, child_compiler_type, child_name, child_byte_size,
26385ffd83dbSDimitry Andric               child_byte_offset, child_bitfield_bit_size,
26395ffd83dbSDimitry Andric               child_bitfield_bit_offset, child_is_base_class,
26405ffd83dbSDimitry Andric               child_is_deref_of_parent, eAddressTypeInvalid, language_flags);
26415ffd83dbSDimitry Andric         }
26425ffd83dbSDimitry Andric       }
26435ffd83dbSDimitry Andric     }
26445ffd83dbSDimitry Andric 
26450b57cec5SDimitry Andric   } else if (HasSyntheticValue()) {
26460b57cec5SDimitry Andric     m_deref_valobj =
2647fe013be4SDimitry Andric         GetSyntheticValue()->GetChildMemberWithName("$$dereference$$").get();
26485ffd83dbSDimitry Andric   } else if (IsSynthetic()) {
2649fe013be4SDimitry Andric     m_deref_valobj = GetChildMemberWithName("$$dereference$$").get();
26500b57cec5SDimitry Andric   }
26510b57cec5SDimitry Andric 
26520b57cec5SDimitry Andric   if (m_deref_valobj) {
26530b57cec5SDimitry Andric     error.Clear();
26540b57cec5SDimitry Andric     return m_deref_valobj->GetSP();
26550b57cec5SDimitry Andric   } else {
26560b57cec5SDimitry Andric     StreamString strm;
26575ffd83dbSDimitry Andric     GetExpressionPath(strm);
26580b57cec5SDimitry Andric 
26590b57cec5SDimitry Andric     if (is_pointer_or_reference_type)
26600b57cec5SDimitry Andric       error.SetErrorStringWithFormat("dereference failed: (%s) %s",
26610b57cec5SDimitry Andric                                      GetTypeName().AsCString("<invalid type>"),
26620b57cec5SDimitry Andric                                      strm.GetData());
26630b57cec5SDimitry Andric     else
26640b57cec5SDimitry Andric       error.SetErrorStringWithFormat("not a pointer or reference type: (%s) %s",
26650b57cec5SDimitry Andric                                      GetTypeName().AsCString("<invalid type>"),
26660b57cec5SDimitry Andric                                      strm.GetData());
26670b57cec5SDimitry Andric     return ValueObjectSP();
26680b57cec5SDimitry Andric   }
26690b57cec5SDimitry Andric }
26700b57cec5SDimitry Andric 
AddressOf(Status & error)26710b57cec5SDimitry Andric ValueObjectSP ValueObject::AddressOf(Status &error) {
26720b57cec5SDimitry Andric   if (m_addr_of_valobj_sp)
26730b57cec5SDimitry Andric     return m_addr_of_valobj_sp;
26740b57cec5SDimitry Andric 
26750b57cec5SDimitry Andric   AddressType address_type = eAddressTypeInvalid;
26760b57cec5SDimitry Andric   const bool scalar_is_load_address = false;
26770b57cec5SDimitry Andric   addr_t addr = GetAddressOf(scalar_is_load_address, &address_type);
26780b57cec5SDimitry Andric   error.Clear();
2679*a58f00eaSDimitry Andric 
26800b57cec5SDimitry Andric   StreamString expr_path_strm;
26815ffd83dbSDimitry Andric   GetExpressionPath(expr_path_strm);
2682*a58f00eaSDimitry Andric   const char *expr_path_str = expr_path_strm.GetData();
2683*a58f00eaSDimitry Andric 
2684*a58f00eaSDimitry Andric   ExecutionContext exe_ctx(GetExecutionContextRef());
2685*a58f00eaSDimitry Andric   auto scope = exe_ctx.GetBestExecutionContextScope();
2686*a58f00eaSDimitry Andric 
2687*a58f00eaSDimitry Andric   if (addr == LLDB_INVALID_ADDRESS) {
2688*a58f00eaSDimitry Andric     error.SetErrorStringWithFormat("'%s' doesn't have a valid address",
2689*a58f00eaSDimitry Andric                                    expr_path_str);
2690*a58f00eaSDimitry Andric     return ValueObjectSP();
2691*a58f00eaSDimitry Andric   }
2692*a58f00eaSDimitry Andric 
2693*a58f00eaSDimitry Andric   switch (address_type) {
2694*a58f00eaSDimitry Andric   case eAddressTypeInvalid:
2695*a58f00eaSDimitry Andric     error.SetErrorStringWithFormat("'%s' is not in memory", expr_path_str);
2696*a58f00eaSDimitry Andric     return ValueObjectSP();
2697*a58f00eaSDimitry Andric 
2698*a58f00eaSDimitry Andric   case eAddressTypeHost:
2699*a58f00eaSDimitry Andric     error.SetErrorStringWithFormat("'%s' is in host process (LLDB) memory",
2700*a58f00eaSDimitry Andric                                    expr_path_str);
2701*a58f00eaSDimitry Andric     return ValueObjectSP();
27020b57cec5SDimitry Andric 
27030b57cec5SDimitry Andric   case eAddressTypeFile:
27040b57cec5SDimitry Andric   case eAddressTypeLoad: {
27050b57cec5SDimitry Andric     CompilerType compiler_type = GetCompilerType();
2706*a58f00eaSDimitry Andric     if (!compiler_type) {
2707*a58f00eaSDimitry Andric       error.SetErrorStringWithFormat("'%s' doesn't have a compiler type",
2708*a58f00eaSDimitry Andric                                      expr_path_str);
2709*a58f00eaSDimitry Andric       return ValueObjectSP();
27100b57cec5SDimitry Andric     }
27110b57cec5SDimitry Andric 
2712*a58f00eaSDimitry Andric     std::string name(1, '&');
2713*a58f00eaSDimitry Andric     name.append(m_name.AsCString(""));
2714*a58f00eaSDimitry Andric     m_addr_of_valobj_sp = ValueObjectConstResult::Create(
2715*a58f00eaSDimitry Andric         scope, compiler_type.GetPointerType(), ConstString(name.c_str()), addr,
2716*a58f00eaSDimitry Andric         eAddressTypeInvalid, m_data.GetAddressByteSize());
27170b57cec5SDimitry Andric     return m_addr_of_valobj_sp;
27180b57cec5SDimitry Andric   }
2719*a58f00eaSDimitry Andric   }
2720*a58f00eaSDimitry Andric }
27210b57cec5SDimitry Andric 
DoCast(const CompilerType & compiler_type)2722fe013be4SDimitry Andric ValueObjectSP ValueObject::DoCast(const CompilerType &compiler_type) {
27230b57cec5SDimitry Andric     return ValueObjectCast::Create(*this, GetName(), compiler_type);
27240b57cec5SDimitry Andric }
27250b57cec5SDimitry Andric 
Cast(const CompilerType & compiler_type)2726fe013be4SDimitry Andric ValueObjectSP ValueObject::Cast(const CompilerType &compiler_type) {
2727fe013be4SDimitry Andric   // Only allow casts if the original type is equal or larger than the cast
2728fe013be4SDimitry Andric   // type.  We don't know how to fetch more data for all the ConstResult types,
2729fe013be4SDimitry Andric   // so we can't guarantee this will work:
2730fe013be4SDimitry Andric   Status error;
2731fe013be4SDimitry Andric   CompilerType my_type = GetCompilerType();
2732fe013be4SDimitry Andric 
2733fe013be4SDimitry Andric   ExecutionContextScope *exe_scope
2734fe013be4SDimitry Andric       = ExecutionContext(GetExecutionContextRef())
2735fe013be4SDimitry Andric           .GetBestExecutionContextScope();
2736fe013be4SDimitry Andric   if (compiler_type.GetByteSize(exe_scope)
2737fe013be4SDimitry Andric       <= GetCompilerType().GetByteSize(exe_scope)) {
2738fe013be4SDimitry Andric         return DoCast(compiler_type);
2739fe013be4SDimitry Andric   }
2740fe013be4SDimitry Andric   error.SetErrorString("Can only cast to a type that is equal to or smaller "
2741fe013be4SDimitry Andric                        "than the orignal type.");
2742fe013be4SDimitry Andric 
2743fe013be4SDimitry Andric   return ValueObjectConstResult::Create(
2744fe013be4SDimitry Andric       ExecutionContext(GetExecutionContextRef()).GetBestExecutionContextScope(),
2745fe013be4SDimitry Andric                        error);
2746fe013be4SDimitry Andric }
2747fe013be4SDimitry Andric 
Clone(ConstString new_name)27480b57cec5SDimitry Andric lldb::ValueObjectSP ValueObject::Clone(ConstString new_name) {
27490b57cec5SDimitry Andric   return ValueObjectCast::Create(*this, new_name, GetCompilerType());
27500b57cec5SDimitry Andric }
27510b57cec5SDimitry Andric 
CastPointerType(const char * name,CompilerType & compiler_type)27520b57cec5SDimitry Andric ValueObjectSP ValueObject::CastPointerType(const char *name,
27530b57cec5SDimitry Andric                                            CompilerType &compiler_type) {
27540b57cec5SDimitry Andric   ValueObjectSP valobj_sp;
27550b57cec5SDimitry Andric   AddressType address_type;
27560b57cec5SDimitry Andric   addr_t ptr_value = GetPointerValue(&address_type);
27570b57cec5SDimitry Andric 
27580b57cec5SDimitry Andric   if (ptr_value != LLDB_INVALID_ADDRESS) {
27590b57cec5SDimitry Andric     Address ptr_addr(ptr_value);
27600b57cec5SDimitry Andric     ExecutionContext exe_ctx(GetExecutionContextRef());
27610b57cec5SDimitry Andric     valobj_sp = ValueObjectMemory::Create(
27620b57cec5SDimitry Andric         exe_ctx.GetBestExecutionContextScope(), name, ptr_addr, compiler_type);
27630b57cec5SDimitry Andric   }
27640b57cec5SDimitry Andric   return valobj_sp;
27650b57cec5SDimitry Andric }
27660b57cec5SDimitry Andric 
CastPointerType(const char * name,TypeSP & type_sp)27670b57cec5SDimitry Andric ValueObjectSP ValueObject::CastPointerType(const char *name, TypeSP &type_sp) {
27680b57cec5SDimitry Andric   ValueObjectSP valobj_sp;
27690b57cec5SDimitry Andric   AddressType address_type;
27700b57cec5SDimitry Andric   addr_t ptr_value = GetPointerValue(&address_type);
27710b57cec5SDimitry Andric 
27720b57cec5SDimitry Andric   if (ptr_value != LLDB_INVALID_ADDRESS) {
27730b57cec5SDimitry Andric     Address ptr_addr(ptr_value);
27740b57cec5SDimitry Andric     ExecutionContext exe_ctx(GetExecutionContextRef());
27750b57cec5SDimitry Andric     valobj_sp = ValueObjectMemory::Create(
27760b57cec5SDimitry Andric         exe_ctx.GetBestExecutionContextScope(), name, ptr_addr, type_sp);
27770b57cec5SDimitry Andric   }
27780b57cec5SDimitry Andric   return valobj_sp;
27790b57cec5SDimitry Andric }
27800b57cec5SDimitry Andric 
EvaluationPoint()2781fe6060f1SDimitry Andric ValueObject::EvaluationPoint::EvaluationPoint() : m_mod_id(), m_exe_ctx_ref() {}
27820b57cec5SDimitry Andric 
EvaluationPoint(ExecutionContextScope * exe_scope,bool use_selected)27830b57cec5SDimitry Andric ValueObject::EvaluationPoint::EvaluationPoint(ExecutionContextScope *exe_scope,
27840b57cec5SDimitry Andric                                               bool use_selected)
278581ad6265SDimitry Andric     : m_mod_id(), m_exe_ctx_ref() {
27860b57cec5SDimitry Andric   ExecutionContext exe_ctx(exe_scope);
27870b57cec5SDimitry Andric   TargetSP target_sp(exe_ctx.GetTargetSP());
27880b57cec5SDimitry Andric   if (target_sp) {
27890b57cec5SDimitry Andric     m_exe_ctx_ref.SetTargetSP(target_sp);
27900b57cec5SDimitry Andric     ProcessSP process_sp(exe_ctx.GetProcessSP());
27910b57cec5SDimitry Andric     if (!process_sp)
27920b57cec5SDimitry Andric       process_sp = target_sp->GetProcessSP();
27930b57cec5SDimitry Andric 
27940b57cec5SDimitry Andric     if (process_sp) {
27950b57cec5SDimitry Andric       m_mod_id = process_sp->GetModID();
27960b57cec5SDimitry Andric       m_exe_ctx_ref.SetProcessSP(process_sp);
27970b57cec5SDimitry Andric 
27980b57cec5SDimitry Andric       ThreadSP thread_sp(exe_ctx.GetThreadSP());
27990b57cec5SDimitry Andric 
28000b57cec5SDimitry Andric       if (!thread_sp) {
28010b57cec5SDimitry Andric         if (use_selected)
28020b57cec5SDimitry Andric           thread_sp = process_sp->GetThreadList().GetSelectedThread();
28030b57cec5SDimitry Andric       }
28040b57cec5SDimitry Andric 
28050b57cec5SDimitry Andric       if (thread_sp) {
28060b57cec5SDimitry Andric         m_exe_ctx_ref.SetThreadSP(thread_sp);
28070b57cec5SDimitry Andric 
28080b57cec5SDimitry Andric         StackFrameSP frame_sp(exe_ctx.GetFrameSP());
28090b57cec5SDimitry Andric         if (!frame_sp) {
28100b57cec5SDimitry Andric           if (use_selected)
2811fe013be4SDimitry Andric             frame_sp = thread_sp->GetSelectedFrame(DoNoSelectMostRelevantFrame);
28120b57cec5SDimitry Andric         }
28130b57cec5SDimitry Andric         if (frame_sp)
28140b57cec5SDimitry Andric           m_exe_ctx_ref.SetFrameSP(frame_sp);
28150b57cec5SDimitry Andric       }
28160b57cec5SDimitry Andric     }
28170b57cec5SDimitry Andric   }
28180b57cec5SDimitry Andric }
28190b57cec5SDimitry Andric 
EvaluationPoint(const ValueObject::EvaluationPoint & rhs)28200b57cec5SDimitry Andric ValueObject::EvaluationPoint::EvaluationPoint(
28210b57cec5SDimitry Andric     const ValueObject::EvaluationPoint &rhs)
282281ad6265SDimitry Andric     : m_mod_id(), m_exe_ctx_ref(rhs.m_exe_ctx_ref) {}
28230b57cec5SDimitry Andric 
2824fe6060f1SDimitry Andric ValueObject::EvaluationPoint::~EvaluationPoint() = default;
28250b57cec5SDimitry Andric 
28260b57cec5SDimitry Andric // This function checks the EvaluationPoint against the current process state.
28270b57cec5SDimitry Andric // If the current state matches the evaluation point, or the evaluation point
28280b57cec5SDimitry Andric // is already invalid, then we return false, meaning "no change".  If the
28290b57cec5SDimitry Andric // current state is different, we update our state, and return true meaning
28300b57cec5SDimitry Andric // "yes, change".  If we did see a change, we also set m_needs_update to true,
28310b57cec5SDimitry Andric // so future calls to NeedsUpdate will return true. exe_scope will be set to
28320b57cec5SDimitry Andric // the current execution context scope.
28330b57cec5SDimitry Andric 
SyncWithProcessState(bool accept_invalid_exe_ctx)28340b57cec5SDimitry Andric bool ValueObject::EvaluationPoint::SyncWithProcessState(
28350b57cec5SDimitry Andric     bool accept_invalid_exe_ctx) {
28360b57cec5SDimitry Andric   // Start with the target, if it is NULL, then we're obviously not going to
28370b57cec5SDimitry Andric   // get any further:
28380b57cec5SDimitry Andric   const bool thread_and_frame_only_if_stopped = true;
28390b57cec5SDimitry Andric   ExecutionContext exe_ctx(
28400b57cec5SDimitry Andric       m_exe_ctx_ref.Lock(thread_and_frame_only_if_stopped));
28410b57cec5SDimitry Andric 
28420b57cec5SDimitry Andric   if (exe_ctx.GetTargetPtr() == nullptr)
28430b57cec5SDimitry Andric     return false;
28440b57cec5SDimitry Andric 
28450b57cec5SDimitry Andric   // If we don't have a process nothing can change.
28460b57cec5SDimitry Andric   Process *process = exe_ctx.GetProcessPtr();
28470b57cec5SDimitry Andric   if (process == nullptr)
28480b57cec5SDimitry Andric     return false;
28490b57cec5SDimitry Andric 
28500b57cec5SDimitry Andric   // If our stop id is the current stop ID, nothing has changed:
28510b57cec5SDimitry Andric   ProcessModID current_mod_id = process->GetModID();
28520b57cec5SDimitry Andric 
28530b57cec5SDimitry Andric   // If the current stop id is 0, either we haven't run yet, or the process
28540b57cec5SDimitry Andric   // state has been cleared. In either case, we aren't going to be able to sync
28550b57cec5SDimitry Andric   // with the process state.
28560b57cec5SDimitry Andric   if (current_mod_id.GetStopID() == 0)
28570b57cec5SDimitry Andric     return false;
28580b57cec5SDimitry Andric 
28590b57cec5SDimitry Andric   bool changed = false;
28600b57cec5SDimitry Andric   const bool was_valid = m_mod_id.IsValid();
28610b57cec5SDimitry Andric   if (was_valid) {
28620b57cec5SDimitry Andric     if (m_mod_id == current_mod_id) {
28630b57cec5SDimitry Andric       // Everything is already up to date in this object, no need to update the
28640b57cec5SDimitry Andric       // execution context scope.
28650b57cec5SDimitry Andric       changed = false;
28660b57cec5SDimitry Andric     } else {
28670b57cec5SDimitry Andric       m_mod_id = current_mod_id;
28680b57cec5SDimitry Andric       m_needs_update = true;
28690b57cec5SDimitry Andric       changed = true;
28700b57cec5SDimitry Andric     }
28710b57cec5SDimitry Andric   }
28720b57cec5SDimitry Andric 
28730b57cec5SDimitry Andric   // Now re-look up the thread and frame in case the underlying objects have
28740b57cec5SDimitry Andric   // gone away & been recreated. That way we'll be sure to return a valid
28750b57cec5SDimitry Andric   // exe_scope. If we used to have a thread or a frame but can't find it
28760b57cec5SDimitry Andric   // anymore, then mark ourselves as invalid.
28770b57cec5SDimitry Andric 
28780b57cec5SDimitry Andric   if (!accept_invalid_exe_ctx) {
28790b57cec5SDimitry Andric     if (m_exe_ctx_ref.HasThreadRef()) {
28800b57cec5SDimitry Andric       ThreadSP thread_sp(m_exe_ctx_ref.GetThreadSP());
28810b57cec5SDimitry Andric       if (thread_sp) {
28820b57cec5SDimitry Andric         if (m_exe_ctx_ref.HasFrameRef()) {
28830b57cec5SDimitry Andric           StackFrameSP frame_sp(m_exe_ctx_ref.GetFrameSP());
28840b57cec5SDimitry Andric           if (!frame_sp) {
28850b57cec5SDimitry Andric             // We used to have a frame, but now it is gone
28860b57cec5SDimitry Andric             SetInvalid();
28870b57cec5SDimitry Andric             changed = was_valid;
28880b57cec5SDimitry Andric           }
28890b57cec5SDimitry Andric         }
28900b57cec5SDimitry Andric       } else {
28910b57cec5SDimitry Andric         // We used to have a thread, but now it is gone
28920b57cec5SDimitry Andric         SetInvalid();
28930b57cec5SDimitry Andric         changed = was_valid;
28940b57cec5SDimitry Andric       }
28950b57cec5SDimitry Andric     }
28960b57cec5SDimitry Andric   }
28970b57cec5SDimitry Andric 
28980b57cec5SDimitry Andric   return changed;
28990b57cec5SDimitry Andric }
29000b57cec5SDimitry Andric 
SetUpdated()29010b57cec5SDimitry Andric void ValueObject::EvaluationPoint::SetUpdated() {
29020b57cec5SDimitry Andric   ProcessSP process_sp(m_exe_ctx_ref.GetProcessSP());
29030b57cec5SDimitry Andric   if (process_sp)
29040b57cec5SDimitry Andric     m_mod_id = process_sp->GetModID();
29050b57cec5SDimitry Andric   m_needs_update = false;
29060b57cec5SDimitry Andric }
29070b57cec5SDimitry Andric 
ClearUserVisibleData(uint32_t clear_mask)29080b57cec5SDimitry Andric void ValueObject::ClearUserVisibleData(uint32_t clear_mask) {
29090b57cec5SDimitry Andric   if ((clear_mask & eClearUserVisibleDataItemsValue) ==
29100b57cec5SDimitry Andric       eClearUserVisibleDataItemsValue)
29110b57cec5SDimitry Andric     m_value_str.clear();
29120b57cec5SDimitry Andric 
29130b57cec5SDimitry Andric   if ((clear_mask & eClearUserVisibleDataItemsLocation) ==
29140b57cec5SDimitry Andric       eClearUserVisibleDataItemsLocation)
29150b57cec5SDimitry Andric     m_location_str.clear();
29160b57cec5SDimitry Andric 
29170b57cec5SDimitry Andric   if ((clear_mask & eClearUserVisibleDataItemsSummary) ==
29180b57cec5SDimitry Andric       eClearUserVisibleDataItemsSummary)
29190b57cec5SDimitry Andric     m_summary_str.clear();
29200b57cec5SDimitry Andric 
29210b57cec5SDimitry Andric   if ((clear_mask & eClearUserVisibleDataItemsDescription) ==
29220b57cec5SDimitry Andric       eClearUserVisibleDataItemsDescription)
29230b57cec5SDimitry Andric     m_object_desc_str.clear();
29240b57cec5SDimitry Andric 
29250b57cec5SDimitry Andric   if ((clear_mask & eClearUserVisibleDataItemsSyntheticChildren) ==
29260b57cec5SDimitry Andric       eClearUserVisibleDataItemsSyntheticChildren) {
29270b57cec5SDimitry Andric     if (m_synthetic_value)
29280b57cec5SDimitry Andric       m_synthetic_value = nullptr;
29290b57cec5SDimitry Andric   }
29300b57cec5SDimitry Andric }
29310b57cec5SDimitry Andric 
GetSymbolContextScope()29320b57cec5SDimitry Andric SymbolContextScope *ValueObject::GetSymbolContextScope() {
29330b57cec5SDimitry Andric   if (m_parent) {
29340b57cec5SDimitry Andric     if (!m_parent->IsPointerOrReferenceType())
29350b57cec5SDimitry Andric       return m_parent->GetSymbolContextScope();
29360b57cec5SDimitry Andric   }
29370b57cec5SDimitry Andric   return nullptr;
29380b57cec5SDimitry Andric }
29390b57cec5SDimitry Andric 
29400b57cec5SDimitry Andric lldb::ValueObjectSP
CreateValueObjectFromExpression(llvm::StringRef name,llvm::StringRef expression,const ExecutionContext & exe_ctx)29410b57cec5SDimitry Andric ValueObject::CreateValueObjectFromExpression(llvm::StringRef name,
29420b57cec5SDimitry Andric                                              llvm::StringRef expression,
29430b57cec5SDimitry Andric                                              const ExecutionContext &exe_ctx) {
29440b57cec5SDimitry Andric   return CreateValueObjectFromExpression(name, expression, exe_ctx,
29450b57cec5SDimitry Andric                                          EvaluateExpressionOptions());
29460b57cec5SDimitry Andric }
29470b57cec5SDimitry Andric 
CreateValueObjectFromExpression(llvm::StringRef name,llvm::StringRef expression,const ExecutionContext & exe_ctx,const EvaluateExpressionOptions & options)29480b57cec5SDimitry Andric lldb::ValueObjectSP ValueObject::CreateValueObjectFromExpression(
29490b57cec5SDimitry Andric     llvm::StringRef name, llvm::StringRef expression,
29500b57cec5SDimitry Andric     const ExecutionContext &exe_ctx, const EvaluateExpressionOptions &options) {
29510b57cec5SDimitry Andric   lldb::ValueObjectSP retval_sp;
29520b57cec5SDimitry Andric   lldb::TargetSP target_sp(exe_ctx.GetTargetSP());
29530b57cec5SDimitry Andric   if (!target_sp)
29540b57cec5SDimitry Andric     return retval_sp;
29550b57cec5SDimitry Andric   if (expression.empty())
29560b57cec5SDimitry Andric     return retval_sp;
29570b57cec5SDimitry Andric   target_sp->EvaluateExpression(expression, exe_ctx.GetFrameSP().get(),
29580b57cec5SDimitry Andric                                 retval_sp, options);
29590b57cec5SDimitry Andric   if (retval_sp && !name.empty())
29600b57cec5SDimitry Andric     retval_sp->SetName(ConstString(name));
29610b57cec5SDimitry Andric   return retval_sp;
29620b57cec5SDimitry Andric }
29630b57cec5SDimitry Andric 
CreateValueObjectFromAddress(llvm::StringRef name,uint64_t address,const ExecutionContext & exe_ctx,CompilerType type)29640b57cec5SDimitry Andric lldb::ValueObjectSP ValueObject::CreateValueObjectFromAddress(
29650b57cec5SDimitry Andric     llvm::StringRef name, uint64_t address, const ExecutionContext &exe_ctx,
29660b57cec5SDimitry Andric     CompilerType type) {
29670b57cec5SDimitry Andric   if (type) {
29680b57cec5SDimitry Andric     CompilerType pointer_type(type.GetPointerType());
29690b57cec5SDimitry Andric     if (pointer_type) {
29700b57cec5SDimitry Andric       lldb::DataBufferSP buffer(
29710b57cec5SDimitry Andric           new lldb_private::DataBufferHeap(&address, sizeof(lldb::addr_t)));
29720b57cec5SDimitry Andric       lldb::ValueObjectSP ptr_result_valobj_sp(ValueObjectConstResult::Create(
29730b57cec5SDimitry Andric           exe_ctx.GetBestExecutionContextScope(), pointer_type,
29740b57cec5SDimitry Andric           ConstString(name), buffer, exe_ctx.GetByteOrder(),
29750b57cec5SDimitry Andric           exe_ctx.GetAddressByteSize()));
29760b57cec5SDimitry Andric       if (ptr_result_valobj_sp) {
29770b57cec5SDimitry Andric         ptr_result_valobj_sp->GetValue().SetValueType(
2978fe6060f1SDimitry Andric             Value::ValueType::LoadAddress);
29790b57cec5SDimitry Andric         Status err;
29800b57cec5SDimitry Andric         ptr_result_valobj_sp = ptr_result_valobj_sp->Dereference(err);
29810b57cec5SDimitry Andric         if (ptr_result_valobj_sp && !name.empty())
29820b57cec5SDimitry Andric           ptr_result_valobj_sp->SetName(ConstString(name));
29830b57cec5SDimitry Andric       }
29840b57cec5SDimitry Andric       return ptr_result_valobj_sp;
29850b57cec5SDimitry Andric     }
29860b57cec5SDimitry Andric   }
29870b57cec5SDimitry Andric   return lldb::ValueObjectSP();
29880b57cec5SDimitry Andric }
29890b57cec5SDimitry Andric 
CreateValueObjectFromData(llvm::StringRef name,const DataExtractor & data,const ExecutionContext & exe_ctx,CompilerType type)29900b57cec5SDimitry Andric lldb::ValueObjectSP ValueObject::CreateValueObjectFromData(
29910b57cec5SDimitry Andric     llvm::StringRef name, const DataExtractor &data,
29920b57cec5SDimitry Andric     const ExecutionContext &exe_ctx, CompilerType type) {
29930b57cec5SDimitry Andric   lldb::ValueObjectSP new_value_sp;
29940b57cec5SDimitry Andric   new_value_sp = ValueObjectConstResult::Create(
29950b57cec5SDimitry Andric       exe_ctx.GetBestExecutionContextScope(), type, ConstString(name), data,
29960b57cec5SDimitry Andric       LLDB_INVALID_ADDRESS);
29970b57cec5SDimitry Andric   new_value_sp->SetAddressTypeOfChildren(eAddressTypeLoad);
29980b57cec5SDimitry Andric   if (new_value_sp && !name.empty())
29990b57cec5SDimitry Andric     new_value_sp->SetName(ConstString(name));
30000b57cec5SDimitry Andric   return new_value_sp;
30010b57cec5SDimitry Andric }
30020b57cec5SDimitry Andric 
GetModule()30030b57cec5SDimitry Andric ModuleSP ValueObject::GetModule() {
30040b57cec5SDimitry Andric   ValueObject *root(GetRoot());
30050b57cec5SDimitry Andric   if (root != this)
30060b57cec5SDimitry Andric     return root->GetModule();
30070b57cec5SDimitry Andric   return lldb::ModuleSP();
30080b57cec5SDimitry Andric }
30090b57cec5SDimitry Andric 
GetRoot()30100b57cec5SDimitry Andric ValueObject *ValueObject::GetRoot() {
30110b57cec5SDimitry Andric   if (m_root)
30120b57cec5SDimitry Andric     return m_root;
30130b57cec5SDimitry Andric   return (m_root = FollowParentChain([](ValueObject *vo) -> bool {
30140b57cec5SDimitry Andric             return (vo->m_parent != nullptr);
30150b57cec5SDimitry Andric           }));
30160b57cec5SDimitry Andric }
30170b57cec5SDimitry Andric 
30180b57cec5SDimitry Andric ValueObject *
FollowParentChain(std::function<bool (ValueObject *)> f)30190b57cec5SDimitry Andric ValueObject::FollowParentChain(std::function<bool(ValueObject *)> f) {
30200b57cec5SDimitry Andric   ValueObject *vo = this;
30210b57cec5SDimitry Andric   while (vo) {
30220b57cec5SDimitry Andric     if (!f(vo))
30230b57cec5SDimitry Andric       break;
30240b57cec5SDimitry Andric     vo = vo->m_parent;
30250b57cec5SDimitry Andric   }
30260b57cec5SDimitry Andric   return vo;
30270b57cec5SDimitry Andric }
30280b57cec5SDimitry Andric 
GetAddressTypeOfChildren()30290b57cec5SDimitry Andric AddressType ValueObject::GetAddressTypeOfChildren() {
30300b57cec5SDimitry Andric   if (m_address_type_of_ptr_or_ref_children == eAddressTypeInvalid) {
30310b57cec5SDimitry Andric     ValueObject *root(GetRoot());
30320b57cec5SDimitry Andric     if (root != this)
30330b57cec5SDimitry Andric       return root->GetAddressTypeOfChildren();
30340b57cec5SDimitry Andric   }
30350b57cec5SDimitry Andric   return m_address_type_of_ptr_or_ref_children;
30360b57cec5SDimitry Andric }
30370b57cec5SDimitry Andric 
GetDynamicValueType()30380b57cec5SDimitry Andric lldb::DynamicValueType ValueObject::GetDynamicValueType() {
30390b57cec5SDimitry Andric   ValueObject *with_dv_info = this;
30400b57cec5SDimitry Andric   while (with_dv_info) {
30410b57cec5SDimitry Andric     if (with_dv_info->HasDynamicValueTypeInfo())
30420b57cec5SDimitry Andric       return with_dv_info->GetDynamicValueTypeImpl();
30430b57cec5SDimitry Andric     with_dv_info = with_dv_info->m_parent;
30440b57cec5SDimitry Andric   }
30450b57cec5SDimitry Andric   return lldb::eNoDynamicValues;
30460b57cec5SDimitry Andric }
30470b57cec5SDimitry Andric 
GetFormat() const30480b57cec5SDimitry Andric lldb::Format ValueObject::GetFormat() const {
30490b57cec5SDimitry Andric   const ValueObject *with_fmt_info = this;
30500b57cec5SDimitry Andric   while (with_fmt_info) {
30510b57cec5SDimitry Andric     if (with_fmt_info->m_format != lldb::eFormatDefault)
30520b57cec5SDimitry Andric       return with_fmt_info->m_format;
30530b57cec5SDimitry Andric     with_fmt_info = with_fmt_info->m_parent;
30540b57cec5SDimitry Andric   }
30550b57cec5SDimitry Andric   return m_format;
30560b57cec5SDimitry Andric }
30570b57cec5SDimitry Andric 
GetPreferredDisplayLanguage()30580b57cec5SDimitry Andric lldb::LanguageType ValueObject::GetPreferredDisplayLanguage() {
30590b57cec5SDimitry Andric   lldb::LanguageType type = m_preferred_display_language;
30600b57cec5SDimitry Andric   if (m_preferred_display_language == lldb::eLanguageTypeUnknown) {
30610b57cec5SDimitry Andric     if (GetRoot()) {
30620b57cec5SDimitry Andric       if (GetRoot() == this) {
30630b57cec5SDimitry Andric         if (StackFrameSP frame_sp = GetFrameSP()) {
30640b57cec5SDimitry Andric           const SymbolContext &sc(
30650b57cec5SDimitry Andric               frame_sp->GetSymbolContext(eSymbolContextCompUnit));
30660b57cec5SDimitry Andric           if (CompileUnit *cu = sc.comp_unit)
30670b57cec5SDimitry Andric             type = cu->GetLanguage();
30680b57cec5SDimitry Andric         }
30690b57cec5SDimitry Andric       } else {
30700b57cec5SDimitry Andric         type = GetRoot()->GetPreferredDisplayLanguage();
30710b57cec5SDimitry Andric       }
30720b57cec5SDimitry Andric     }
30730b57cec5SDimitry Andric   }
30740b57cec5SDimitry Andric   return (m_preferred_display_language = type); // only compute it once
30750b57cec5SDimitry Andric }
30760b57cec5SDimitry Andric 
SetPreferredDisplayLanguageIfNeeded(lldb::LanguageType lt)30770b57cec5SDimitry Andric void ValueObject::SetPreferredDisplayLanguageIfNeeded(lldb::LanguageType lt) {
30780b57cec5SDimitry Andric   if (m_preferred_display_language == lldb::eLanguageTypeUnknown)
30790b57cec5SDimitry Andric     SetPreferredDisplayLanguage(lt);
30800b57cec5SDimitry Andric }
30810b57cec5SDimitry Andric 
CanProvideValue()30820b57cec5SDimitry Andric bool ValueObject::CanProvideValue() {
30830b57cec5SDimitry Andric   // we need to support invalid types as providers of values because some bare-
30840b57cec5SDimitry Andric   // board debugging scenarios have no notion of types, but still manage to
30850b57cec5SDimitry Andric   // have raw numeric values for things like registers. sigh.
3086e8d8bef9SDimitry Andric   CompilerType type = GetCompilerType();
30870b57cec5SDimitry Andric   return (!type.IsValid()) || (0 != (type.GetTypeInfo() & eTypeHasValue));
30880b57cec5SDimitry Andric }
30890b57cec5SDimitry Andric 
3090fe6060f1SDimitry Andric 
30910b57cec5SDimitry Andric 
Persist()30920b57cec5SDimitry Andric ValueObjectSP ValueObject::Persist() {
30930b57cec5SDimitry Andric   if (!UpdateValueIfNeeded())
30940b57cec5SDimitry Andric     return nullptr;
30950b57cec5SDimitry Andric 
30960b57cec5SDimitry Andric   TargetSP target_sp(GetTargetSP());
30970b57cec5SDimitry Andric   if (!target_sp)
30980b57cec5SDimitry Andric     return nullptr;
30990b57cec5SDimitry Andric 
31000b57cec5SDimitry Andric   PersistentExpressionState *persistent_state =
31010b57cec5SDimitry Andric       target_sp->GetPersistentExpressionStateForLanguage(
31020b57cec5SDimitry Andric           GetPreferredDisplayLanguage());
31030b57cec5SDimitry Andric 
31040b57cec5SDimitry Andric   if (!persistent_state)
31050b57cec5SDimitry Andric     return nullptr;
31060b57cec5SDimitry Andric 
31075ffd83dbSDimitry Andric   ConstString name = persistent_state->GetNextPersistentVariableName();
31080b57cec5SDimitry Andric 
31090b57cec5SDimitry Andric   ValueObjectSP const_result_sp =
31100b57cec5SDimitry Andric       ValueObjectConstResult::Create(target_sp.get(), GetValue(), name);
31110b57cec5SDimitry Andric 
31125ffd83dbSDimitry Andric   ExpressionVariableSP persistent_var_sp =
31130b57cec5SDimitry Andric       persistent_state->CreatePersistentVariable(const_result_sp);
31145ffd83dbSDimitry Andric   persistent_var_sp->m_live_sp = persistent_var_sp->m_frozen_sp;
31155ffd83dbSDimitry Andric   persistent_var_sp->m_flags |= ExpressionVariable::EVIsProgramReference;
31160b57cec5SDimitry Andric 
31175ffd83dbSDimitry Andric   return persistent_var_sp->GetValueObject();
31180b57cec5SDimitry Andric }
3119c9157d92SDimitry Andric 
GetVTable()3120c9157d92SDimitry Andric lldb::ValueObjectSP ValueObject::GetVTable() {
3121c9157d92SDimitry Andric   return ValueObjectVTable::Create(*this);
3122c9157d92SDimitry Andric }
3123