xref: /freebsd-src/contrib/llvm-project/lldb/source/Core/ValueObject.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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"
205f757f3fSDimitry 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
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
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 
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 
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 
219*0fca6ea1SDimitry Andric     SetValueFormat(DataVisualization::GetFormat(*this, GetDynamicValueType()));
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 
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 
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 
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 
2780b57cec5SDimitry Andric DataExtractor &ValueObject::GetDataExtractor() {
2790b57cec5SDimitry Andric   UpdateValueIfNeeded(false);
2800b57cec5SDimitry Andric   return m_data;
2810b57cec5SDimitry Andric }
2820b57cec5SDimitry Andric 
2830b57cec5SDimitry Andric const Status &ValueObject::GetError() {
2840b57cec5SDimitry Andric   UpdateValueIfNeeded(false);
2850b57cec5SDimitry Andric   return m_error;
2860b57cec5SDimitry Andric }
2870b57cec5SDimitry Andric 
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 
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);
3385f757f3fSDimitry 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 
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 
375*0fca6ea1SDimitry Andric ValueObjectSP ValueObject::GetChildAtIndex(uint32_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);
380*0fca6ea1SDimitry Andric   if (idx < GetNumChildrenIgnoringErrors()) {
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.
385*0fca6ea1SDimitry Andric       m_children.SetChildAtIndex(idx, CreateChildAtIndex(idx));
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
39606c3fb27SDimitry Andric ValueObject::GetChildAtNamePath(llvm::ArrayRef<llvm::StringRef> names) {
3970b57cec5SDimitry Andric   if (names.size() == 0)
3980b57cec5SDimitry Andric     return GetSP();
3990b57cec5SDimitry Andric   ValueObjectSP root(GetSP());
40006c3fb27SDimitry Andric   for (llvm::StringRef name : names) {
40106c3fb27SDimitry 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 
40906c3fb27SDimitry Andric size_t ValueObject::GetIndexOfChildWithName(llvm::StringRef name) {
4100b57cec5SDimitry Andric   bool omit_empty_base_classes = true;
41106c3fb27SDimitry Andric   return GetCompilerType().GetIndexOfChildWithName(name,
4120b57cec5SDimitry Andric                                                    omit_empty_base_classes);
4130b57cec5SDimitry Andric }
4140b57cec5SDimitry Andric 
41506c3fb27SDimitry 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(
43206c3fb27SDimitry 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 
443*0fca6ea1SDimitry Andric llvm::Expected<uint32_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) {
455*0fca6ea1SDimitry Andric     auto num_children_or_err = CalculateNumChildren();
456*0fca6ea1SDimitry Andric     if (num_children_or_err)
457*0fca6ea1SDimitry Andric       SetNumChildren(*num_children_or_err);
458*0fca6ea1SDimitry Andric     else
459*0fca6ea1SDimitry Andric       return num_children_or_err;
4600b57cec5SDimitry Andric   }
4610b57cec5SDimitry Andric   return m_children.GetChildrenCount();
4620b57cec5SDimitry Andric }
4630b57cec5SDimitry Andric 
464*0fca6ea1SDimitry Andric uint32_t ValueObject::GetNumChildrenIgnoringErrors(uint32_t max) {
465*0fca6ea1SDimitry Andric   auto value_or_err = GetNumChildren(max);
466*0fca6ea1SDimitry Andric   if (value_or_err)
467*0fca6ea1SDimitry Andric     return *value_or_err;
468*0fca6ea1SDimitry Andric   LLDB_LOG_ERRORV(GetLog(LLDBLog::DataFormatters), value_or_err.takeError(),
469*0fca6ea1SDimitry Andric                   "{0}");
470*0fca6ea1SDimitry Andric   return 0;
471*0fca6ea1SDimitry Andric }
472*0fca6ea1SDimitry Andric 
4730b57cec5SDimitry Andric bool ValueObject::MightHaveChildren() {
4740b57cec5SDimitry Andric   bool has_children = false;
4750b57cec5SDimitry Andric   const uint32_t type_info = GetTypeInfo();
4760b57cec5SDimitry Andric   if (type_info) {
4770b57cec5SDimitry Andric     if (type_info & (eTypeHasChildren | eTypeIsPointer | eTypeIsReference))
4780b57cec5SDimitry Andric       has_children = true;
4790b57cec5SDimitry Andric   } else {
480*0fca6ea1SDimitry Andric     has_children = GetNumChildrenIgnoringErrors() > 0;
4810b57cec5SDimitry Andric   }
4820b57cec5SDimitry Andric   return has_children;
4830b57cec5SDimitry Andric }
4840b57cec5SDimitry Andric 
4850b57cec5SDimitry Andric // Should only be called by ValueObject::GetNumChildren()
486*0fca6ea1SDimitry Andric void ValueObject::SetNumChildren(uint32_t num_children) {
487fe6060f1SDimitry Andric   m_flags.m_children_count_valid = true;
4880b57cec5SDimitry Andric   m_children.SetChildrenCount(num_children);
4890b57cec5SDimitry Andric }
4900b57cec5SDimitry Andric 
491*0fca6ea1SDimitry Andric ValueObject *ValueObject::CreateChildAtIndex(size_t idx) {
4920b57cec5SDimitry Andric   bool omit_empty_base_classes = true;
493*0fca6ea1SDimitry Andric   bool ignore_array_bounds = false;
494*0fca6ea1SDimitry Andric   std::string child_name;
4950b57cec5SDimitry Andric   uint32_t child_byte_size = 0;
4960b57cec5SDimitry Andric   int32_t child_byte_offset = 0;
4970b57cec5SDimitry Andric   uint32_t child_bitfield_bit_size = 0;
4980b57cec5SDimitry Andric   uint32_t child_bitfield_bit_offset = 0;
4990b57cec5SDimitry Andric   bool child_is_base_class = false;
5000b57cec5SDimitry Andric   bool child_is_deref_of_parent = false;
5010b57cec5SDimitry Andric   uint64_t language_flags = 0;
502*0fca6ea1SDimitry Andric   const bool transparent_pointers = true;
5030b57cec5SDimitry Andric 
5040b57cec5SDimitry Andric   ExecutionContext exe_ctx(GetExecutionContextRef());
5050b57cec5SDimitry Andric 
506*0fca6ea1SDimitry Andric   auto child_compiler_type_or_err =
507*0fca6ea1SDimitry Andric       GetCompilerType().GetChildCompilerTypeAtIndex(
5080b57cec5SDimitry Andric           &exe_ctx, idx, transparent_pointers, omit_empty_base_classes,
509*0fca6ea1SDimitry Andric           ignore_array_bounds, child_name, child_byte_size, child_byte_offset,
510*0fca6ea1SDimitry Andric           child_bitfield_bit_size, child_bitfield_bit_offset,
511*0fca6ea1SDimitry Andric           child_is_base_class, child_is_deref_of_parent, this, language_flags);
512*0fca6ea1SDimitry Andric   if (!child_compiler_type_or_err || !child_compiler_type_or_err->IsValid()) {
513*0fca6ea1SDimitry Andric     LLDB_LOG_ERROR(GetLog(LLDBLog::Types),
514*0fca6ea1SDimitry Andric                    child_compiler_type_or_err.takeError(),
515*0fca6ea1SDimitry Andric                    "could not find child: {0}");
516*0fca6ea1SDimitry Andric     return nullptr;
517*0fca6ea1SDimitry Andric   }
5180b57cec5SDimitry Andric 
519*0fca6ea1SDimitry Andric   return new ValueObjectChild(
520*0fca6ea1SDimitry Andric       *this, *child_compiler_type_or_err, ConstString(child_name),
521*0fca6ea1SDimitry Andric       child_byte_size, child_byte_offset, child_bitfield_bit_size,
522*0fca6ea1SDimitry Andric       child_bitfield_bit_offset, child_is_base_class, child_is_deref_of_parent,
523*0fca6ea1SDimitry Andric       eAddressTypeInvalid, language_flags);
524*0fca6ea1SDimitry Andric }
5250b57cec5SDimitry Andric 
526*0fca6ea1SDimitry Andric ValueObject *ValueObject::CreateSyntheticArrayMember(size_t idx) {
527*0fca6ea1SDimitry Andric   bool omit_empty_base_classes = true;
528*0fca6ea1SDimitry Andric   bool ignore_array_bounds = true;
529*0fca6ea1SDimitry Andric   std::string child_name;
530*0fca6ea1SDimitry Andric   uint32_t child_byte_size = 0;
531*0fca6ea1SDimitry Andric   int32_t child_byte_offset = 0;
532*0fca6ea1SDimitry Andric   uint32_t child_bitfield_bit_size = 0;
533*0fca6ea1SDimitry Andric   uint32_t child_bitfield_bit_offset = 0;
534*0fca6ea1SDimitry Andric   bool child_is_base_class = false;
535*0fca6ea1SDimitry Andric   bool child_is_deref_of_parent = false;
536*0fca6ea1SDimitry Andric   uint64_t language_flags = 0;
537*0fca6ea1SDimitry Andric   const bool transparent_pointers = false;
538*0fca6ea1SDimitry Andric 
539*0fca6ea1SDimitry Andric   ExecutionContext exe_ctx(GetExecutionContextRef());
540*0fca6ea1SDimitry Andric 
541*0fca6ea1SDimitry Andric   auto child_compiler_type_or_err =
542*0fca6ea1SDimitry Andric       GetCompilerType().GetChildCompilerTypeAtIndex(
543*0fca6ea1SDimitry Andric           &exe_ctx, 0, transparent_pointers, omit_empty_base_classes,
544*0fca6ea1SDimitry Andric           ignore_array_bounds, child_name, child_byte_size, child_byte_offset,
545*0fca6ea1SDimitry Andric           child_bitfield_bit_size, child_bitfield_bit_offset,
546*0fca6ea1SDimitry Andric           child_is_base_class, child_is_deref_of_parent, this, language_flags);
547*0fca6ea1SDimitry Andric   if (!child_compiler_type_or_err) {
548*0fca6ea1SDimitry Andric     LLDB_LOG_ERROR(GetLog(LLDBLog::Types),
549*0fca6ea1SDimitry Andric                    child_compiler_type_or_err.takeError(),
550*0fca6ea1SDimitry Andric                    "could not find child: {0}");
551*0fca6ea1SDimitry Andric     return nullptr;
552*0fca6ea1SDimitry Andric   }
553*0fca6ea1SDimitry Andric 
554*0fca6ea1SDimitry Andric   if (child_compiler_type_or_err->IsValid()) {
555*0fca6ea1SDimitry Andric     child_byte_offset += child_byte_size * idx;
556*0fca6ea1SDimitry Andric 
557*0fca6ea1SDimitry Andric     return new ValueObjectChild(
558*0fca6ea1SDimitry Andric         *this, *child_compiler_type_or_err, ConstString(child_name),
559*0fca6ea1SDimitry Andric         child_byte_size, child_byte_offset, child_bitfield_bit_size,
560*0fca6ea1SDimitry Andric         child_bitfield_bit_offset, child_is_base_class,
561*0fca6ea1SDimitry Andric         child_is_deref_of_parent, eAddressTypeInvalid, language_flags);
5620b57cec5SDimitry Andric   }
5630b57cec5SDimitry Andric 
5645ffd83dbSDimitry Andric   // In case of an incomplete type, try to use the ValueObject's
5655ffd83dbSDimitry Andric   // synthetic value to create the child ValueObject.
566*0fca6ea1SDimitry Andric   if (ValueObjectSP synth_valobj_sp = GetSyntheticValue())
567*0fca6ea1SDimitry Andric     return synth_valobj_sp->GetChildAtIndex(idx, /*can_create=*/true).get();
5685ffd83dbSDimitry Andric 
569*0fca6ea1SDimitry Andric   return nullptr;
5700b57cec5SDimitry Andric }
5710b57cec5SDimitry Andric 
5720b57cec5SDimitry Andric bool ValueObject::GetSummaryAsCString(TypeSummaryImpl *summary_ptr,
5730b57cec5SDimitry Andric                                       std::string &destination,
5740b57cec5SDimitry Andric                                       lldb::LanguageType lang) {
5750b57cec5SDimitry Andric   return GetSummaryAsCString(summary_ptr, destination,
5760b57cec5SDimitry Andric                              TypeSummaryOptions().SetLanguage(lang));
5770b57cec5SDimitry Andric }
5780b57cec5SDimitry Andric 
5790b57cec5SDimitry Andric bool ValueObject::GetSummaryAsCString(TypeSummaryImpl *summary_ptr,
5800b57cec5SDimitry Andric                                       std::string &destination,
5810b57cec5SDimitry Andric                                       const TypeSummaryOptions &options) {
5820b57cec5SDimitry Andric   destination.clear();
5830b57cec5SDimitry Andric 
584bdd1243dSDimitry Andric   // If we have a forcefully completed type, don't try and show a summary from
585bdd1243dSDimitry Andric   // a valid summary string or function because the type is not complete and
586bdd1243dSDimitry Andric   // no member variables or member functions will be available.
587bdd1243dSDimitry Andric   if (GetCompilerType().IsForcefullyCompleted()) {
588bdd1243dSDimitry Andric       destination = "<incomplete type>";
589bdd1243dSDimitry Andric       return true;
590bdd1243dSDimitry Andric   }
591bdd1243dSDimitry Andric 
5920b57cec5SDimitry Andric   // ideally we would like to bail out if passing NULL, but if we do so we end
5930b57cec5SDimitry Andric   // up not providing the summary for function pointers anymore
594fe6060f1SDimitry Andric   if (/*summary_ptr == NULL ||*/ m_flags.m_is_getting_summary)
5950b57cec5SDimitry Andric     return false;
5960b57cec5SDimitry Andric 
597fe6060f1SDimitry Andric   m_flags.m_is_getting_summary = true;
5980b57cec5SDimitry Andric 
5990b57cec5SDimitry Andric   TypeSummaryOptions actual_options(options);
6000b57cec5SDimitry Andric 
6010b57cec5SDimitry Andric   if (actual_options.GetLanguage() == lldb::eLanguageTypeUnknown)
6020b57cec5SDimitry Andric     actual_options.SetLanguage(GetPreferredDisplayLanguage());
6030b57cec5SDimitry Andric 
6040b57cec5SDimitry Andric   // this is a hot path in code and we prefer to avoid setting this string all
6050b57cec5SDimitry Andric   // too often also clearing out other information that we might care to see in
6060b57cec5SDimitry Andric   // a crash log. might be useful in very specific situations though.
6070b57cec5SDimitry Andric   /*Host::SetCrashDescriptionWithFormat("Trying to fetch a summary for %s %s.
6080b57cec5SDimitry Andric    Summary provider's description is %s",
6090b57cec5SDimitry Andric    GetTypeName().GetCString(),
6100b57cec5SDimitry Andric    GetName().GetCString(),
6110b57cec5SDimitry Andric    summary_ptr->GetDescription().c_str());*/
6120b57cec5SDimitry Andric 
6130b57cec5SDimitry Andric   if (UpdateValueIfNeeded(false) && summary_ptr) {
6140b57cec5SDimitry Andric     if (HasSyntheticValue())
6150b57cec5SDimitry Andric       m_synthetic_value->UpdateValueIfNeeded(); // the summary might depend on
6160b57cec5SDimitry Andric                                                 // the synthetic children being
6170b57cec5SDimitry Andric                                                 // up-to-date (e.g. ${svar%#})
6180b57cec5SDimitry Andric     summary_ptr->FormatObject(this, destination, actual_options);
6190b57cec5SDimitry Andric   }
620fe6060f1SDimitry Andric   m_flags.m_is_getting_summary = false;
6210b57cec5SDimitry Andric   return !destination.empty();
6220b57cec5SDimitry Andric }
6230b57cec5SDimitry Andric 
6240b57cec5SDimitry Andric const char *ValueObject::GetSummaryAsCString(lldb::LanguageType lang) {
6250b57cec5SDimitry Andric   if (UpdateValueIfNeeded(true) && m_summary_str.empty()) {
6260b57cec5SDimitry Andric     TypeSummaryOptions summary_options;
6270b57cec5SDimitry Andric     summary_options.SetLanguage(lang);
6280b57cec5SDimitry Andric     GetSummaryAsCString(GetSummaryFormat().get(), m_summary_str,
6290b57cec5SDimitry Andric                         summary_options);
6300b57cec5SDimitry Andric   }
6310b57cec5SDimitry Andric   if (m_summary_str.empty())
6320b57cec5SDimitry Andric     return nullptr;
6330b57cec5SDimitry Andric   return m_summary_str.c_str();
6340b57cec5SDimitry Andric }
6350b57cec5SDimitry Andric 
6360b57cec5SDimitry Andric bool ValueObject::GetSummaryAsCString(std::string &destination,
6370b57cec5SDimitry Andric                                       const TypeSummaryOptions &options) {
6380b57cec5SDimitry Andric   return GetSummaryAsCString(GetSummaryFormat().get(), destination, options);
6390b57cec5SDimitry Andric }
6400b57cec5SDimitry Andric 
6410b57cec5SDimitry Andric bool ValueObject::IsCStringContainer(bool check_pointer) {
6420b57cec5SDimitry Andric   CompilerType pointee_or_element_compiler_type;
6430b57cec5SDimitry Andric   const Flags type_flags(GetTypeInfo(&pointee_or_element_compiler_type));
6440b57cec5SDimitry Andric   bool is_char_arr_ptr(type_flags.AnySet(eTypeIsArray | eTypeIsPointer) &&
6450b57cec5SDimitry Andric                        pointee_or_element_compiler_type.IsCharType());
6460b57cec5SDimitry Andric   if (!is_char_arr_ptr)
6470b57cec5SDimitry Andric     return false;
6480b57cec5SDimitry Andric   if (!check_pointer)
6490b57cec5SDimitry Andric     return true;
6500b57cec5SDimitry Andric   if (type_flags.Test(eTypeIsArray))
6510b57cec5SDimitry Andric     return true;
6520b57cec5SDimitry Andric   addr_t cstr_address = LLDB_INVALID_ADDRESS;
6530b57cec5SDimitry Andric   AddressType cstr_address_type = eAddressTypeInvalid;
6545ffd83dbSDimitry Andric   cstr_address = GetPointerValue(&cstr_address_type);
6550b57cec5SDimitry Andric   return (cstr_address != LLDB_INVALID_ADDRESS);
6560b57cec5SDimitry Andric }
6570b57cec5SDimitry Andric 
6580b57cec5SDimitry Andric size_t ValueObject::GetPointeeData(DataExtractor &data, uint32_t item_idx,
6590b57cec5SDimitry Andric                                    uint32_t item_count) {
6600b57cec5SDimitry Andric   CompilerType pointee_or_element_compiler_type;
6610b57cec5SDimitry Andric   const uint32_t type_info = GetTypeInfo(&pointee_or_element_compiler_type);
6620b57cec5SDimitry Andric   const bool is_pointer_type = type_info & eTypeIsPointer;
6630b57cec5SDimitry Andric   const bool is_array_type = type_info & eTypeIsArray;
6640b57cec5SDimitry Andric   if (!(is_pointer_type || is_array_type))
6650b57cec5SDimitry Andric     return 0;
6660b57cec5SDimitry Andric 
6670b57cec5SDimitry Andric   if (item_count == 0)
6680b57cec5SDimitry Andric     return 0;
6690b57cec5SDimitry Andric 
6700b57cec5SDimitry Andric   ExecutionContext exe_ctx(GetExecutionContextRef());
6710b57cec5SDimitry Andric 
672bdd1243dSDimitry Andric   std::optional<uint64_t> item_type_size =
6730b57cec5SDimitry Andric       pointee_or_element_compiler_type.GetByteSize(
6740b57cec5SDimitry Andric           exe_ctx.GetBestExecutionContextScope());
6750b57cec5SDimitry Andric   if (!item_type_size)
6760b57cec5SDimitry Andric     return 0;
6770b57cec5SDimitry Andric   const uint64_t bytes = item_count * *item_type_size;
6780b57cec5SDimitry Andric   const uint64_t offset = item_idx * *item_type_size;
6790b57cec5SDimitry Andric 
6800b57cec5SDimitry Andric   if (item_idx == 0 && item_count == 1) // simply a deref
6810b57cec5SDimitry Andric   {
6820b57cec5SDimitry Andric     if (is_pointer_type) {
6830b57cec5SDimitry Andric       Status error;
6840b57cec5SDimitry Andric       ValueObjectSP pointee_sp = Dereference(error);
6850b57cec5SDimitry Andric       if (error.Fail() || pointee_sp.get() == nullptr)
6860b57cec5SDimitry Andric         return 0;
6870b57cec5SDimitry Andric       return pointee_sp->GetData(data, error);
6880b57cec5SDimitry Andric     } else {
68906c3fb27SDimitry Andric       ValueObjectSP child_sp = GetChildAtIndex(0);
6900b57cec5SDimitry Andric       if (child_sp.get() == nullptr)
6910b57cec5SDimitry Andric         return 0;
6920b57cec5SDimitry Andric       Status error;
6930b57cec5SDimitry Andric       return child_sp->GetData(data, error);
6940b57cec5SDimitry Andric     }
6950b57cec5SDimitry Andric     return true;
6960b57cec5SDimitry Andric   } else /* (items > 1) */
6970b57cec5SDimitry Andric   {
6980b57cec5SDimitry Andric     Status error;
6990b57cec5SDimitry Andric     lldb_private::DataBufferHeap *heap_buf_ptr = nullptr;
7000b57cec5SDimitry Andric     lldb::DataBufferSP data_sp(heap_buf_ptr =
7010b57cec5SDimitry Andric                                    new lldb_private::DataBufferHeap());
7020b57cec5SDimitry Andric 
7030b57cec5SDimitry Andric     AddressType addr_type;
7040b57cec5SDimitry Andric     lldb::addr_t addr = is_pointer_type ? GetPointerValue(&addr_type)
7050b57cec5SDimitry Andric                                         : GetAddressOf(true, &addr_type);
7060b57cec5SDimitry Andric 
7070b57cec5SDimitry Andric     switch (addr_type) {
7080b57cec5SDimitry Andric     case eAddressTypeFile: {
7090b57cec5SDimitry Andric       ModuleSP module_sp(GetModule());
7100b57cec5SDimitry Andric       if (module_sp) {
7110b57cec5SDimitry Andric         addr = addr + offset;
7120b57cec5SDimitry Andric         Address so_addr;
7130b57cec5SDimitry Andric         module_sp->ResolveFileAddress(addr, so_addr);
7140b57cec5SDimitry Andric         ExecutionContext exe_ctx(GetExecutionContextRef());
7150b57cec5SDimitry Andric         Target *target = exe_ctx.GetTargetPtr();
7160b57cec5SDimitry Andric         if (target) {
7170b57cec5SDimitry Andric           heap_buf_ptr->SetByteSize(bytes);
7180b57cec5SDimitry Andric           size_t bytes_read = target->ReadMemory(
719fe6060f1SDimitry Andric               so_addr, heap_buf_ptr->GetBytes(), bytes, error, true);
7200b57cec5SDimitry Andric           if (error.Success()) {
7210b57cec5SDimitry Andric             data.SetData(data_sp);
7220b57cec5SDimitry Andric             return bytes_read;
7230b57cec5SDimitry Andric           }
7240b57cec5SDimitry Andric         }
7250b57cec5SDimitry Andric       }
7260b57cec5SDimitry Andric     } break;
7270b57cec5SDimitry Andric     case eAddressTypeLoad: {
7280b57cec5SDimitry Andric       ExecutionContext exe_ctx(GetExecutionContextRef());
7290b57cec5SDimitry Andric       Process *process = exe_ctx.GetProcessPtr();
7300b57cec5SDimitry Andric       if (process) {
7310b57cec5SDimitry Andric         heap_buf_ptr->SetByteSize(bytes);
7320b57cec5SDimitry Andric         size_t bytes_read = process->ReadMemory(
7330b57cec5SDimitry Andric             addr + offset, heap_buf_ptr->GetBytes(), bytes, error);
7340b57cec5SDimitry Andric         if (error.Success() || bytes_read > 0) {
7350b57cec5SDimitry Andric           data.SetData(data_sp);
7360b57cec5SDimitry Andric           return bytes_read;
7370b57cec5SDimitry Andric         }
7380b57cec5SDimitry Andric       }
7390b57cec5SDimitry Andric     } break;
7400b57cec5SDimitry Andric     case eAddressTypeHost: {
7410b57cec5SDimitry Andric       auto max_bytes =
7420b57cec5SDimitry Andric           GetCompilerType().GetByteSize(exe_ctx.GetBestExecutionContextScope());
7430b57cec5SDimitry Andric       if (max_bytes && *max_bytes > offset) {
7440b57cec5SDimitry Andric         size_t bytes_read = std::min<uint64_t>(*max_bytes - offset, bytes);
7450b57cec5SDimitry Andric         addr = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
7460b57cec5SDimitry Andric         if (addr == 0 || addr == LLDB_INVALID_ADDRESS)
7470b57cec5SDimitry Andric           break;
7480b57cec5SDimitry Andric         heap_buf_ptr->CopyData((uint8_t *)(addr + offset), bytes_read);
7490b57cec5SDimitry Andric         data.SetData(data_sp);
7500b57cec5SDimitry Andric         return bytes_read;
7510b57cec5SDimitry Andric       }
7520b57cec5SDimitry Andric     } break;
7530b57cec5SDimitry Andric     case eAddressTypeInvalid:
7540b57cec5SDimitry Andric       break;
7550b57cec5SDimitry Andric     }
7560b57cec5SDimitry Andric   }
7570b57cec5SDimitry Andric   return 0;
7580b57cec5SDimitry Andric }
7590b57cec5SDimitry Andric 
7600b57cec5SDimitry Andric uint64_t ValueObject::GetData(DataExtractor &data, Status &error) {
7610b57cec5SDimitry Andric   UpdateValueIfNeeded(false);
7620b57cec5SDimitry Andric   ExecutionContext exe_ctx(GetExecutionContextRef());
7639dba64beSDimitry Andric   error = m_value.GetValueAsData(&exe_ctx, data, GetModule().get());
7640b57cec5SDimitry Andric   if (error.Fail()) {
7650b57cec5SDimitry Andric     if (m_data.GetByteSize()) {
7660b57cec5SDimitry Andric       data = m_data;
7670b57cec5SDimitry Andric       error.Clear();
7680b57cec5SDimitry Andric       return data.GetByteSize();
7690b57cec5SDimitry Andric     } else {
7700b57cec5SDimitry Andric       return 0;
7710b57cec5SDimitry Andric     }
7720b57cec5SDimitry Andric   }
7730b57cec5SDimitry Andric   data.SetAddressByteSize(m_data.GetAddressByteSize());
7740b57cec5SDimitry Andric   data.SetByteOrder(m_data.GetByteOrder());
7750b57cec5SDimitry Andric   return data.GetByteSize();
7760b57cec5SDimitry Andric }
7770b57cec5SDimitry Andric 
7780b57cec5SDimitry Andric bool ValueObject::SetData(DataExtractor &data, Status &error) {
7790b57cec5SDimitry Andric   error.Clear();
7800b57cec5SDimitry Andric   // Make sure our value is up to date first so that our location and location
7810b57cec5SDimitry Andric   // type is valid.
7820b57cec5SDimitry Andric   if (!UpdateValueIfNeeded(false)) {
7830b57cec5SDimitry Andric     error.SetErrorString("unable to read value");
7840b57cec5SDimitry Andric     return false;
7850b57cec5SDimitry Andric   }
7860b57cec5SDimitry Andric 
7870b57cec5SDimitry Andric   uint64_t count = 0;
7880b57cec5SDimitry Andric   const Encoding encoding = GetCompilerType().GetEncoding(count);
7890b57cec5SDimitry Andric 
79081ad6265SDimitry Andric   const size_t byte_size = GetByteSize().value_or(0);
7910b57cec5SDimitry Andric 
7920b57cec5SDimitry Andric   Value::ValueType value_type = m_value.GetValueType();
7930b57cec5SDimitry Andric 
7940b57cec5SDimitry Andric   switch (value_type) {
795fe6060f1SDimitry Andric   case Value::ValueType::Invalid:
796fe6060f1SDimitry Andric     error.SetErrorString("invalid location");
797fe6060f1SDimitry Andric     return false;
798fe6060f1SDimitry Andric   case Value::ValueType::Scalar: {
7990b57cec5SDimitry Andric     Status set_error =
8000b57cec5SDimitry Andric         m_value.GetScalar().SetValueFromData(data, encoding, byte_size);
8010b57cec5SDimitry Andric 
8020b57cec5SDimitry Andric     if (!set_error.Success()) {
8030b57cec5SDimitry Andric       error.SetErrorStringWithFormat("unable to set scalar value: %s",
8040b57cec5SDimitry Andric                                      set_error.AsCString());
8050b57cec5SDimitry Andric       return false;
8060b57cec5SDimitry Andric     }
8070b57cec5SDimitry Andric   } break;
808fe6060f1SDimitry Andric   case Value::ValueType::LoadAddress: {
8090b57cec5SDimitry Andric     // If it is a load address, then the scalar value is the storage location
8100b57cec5SDimitry Andric     // of the data, and we have to shove this value down to that load location.
8110b57cec5SDimitry Andric     ExecutionContext exe_ctx(GetExecutionContextRef());
8120b57cec5SDimitry Andric     Process *process = exe_ctx.GetProcessPtr();
8130b57cec5SDimitry Andric     if (process) {
8140b57cec5SDimitry Andric       addr_t target_addr = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
8150b57cec5SDimitry Andric       size_t bytes_written = process->WriteMemory(
8160b57cec5SDimitry Andric           target_addr, data.GetDataStart(), byte_size, error);
8170b57cec5SDimitry Andric       if (!error.Success())
8180b57cec5SDimitry Andric         return false;
8190b57cec5SDimitry Andric       if (bytes_written != byte_size) {
8200b57cec5SDimitry Andric         error.SetErrorString("unable to write value to memory");
8210b57cec5SDimitry Andric         return false;
8220b57cec5SDimitry Andric       }
8230b57cec5SDimitry Andric     }
8240b57cec5SDimitry Andric   } break;
825fe6060f1SDimitry Andric   case Value::ValueType::HostAddress: {
8260b57cec5SDimitry Andric     // If it is a host address, then we stuff the scalar as a DataBuffer into
8270b57cec5SDimitry Andric     // the Value's data.
8280b57cec5SDimitry Andric     DataBufferSP buffer_sp(new DataBufferHeap(byte_size, 0));
8290b57cec5SDimitry Andric     m_data.SetData(buffer_sp, 0);
8300b57cec5SDimitry Andric     data.CopyByteOrderedData(0, byte_size,
8310b57cec5SDimitry Andric                              const_cast<uint8_t *>(m_data.GetDataStart()),
8320b57cec5SDimitry Andric                              byte_size, m_data.GetByteOrder());
8330b57cec5SDimitry Andric     m_value.GetScalar() = (uintptr_t)m_data.GetDataStart();
8340b57cec5SDimitry Andric   } break;
835fe6060f1SDimitry Andric   case Value::ValueType::FileAddress:
8360b57cec5SDimitry Andric     break;
8370b57cec5SDimitry Andric   }
8380b57cec5SDimitry Andric 
8390b57cec5SDimitry Andric   // If we have reached this point, then we have successfully changed the
8400b57cec5SDimitry Andric   // value.
8410b57cec5SDimitry Andric   SetNeedsUpdate();
8420b57cec5SDimitry Andric   return true;
8430b57cec5SDimitry Andric }
8440b57cec5SDimitry Andric 
8450b57cec5SDimitry Andric static bool CopyStringDataToBufferSP(const StreamString &source,
84681ad6265SDimitry Andric                                      lldb::WritableDataBufferSP &destination) {
847349cc55cSDimitry Andric   llvm::StringRef src = source.GetString();
84881ad6265SDimitry Andric   src = src.rtrim('\0');
849349cc55cSDimitry Andric   destination = std::make_shared<DataBufferHeap>(src.size(), 0);
850349cc55cSDimitry Andric   memcpy(destination->GetBytes(), src.data(), src.size());
8510b57cec5SDimitry Andric   return true;
8520b57cec5SDimitry Andric }
8530b57cec5SDimitry Andric 
8540b57cec5SDimitry Andric std::pair<size_t, bool>
85581ad6265SDimitry Andric ValueObject::ReadPointedString(lldb::WritableDataBufferSP &buffer_sp,
8567a6dacacSDimitry Andric                                Status &error, bool honor_array) {
8570b57cec5SDimitry Andric   bool was_capped = false;
8580b57cec5SDimitry Andric   StreamString s;
8590b57cec5SDimitry Andric   ExecutionContext exe_ctx(GetExecutionContextRef());
8600b57cec5SDimitry Andric   Target *target = exe_ctx.GetTargetPtr();
8610b57cec5SDimitry Andric 
8620b57cec5SDimitry Andric   if (!target) {
8630b57cec5SDimitry Andric     s << "<no target to read from>";
8640b57cec5SDimitry Andric     error.SetErrorString("no target to read from");
8650b57cec5SDimitry Andric     CopyStringDataToBufferSP(s, buffer_sp);
8660b57cec5SDimitry Andric     return {0, was_capped};
8670b57cec5SDimitry Andric   }
8680b57cec5SDimitry Andric 
8697a6dacacSDimitry Andric   const auto max_length = target->GetMaximumSizeOfStringSummary();
8700b57cec5SDimitry Andric 
8710b57cec5SDimitry Andric   size_t bytes_read = 0;
8720b57cec5SDimitry Andric   size_t total_bytes_read = 0;
8730b57cec5SDimitry Andric 
8740b57cec5SDimitry Andric   CompilerType compiler_type = GetCompilerType();
8750b57cec5SDimitry Andric   CompilerType elem_or_pointee_compiler_type;
8760b57cec5SDimitry Andric   const Flags type_flags(GetTypeInfo(&elem_or_pointee_compiler_type));
8770b57cec5SDimitry Andric   if (type_flags.AnySet(eTypeIsArray | eTypeIsPointer) &&
8780b57cec5SDimitry Andric       elem_or_pointee_compiler_type.IsCharType()) {
8790b57cec5SDimitry Andric     addr_t cstr_address = LLDB_INVALID_ADDRESS;
8800b57cec5SDimitry Andric     AddressType cstr_address_type = eAddressTypeInvalid;
8810b57cec5SDimitry Andric 
8820b57cec5SDimitry Andric     size_t cstr_len = 0;
8830b57cec5SDimitry Andric     bool capped_data = false;
8840b57cec5SDimitry Andric     const bool is_array = type_flags.Test(eTypeIsArray);
8850b57cec5SDimitry Andric     if (is_array) {
8860b57cec5SDimitry Andric       // We have an array
8870b57cec5SDimitry Andric       uint64_t array_size = 0;
888fe6060f1SDimitry Andric       if (compiler_type.IsArrayType(nullptr, &array_size)) {
8890b57cec5SDimitry Andric         cstr_len = array_size;
8900b57cec5SDimitry Andric         if (cstr_len > max_length) {
8910b57cec5SDimitry Andric           capped_data = true;
8920b57cec5SDimitry Andric           cstr_len = max_length;
8930b57cec5SDimitry Andric         }
8940b57cec5SDimitry Andric       }
8950b57cec5SDimitry Andric       cstr_address = GetAddressOf(true, &cstr_address_type);
8960b57cec5SDimitry Andric     } else {
8970b57cec5SDimitry Andric       // We have a pointer
8980b57cec5SDimitry Andric       cstr_address = GetPointerValue(&cstr_address_type);
8990b57cec5SDimitry Andric     }
9000b57cec5SDimitry Andric 
9010b57cec5SDimitry Andric     if (cstr_address == 0 || cstr_address == LLDB_INVALID_ADDRESS) {
9020b57cec5SDimitry Andric       if (cstr_address_type == eAddressTypeHost && is_array) {
9030b57cec5SDimitry Andric         const char *cstr = GetDataExtractor().PeekCStr(0);
9040b57cec5SDimitry Andric         if (cstr == nullptr) {
9050b57cec5SDimitry Andric           s << "<invalid address>";
9060b57cec5SDimitry Andric           error.SetErrorString("invalid address");
9070b57cec5SDimitry Andric           CopyStringDataToBufferSP(s, buffer_sp);
9080b57cec5SDimitry Andric           return {0, was_capped};
9090b57cec5SDimitry Andric         }
910349cc55cSDimitry Andric         s << llvm::StringRef(cstr, cstr_len);
911349cc55cSDimitry Andric         CopyStringDataToBufferSP(s, buffer_sp);
9120b57cec5SDimitry Andric         return {cstr_len, was_capped};
9130b57cec5SDimitry Andric       } else {
9140b57cec5SDimitry Andric         s << "<invalid address>";
9150b57cec5SDimitry Andric         error.SetErrorString("invalid address");
9160b57cec5SDimitry Andric         CopyStringDataToBufferSP(s, buffer_sp);
9170b57cec5SDimitry Andric         return {0, was_capped};
9180b57cec5SDimitry Andric       }
9190b57cec5SDimitry Andric     }
9200b57cec5SDimitry Andric 
9210b57cec5SDimitry Andric     Address cstr_so_addr(cstr_address);
9220b57cec5SDimitry Andric     DataExtractor data;
9230b57cec5SDimitry Andric     if (cstr_len > 0 && honor_array) {
9240b57cec5SDimitry Andric       // I am using GetPointeeData() here to abstract the fact that some
9250b57cec5SDimitry Andric       // ValueObjects are actually frozen pointers in the host but the pointed-
9260b57cec5SDimitry Andric       // to data lives in the debuggee, and GetPointeeData() automatically
9270b57cec5SDimitry Andric       // takes care of this
9280b57cec5SDimitry Andric       GetPointeeData(data, 0, cstr_len);
9290b57cec5SDimitry Andric 
9300b57cec5SDimitry Andric       if ((bytes_read = data.GetByteSize()) > 0) {
9310b57cec5SDimitry Andric         total_bytes_read = bytes_read;
9320b57cec5SDimitry Andric         for (size_t offset = 0; offset < bytes_read; offset++)
9330b57cec5SDimitry Andric           s.Printf("%c", *data.PeekData(offset, 1));
9340b57cec5SDimitry Andric         if (capped_data)
9350b57cec5SDimitry Andric           was_capped = true;
9360b57cec5SDimitry Andric       }
9370b57cec5SDimitry Andric     } else {
9380b57cec5SDimitry Andric       cstr_len = max_length;
9390b57cec5SDimitry Andric       const size_t k_max_buf_size = 64;
9400b57cec5SDimitry Andric 
9410b57cec5SDimitry Andric       size_t offset = 0;
9420b57cec5SDimitry Andric 
9430b57cec5SDimitry Andric       int cstr_len_displayed = -1;
9440b57cec5SDimitry Andric       bool capped_cstr = false;
9450b57cec5SDimitry Andric       // I am using GetPointeeData() here to abstract the fact that some
9460b57cec5SDimitry Andric       // ValueObjects are actually frozen pointers in the host but the pointed-
9470b57cec5SDimitry Andric       // to data lives in the debuggee, and GetPointeeData() automatically
9480b57cec5SDimitry Andric       // takes care of this
9490b57cec5SDimitry Andric       while ((bytes_read = GetPointeeData(data, offset, k_max_buf_size)) > 0) {
9500b57cec5SDimitry Andric         total_bytes_read += bytes_read;
9510b57cec5SDimitry Andric         const char *cstr = data.PeekCStr(0);
9520b57cec5SDimitry Andric         size_t len = strnlen(cstr, k_max_buf_size);
9530b57cec5SDimitry Andric         if (cstr_len_displayed < 0)
9540b57cec5SDimitry Andric           cstr_len_displayed = len;
9550b57cec5SDimitry Andric 
9560b57cec5SDimitry Andric         if (len == 0)
9570b57cec5SDimitry Andric           break;
9580b57cec5SDimitry Andric         cstr_len_displayed += len;
9590b57cec5SDimitry Andric         if (len > bytes_read)
9600b57cec5SDimitry Andric           len = bytes_read;
9610b57cec5SDimitry Andric         if (len > cstr_len)
9620b57cec5SDimitry Andric           len = cstr_len;
9630b57cec5SDimitry Andric 
9640b57cec5SDimitry Andric         for (size_t offset = 0; offset < bytes_read; offset++)
9650b57cec5SDimitry Andric           s.Printf("%c", *data.PeekData(offset, 1));
9660b57cec5SDimitry Andric 
9670b57cec5SDimitry Andric         if (len < k_max_buf_size)
9680b57cec5SDimitry Andric           break;
9690b57cec5SDimitry Andric 
9700b57cec5SDimitry Andric         if (len >= cstr_len) {
9710b57cec5SDimitry Andric           capped_cstr = true;
9720b57cec5SDimitry Andric           break;
9730b57cec5SDimitry Andric         }
9740b57cec5SDimitry Andric 
9750b57cec5SDimitry Andric         cstr_len -= len;
9760b57cec5SDimitry Andric         offset += len;
9770b57cec5SDimitry Andric       }
9780b57cec5SDimitry Andric 
9790b57cec5SDimitry Andric       if (cstr_len_displayed >= 0) {
9800b57cec5SDimitry Andric         if (capped_cstr)
9810b57cec5SDimitry Andric           was_capped = true;
9820b57cec5SDimitry Andric       }
9830b57cec5SDimitry Andric     }
9840b57cec5SDimitry Andric   } else {
9850b57cec5SDimitry Andric     error.SetErrorString("not a string object");
9860b57cec5SDimitry Andric     s << "<not a string object>";
9870b57cec5SDimitry Andric   }
9880b57cec5SDimitry Andric   CopyStringDataToBufferSP(s, buffer_sp);
9890b57cec5SDimitry Andric   return {total_bytes_read, was_capped};
9900b57cec5SDimitry Andric }
9910b57cec5SDimitry Andric 
992*0fca6ea1SDimitry Andric llvm::Expected<std::string> ValueObject::GetObjectDescription() {
9930b57cec5SDimitry Andric   if (!UpdateValueIfNeeded(true))
994*0fca6ea1SDimitry Andric     return llvm::createStringError("could not update value");
9950b57cec5SDimitry Andric 
9960b57cec5SDimitry Andric   // Return cached value.
9970b57cec5SDimitry Andric   if (!m_object_desc_str.empty())
998*0fca6ea1SDimitry Andric     return m_object_desc_str;
9990b57cec5SDimitry Andric 
10000b57cec5SDimitry Andric   ExecutionContext exe_ctx(GetExecutionContextRef());
10010b57cec5SDimitry Andric   Process *process = exe_ctx.GetProcessPtr();
10020b57cec5SDimitry Andric   if (!process)
1003*0fca6ea1SDimitry Andric     return llvm::createStringError("no process");
10040b57cec5SDimitry Andric 
10050b57cec5SDimitry Andric   // Returns the object description produced by one language runtime.
1006*0fca6ea1SDimitry Andric   auto get_object_description =
1007*0fca6ea1SDimitry Andric       [&](LanguageType language) -> llvm::Expected<std::string> {
10080b57cec5SDimitry Andric     if (LanguageRuntime *runtime = process->GetLanguageRuntime(language)) {
10090b57cec5SDimitry Andric       StreamString s;
1010*0fca6ea1SDimitry Andric       if (llvm::Error error = runtime->GetObjectDescription(s, *this))
1011*0fca6ea1SDimitry Andric         return error;
1012*0fca6ea1SDimitry Andric       m_object_desc_str = s.GetString();
1013*0fca6ea1SDimitry Andric       return m_object_desc_str;
10140b57cec5SDimitry Andric     }
1015*0fca6ea1SDimitry Andric     return llvm::createStringError("no native language runtime");
10160b57cec5SDimitry Andric   };
10170b57cec5SDimitry Andric 
10180b57cec5SDimitry Andric   // Try the native language runtime first.
10190b57cec5SDimitry Andric   LanguageType native_language = GetObjectRuntimeLanguage();
1020*0fca6ea1SDimitry Andric   llvm::Expected<std::string> desc = get_object_description(native_language);
1021*0fca6ea1SDimitry Andric   if (desc)
10220b57cec5SDimitry Andric     return desc;
10230b57cec5SDimitry Andric 
10240b57cec5SDimitry Andric   // Try the Objective-C language runtime. This fallback is necessary
10250b57cec5SDimitry Andric   // for Objective-C++ and mixed Objective-C / C++ programs.
1026*0fca6ea1SDimitry Andric   if (Language::LanguageIsCFamily(native_language)) {
1027*0fca6ea1SDimitry Andric     // We're going to try again, so let's drop the first error.
1028*0fca6ea1SDimitry Andric     llvm::consumeError(desc.takeError());
10290b57cec5SDimitry Andric     return get_object_description(eLanguageTypeObjC);
1030*0fca6ea1SDimitry Andric   }
1031*0fca6ea1SDimitry Andric   return desc;
10320b57cec5SDimitry Andric }
10330b57cec5SDimitry Andric 
10340b57cec5SDimitry Andric bool ValueObject::GetValueAsCString(const lldb_private::TypeFormatImpl &format,
10350b57cec5SDimitry Andric                                     std::string &destination) {
10360b57cec5SDimitry Andric   if (UpdateValueIfNeeded(false))
10370b57cec5SDimitry Andric     return format.FormatObject(this, destination);
10380b57cec5SDimitry Andric   else
10390b57cec5SDimitry Andric     return false;
10400b57cec5SDimitry Andric }
10410b57cec5SDimitry Andric 
10420b57cec5SDimitry Andric bool ValueObject::GetValueAsCString(lldb::Format format,
10430b57cec5SDimitry Andric                                     std::string &destination) {
10440b57cec5SDimitry Andric   return GetValueAsCString(TypeFormatImpl_Format(format), destination);
10450b57cec5SDimitry Andric }
10460b57cec5SDimitry Andric 
10470b57cec5SDimitry Andric const char *ValueObject::GetValueAsCString() {
10480b57cec5SDimitry Andric   if (UpdateValueIfNeeded(true)) {
10490b57cec5SDimitry Andric     lldb::TypeFormatImplSP format_sp;
10500b57cec5SDimitry Andric     lldb::Format my_format = GetFormat();
10510b57cec5SDimitry Andric     if (my_format == lldb::eFormatDefault) {
10520b57cec5SDimitry Andric       if (m_type_format_sp)
10530b57cec5SDimitry Andric         format_sp = m_type_format_sp;
10540b57cec5SDimitry Andric       else {
1055fe6060f1SDimitry Andric         if (m_flags.m_is_bitfield_for_scalar)
10560b57cec5SDimitry Andric           my_format = eFormatUnsigned;
10570b57cec5SDimitry Andric         else {
1058fe6060f1SDimitry Andric           if (m_value.GetContextType() == Value::ContextType::RegisterInfo) {
10590b57cec5SDimitry Andric             const RegisterInfo *reg_info = m_value.GetRegisterInfo();
10600b57cec5SDimitry Andric             if (reg_info)
10610b57cec5SDimitry Andric               my_format = reg_info->format;
10620b57cec5SDimitry Andric           } else {
10630b57cec5SDimitry Andric             my_format = GetValue().GetCompilerType().GetFormat();
10640b57cec5SDimitry Andric           }
10650b57cec5SDimitry Andric         }
10660b57cec5SDimitry Andric       }
10670b57cec5SDimitry Andric     }
10680b57cec5SDimitry Andric     if (my_format != m_last_format || m_value_str.empty()) {
10690b57cec5SDimitry Andric       m_last_format = my_format;
10700b57cec5SDimitry Andric       if (!format_sp)
10710b57cec5SDimitry Andric         format_sp = std::make_shared<TypeFormatImpl_Format>(my_format);
10720b57cec5SDimitry Andric       if (GetValueAsCString(*format_sp.get(), m_value_str)) {
1073fe6060f1SDimitry Andric         if (!m_flags.m_value_did_change && m_flags.m_old_value_valid) {
10740b57cec5SDimitry Andric           // The value was gotten successfully, so we consider the value as
10750b57cec5SDimitry Andric           // changed if the value string differs
10760b57cec5SDimitry Andric           SetValueDidChange(m_old_value_str != m_value_str);
10770b57cec5SDimitry Andric         }
10780b57cec5SDimitry Andric       }
10790b57cec5SDimitry Andric     }
10800b57cec5SDimitry Andric   }
10810b57cec5SDimitry Andric   if (m_value_str.empty())
10820b57cec5SDimitry Andric     return nullptr;
10830b57cec5SDimitry Andric   return m_value_str.c_str();
10840b57cec5SDimitry Andric }
10850b57cec5SDimitry Andric 
10860b57cec5SDimitry Andric // if > 8bytes, 0 is returned. this method should mostly be used to read
10870b57cec5SDimitry Andric // address values out of pointers
10880b57cec5SDimitry Andric uint64_t ValueObject::GetValueAsUnsigned(uint64_t fail_value, bool *success) {
10890b57cec5SDimitry Andric   // If our byte size is zero this is an aggregate type that has children
10900b57cec5SDimitry Andric   if (CanProvideValue()) {
10910b57cec5SDimitry Andric     Scalar scalar;
10920b57cec5SDimitry Andric     if (ResolveValue(scalar)) {
10930b57cec5SDimitry Andric       if (success)
10940b57cec5SDimitry Andric         *success = true;
10955ffd83dbSDimitry Andric       scalar.MakeUnsigned();
10960b57cec5SDimitry Andric       return scalar.ULongLong(fail_value);
10970b57cec5SDimitry Andric     }
10980b57cec5SDimitry Andric     // fallthrough, otherwise...
10990b57cec5SDimitry Andric   }
11000b57cec5SDimitry Andric 
11010b57cec5SDimitry Andric   if (success)
11020b57cec5SDimitry Andric     *success = false;
11030b57cec5SDimitry Andric   return fail_value;
11040b57cec5SDimitry Andric }
11050b57cec5SDimitry Andric 
11060b57cec5SDimitry Andric int64_t ValueObject::GetValueAsSigned(int64_t fail_value, bool *success) {
11070b57cec5SDimitry Andric   // If our byte size is zero this is an aggregate type that has children
11080b57cec5SDimitry Andric   if (CanProvideValue()) {
11090b57cec5SDimitry Andric     Scalar scalar;
11100b57cec5SDimitry Andric     if (ResolveValue(scalar)) {
11110b57cec5SDimitry Andric       if (success)
11120b57cec5SDimitry Andric         *success = true;
11135ffd83dbSDimitry Andric       scalar.MakeSigned();
11140b57cec5SDimitry Andric       return scalar.SLongLong(fail_value);
11150b57cec5SDimitry Andric     }
11160b57cec5SDimitry Andric     // fallthrough, otherwise...
11170b57cec5SDimitry Andric   }
11180b57cec5SDimitry Andric 
11190b57cec5SDimitry Andric   if (success)
11200b57cec5SDimitry Andric     *success = false;
11210b57cec5SDimitry Andric   return fail_value;
11220b57cec5SDimitry Andric }
11230b57cec5SDimitry Andric 
1124*0fca6ea1SDimitry Andric llvm::Expected<llvm::APSInt> ValueObject::GetValueAsAPSInt() {
1125*0fca6ea1SDimitry Andric   // Make sure the type can be converted to an APSInt.
1126*0fca6ea1SDimitry Andric   if (!GetCompilerType().IsInteger() &&
1127*0fca6ea1SDimitry Andric       !GetCompilerType().IsScopedEnumerationType() &&
1128*0fca6ea1SDimitry Andric       !GetCompilerType().IsEnumerationType() &&
1129*0fca6ea1SDimitry Andric       !GetCompilerType().IsPointerType() &&
1130*0fca6ea1SDimitry Andric       !GetCompilerType().IsNullPtrType() &&
1131*0fca6ea1SDimitry Andric       !GetCompilerType().IsReferenceType() && !GetCompilerType().IsBoolean())
1132*0fca6ea1SDimitry Andric     return llvm::make_error<llvm::StringError>(
1133*0fca6ea1SDimitry Andric         "type cannot be converted to APSInt", llvm::inconvertibleErrorCode());
1134*0fca6ea1SDimitry Andric 
1135*0fca6ea1SDimitry Andric   if (CanProvideValue()) {
1136*0fca6ea1SDimitry Andric     Scalar scalar;
1137*0fca6ea1SDimitry Andric     if (ResolveValue(scalar))
1138*0fca6ea1SDimitry Andric       return scalar.GetAPSInt();
1139*0fca6ea1SDimitry Andric   }
1140*0fca6ea1SDimitry Andric 
1141*0fca6ea1SDimitry Andric   return llvm::make_error<llvm::StringError>(
1142*0fca6ea1SDimitry Andric       "error occurred; unable to convert to APSInt",
1143*0fca6ea1SDimitry Andric       llvm::inconvertibleErrorCode());
1144*0fca6ea1SDimitry Andric }
1145*0fca6ea1SDimitry Andric 
1146*0fca6ea1SDimitry Andric llvm::Expected<llvm::APFloat> ValueObject::GetValueAsAPFloat() {
1147*0fca6ea1SDimitry Andric   if (!GetCompilerType().IsFloat())
1148*0fca6ea1SDimitry Andric     return llvm::make_error<llvm::StringError>(
1149*0fca6ea1SDimitry Andric         "type cannot be converted to APFloat", llvm::inconvertibleErrorCode());
1150*0fca6ea1SDimitry Andric 
1151*0fca6ea1SDimitry Andric   if (CanProvideValue()) {
1152*0fca6ea1SDimitry Andric     Scalar scalar;
1153*0fca6ea1SDimitry Andric     if (ResolveValue(scalar))
1154*0fca6ea1SDimitry Andric       return scalar.GetAPFloat();
1155*0fca6ea1SDimitry Andric   }
1156*0fca6ea1SDimitry Andric 
1157*0fca6ea1SDimitry Andric   return llvm::make_error<llvm::StringError>(
1158*0fca6ea1SDimitry Andric       "error occurred; unable to convert to APFloat",
1159*0fca6ea1SDimitry Andric       llvm::inconvertibleErrorCode());
1160*0fca6ea1SDimitry Andric }
1161*0fca6ea1SDimitry Andric 
1162*0fca6ea1SDimitry Andric llvm::Expected<bool> ValueObject::GetValueAsBool() {
1163*0fca6ea1SDimitry Andric   CompilerType val_type = GetCompilerType();
1164*0fca6ea1SDimitry Andric   if (val_type.IsInteger() || val_type.IsUnscopedEnumerationType() ||
1165*0fca6ea1SDimitry Andric       val_type.IsPointerType()) {
1166*0fca6ea1SDimitry Andric     auto value_or_err = GetValueAsAPSInt();
1167*0fca6ea1SDimitry Andric     if (value_or_err)
1168*0fca6ea1SDimitry Andric       return value_or_err->getBoolValue();
1169*0fca6ea1SDimitry Andric   }
1170*0fca6ea1SDimitry Andric   if (val_type.IsFloat()) {
1171*0fca6ea1SDimitry Andric     auto value_or_err = GetValueAsAPFloat();
1172*0fca6ea1SDimitry Andric     if (value_or_err)
1173*0fca6ea1SDimitry Andric       return value_or_err->isNonZero();
1174*0fca6ea1SDimitry Andric   }
1175*0fca6ea1SDimitry Andric   if (val_type.IsArrayType())
1176*0fca6ea1SDimitry Andric     return GetAddressOf() != 0;
1177*0fca6ea1SDimitry Andric 
1178*0fca6ea1SDimitry Andric   return llvm::make_error<llvm::StringError>("type cannot be converted to bool",
1179*0fca6ea1SDimitry Andric                                              llvm::inconvertibleErrorCode());
1180*0fca6ea1SDimitry Andric }
1181*0fca6ea1SDimitry Andric 
1182*0fca6ea1SDimitry Andric void ValueObject::SetValueFromInteger(const llvm::APInt &value, Status &error) {
1183*0fca6ea1SDimitry Andric   // Verify the current object is an integer object
1184*0fca6ea1SDimitry Andric   CompilerType val_type = GetCompilerType();
1185*0fca6ea1SDimitry Andric   if (!val_type.IsInteger() && !val_type.IsUnscopedEnumerationType() &&
1186*0fca6ea1SDimitry Andric       !val_type.IsFloat() && !val_type.IsPointerType() &&
1187*0fca6ea1SDimitry Andric       !val_type.IsScalarType()) {
1188*0fca6ea1SDimitry Andric     error.SetErrorString("current value object is not an integer objet");
1189*0fca6ea1SDimitry Andric     return;
1190*0fca6ea1SDimitry Andric   }
1191*0fca6ea1SDimitry Andric 
1192*0fca6ea1SDimitry Andric   // Verify the current object is not actually associated with any program
1193*0fca6ea1SDimitry Andric   // variable.
1194*0fca6ea1SDimitry Andric   if (GetVariable()) {
1195*0fca6ea1SDimitry Andric     error.SetErrorString("current value object is not a temporary object");
1196*0fca6ea1SDimitry Andric     return;
1197*0fca6ea1SDimitry Andric   }
1198*0fca6ea1SDimitry Andric 
1199*0fca6ea1SDimitry Andric   // Verify the proposed new value is the right size.
1200*0fca6ea1SDimitry Andric   lldb::TargetSP target = GetTargetSP();
1201*0fca6ea1SDimitry Andric   uint64_t byte_size = 0;
1202*0fca6ea1SDimitry Andric   if (auto temp = GetCompilerType().GetByteSize(target.get()))
1203*0fca6ea1SDimitry Andric     byte_size = temp.value();
1204*0fca6ea1SDimitry Andric   if (value.getBitWidth() != byte_size * CHAR_BIT) {
1205*0fca6ea1SDimitry Andric     error.SetErrorString(
1206*0fca6ea1SDimitry Andric         "illegal argument: new value should be of the same size");
1207*0fca6ea1SDimitry Andric     return;
1208*0fca6ea1SDimitry Andric   }
1209*0fca6ea1SDimitry Andric 
1210*0fca6ea1SDimitry Andric   lldb::DataExtractorSP data_sp;
1211*0fca6ea1SDimitry Andric   data_sp->SetData(value.getRawData(), byte_size,
1212*0fca6ea1SDimitry Andric                    target->GetArchitecture().GetByteOrder());
1213*0fca6ea1SDimitry Andric   data_sp->SetAddressByteSize(
1214*0fca6ea1SDimitry Andric       static_cast<uint8_t>(target->GetArchitecture().GetAddressByteSize()));
1215*0fca6ea1SDimitry Andric   SetData(*data_sp, error);
1216*0fca6ea1SDimitry Andric }
1217*0fca6ea1SDimitry Andric 
1218*0fca6ea1SDimitry Andric void ValueObject::SetValueFromInteger(lldb::ValueObjectSP new_val_sp,
1219*0fca6ea1SDimitry Andric                                       Status &error) {
1220*0fca6ea1SDimitry Andric   // Verify the current object is an integer object
1221*0fca6ea1SDimitry Andric   CompilerType val_type = GetCompilerType();
1222*0fca6ea1SDimitry Andric   if (!val_type.IsInteger() && !val_type.IsUnscopedEnumerationType() &&
1223*0fca6ea1SDimitry Andric       !val_type.IsFloat() && !val_type.IsPointerType() &&
1224*0fca6ea1SDimitry Andric       !val_type.IsScalarType()) {
1225*0fca6ea1SDimitry Andric     error.SetErrorString("current value object is not an integer objet");
1226*0fca6ea1SDimitry Andric     return;
1227*0fca6ea1SDimitry Andric   }
1228*0fca6ea1SDimitry Andric 
1229*0fca6ea1SDimitry Andric   // Verify the current object is not actually associated with any program
1230*0fca6ea1SDimitry Andric   // variable.
1231*0fca6ea1SDimitry Andric   if (GetVariable()) {
1232*0fca6ea1SDimitry Andric     error.SetErrorString("current value object is not a temporary object");
1233*0fca6ea1SDimitry Andric     return;
1234*0fca6ea1SDimitry Andric   }
1235*0fca6ea1SDimitry Andric 
1236*0fca6ea1SDimitry Andric   // Verify the proposed new value is the right type.
1237*0fca6ea1SDimitry Andric   CompilerType new_val_type = new_val_sp->GetCompilerType();
1238*0fca6ea1SDimitry Andric   if (!new_val_type.IsInteger() && !new_val_type.IsFloat() &&
1239*0fca6ea1SDimitry Andric       !new_val_type.IsPointerType()) {
1240*0fca6ea1SDimitry Andric     error.SetErrorString(
1241*0fca6ea1SDimitry Andric         "illegal argument: new value should be of the same size");
1242*0fca6ea1SDimitry Andric     return;
1243*0fca6ea1SDimitry Andric   }
1244*0fca6ea1SDimitry Andric 
1245*0fca6ea1SDimitry Andric   if (new_val_type.IsInteger()) {
1246*0fca6ea1SDimitry Andric     auto value_or_err = new_val_sp->GetValueAsAPSInt();
1247*0fca6ea1SDimitry Andric     if (value_or_err)
1248*0fca6ea1SDimitry Andric       SetValueFromInteger(*value_or_err, error);
1249*0fca6ea1SDimitry Andric     else
1250*0fca6ea1SDimitry Andric       error.SetErrorString("error getting APSInt from new_val_sp");
1251*0fca6ea1SDimitry Andric   } else if (new_val_type.IsFloat()) {
1252*0fca6ea1SDimitry Andric     auto value_or_err = new_val_sp->GetValueAsAPFloat();
1253*0fca6ea1SDimitry Andric     if (value_or_err)
1254*0fca6ea1SDimitry Andric       SetValueFromInteger(value_or_err->bitcastToAPInt(), error);
1255*0fca6ea1SDimitry Andric     else
1256*0fca6ea1SDimitry Andric       error.SetErrorString("error getting APFloat from new_val_sp");
1257*0fca6ea1SDimitry Andric   } else if (new_val_type.IsPointerType()) {
1258*0fca6ea1SDimitry Andric     bool success = true;
1259*0fca6ea1SDimitry Andric     uint64_t int_val = new_val_sp->GetValueAsUnsigned(0, &success);
1260*0fca6ea1SDimitry Andric     if (success) {
1261*0fca6ea1SDimitry Andric       lldb::TargetSP target = GetTargetSP();
1262*0fca6ea1SDimitry Andric       uint64_t num_bits = 0;
1263*0fca6ea1SDimitry Andric       if (auto temp = new_val_sp->GetCompilerType().GetBitSize(target.get()))
1264*0fca6ea1SDimitry Andric         num_bits = temp.value();
1265*0fca6ea1SDimitry Andric       SetValueFromInteger(llvm::APInt(num_bits, int_val), error);
1266*0fca6ea1SDimitry Andric     } else
1267*0fca6ea1SDimitry Andric       error.SetErrorString("error converting new_val_sp to integer");
1268*0fca6ea1SDimitry Andric   }
1269*0fca6ea1SDimitry Andric }
1270*0fca6ea1SDimitry Andric 
12710b57cec5SDimitry Andric // if any more "special cases" are added to
12720b57cec5SDimitry Andric // ValueObject::DumpPrintableRepresentation() please keep this call up to date
12730b57cec5SDimitry Andric // by returning true for your new special cases. We will eventually move to
12740b57cec5SDimitry Andric // checking this call result before trying to display special cases
12750b57cec5SDimitry Andric bool ValueObject::HasSpecialPrintableRepresentation(
12760b57cec5SDimitry Andric     ValueObjectRepresentationStyle val_obj_display, Format custom_format) {
12770b57cec5SDimitry Andric   Flags flags(GetTypeInfo());
12780b57cec5SDimitry Andric   if (flags.AnySet(eTypeIsArray | eTypeIsPointer) &&
12790b57cec5SDimitry Andric       val_obj_display == ValueObject::eValueObjectRepresentationStyleValue) {
12800b57cec5SDimitry Andric     if (IsCStringContainer(true) &&
12810b57cec5SDimitry Andric         (custom_format == eFormatCString || custom_format == eFormatCharArray ||
12820b57cec5SDimitry Andric          custom_format == eFormatChar || custom_format == eFormatVectorOfChar))
12830b57cec5SDimitry Andric       return true;
12840b57cec5SDimitry Andric 
12850b57cec5SDimitry Andric     if (flags.Test(eTypeIsArray)) {
12860b57cec5SDimitry Andric       if ((custom_format == eFormatBytes) ||
12870b57cec5SDimitry Andric           (custom_format == eFormatBytesWithASCII))
12880b57cec5SDimitry Andric         return true;
12890b57cec5SDimitry Andric 
12900b57cec5SDimitry Andric       if ((custom_format == eFormatVectorOfChar) ||
12910b57cec5SDimitry Andric           (custom_format == eFormatVectorOfFloat32) ||
12920b57cec5SDimitry Andric           (custom_format == eFormatVectorOfFloat64) ||
12930b57cec5SDimitry Andric           (custom_format == eFormatVectorOfSInt16) ||
12940b57cec5SDimitry Andric           (custom_format == eFormatVectorOfSInt32) ||
12950b57cec5SDimitry Andric           (custom_format == eFormatVectorOfSInt64) ||
12960b57cec5SDimitry Andric           (custom_format == eFormatVectorOfSInt8) ||
12970b57cec5SDimitry Andric           (custom_format == eFormatVectorOfUInt128) ||
12980b57cec5SDimitry Andric           (custom_format == eFormatVectorOfUInt16) ||
12990b57cec5SDimitry Andric           (custom_format == eFormatVectorOfUInt32) ||
13000b57cec5SDimitry Andric           (custom_format == eFormatVectorOfUInt64) ||
13010b57cec5SDimitry Andric           (custom_format == eFormatVectorOfUInt8))
13020b57cec5SDimitry Andric         return true;
13030b57cec5SDimitry Andric     }
13040b57cec5SDimitry Andric   }
13050b57cec5SDimitry Andric   return false;
13060b57cec5SDimitry Andric }
13070b57cec5SDimitry Andric 
13080b57cec5SDimitry Andric bool ValueObject::DumpPrintableRepresentation(
13090b57cec5SDimitry Andric     Stream &s, ValueObjectRepresentationStyle val_obj_display,
13100b57cec5SDimitry Andric     Format custom_format, PrintableRepresentationSpecialCases special,
13110b57cec5SDimitry Andric     bool do_dump_error) {
13120b57cec5SDimitry Andric 
131306c3fb27SDimitry Andric   // If the ValueObject has an error, we might end up dumping the type, which
131406c3fb27SDimitry Andric   // is useful, but if we don't even have a type, then don't examine the object
131506c3fb27SDimitry Andric   // further as that's not meaningful, only the error is.
131606c3fb27SDimitry Andric   if (m_error.Fail() && !GetCompilerType().IsValid()) {
131706c3fb27SDimitry Andric     if (do_dump_error)
131806c3fb27SDimitry Andric       s.Printf("<%s>", m_error.AsCString());
131906c3fb27SDimitry Andric     return false;
132006c3fb27SDimitry Andric   }
132106c3fb27SDimitry Andric 
13220b57cec5SDimitry Andric   Flags flags(GetTypeInfo());
13230b57cec5SDimitry Andric 
13240b57cec5SDimitry Andric   bool allow_special =
13250b57cec5SDimitry Andric       (special == ValueObject::PrintableRepresentationSpecialCases::eAllow);
13260b57cec5SDimitry Andric   const bool only_special = false;
13270b57cec5SDimitry Andric 
13280b57cec5SDimitry Andric   if (allow_special) {
13290b57cec5SDimitry Andric     if (flags.AnySet(eTypeIsArray | eTypeIsPointer) &&
13300b57cec5SDimitry Andric         val_obj_display == ValueObject::eValueObjectRepresentationStyleValue) {
13310b57cec5SDimitry Andric       // when being asked to get a printable display an array or pointer type
13320b57cec5SDimitry Andric       // directly, try to "do the right thing"
13330b57cec5SDimitry Andric 
13340b57cec5SDimitry Andric       if (IsCStringContainer(true) &&
13350b57cec5SDimitry Andric           (custom_format == eFormatCString ||
13360b57cec5SDimitry Andric            custom_format == eFormatCharArray || custom_format == eFormatChar ||
13370b57cec5SDimitry Andric            custom_format ==
13380b57cec5SDimitry Andric                eFormatVectorOfChar)) // print char[] & char* directly
13390b57cec5SDimitry Andric       {
13400b57cec5SDimitry Andric         Status error;
134181ad6265SDimitry Andric         lldb::WritableDataBufferSP buffer_sp;
13427a6dacacSDimitry Andric         std::pair<size_t, bool> read_string =
13437a6dacacSDimitry Andric             ReadPointedString(buffer_sp, error,
13447a6dacacSDimitry Andric                               (custom_format == eFormatVectorOfChar) ||
13450b57cec5SDimitry Andric                                   (custom_format == eFormatCharArray));
13460b57cec5SDimitry Andric         lldb_private::formatters::StringPrinter::
13470b57cec5SDimitry Andric             ReadBufferAndDumpToStreamOptions options(*this);
13480b57cec5SDimitry Andric         options.SetData(DataExtractor(
13490b57cec5SDimitry Andric             buffer_sp, lldb::eByteOrderInvalid,
13500b57cec5SDimitry Andric             8)); // none of this matters for a string - pass some defaults
13510b57cec5SDimitry Andric         options.SetStream(&s);
13520b57cec5SDimitry Andric         options.SetPrefixToken(nullptr);
13530b57cec5SDimitry Andric         options.SetQuote('"');
13540b57cec5SDimitry Andric         options.SetSourceSize(buffer_sp->GetByteSize());
13550b57cec5SDimitry Andric         options.SetIsTruncated(read_string.second);
1356349cc55cSDimitry Andric         options.SetBinaryZeroIsTerminator(custom_format != eFormatVectorOfChar);
13570b57cec5SDimitry Andric         formatters::StringPrinter::ReadBufferAndDumpToStream<
13580b57cec5SDimitry Andric             lldb_private::formatters::StringPrinter::StringElementType::ASCII>(
13590b57cec5SDimitry Andric             options);
13600b57cec5SDimitry Andric         return !error.Fail();
13610b57cec5SDimitry Andric       }
13620b57cec5SDimitry Andric 
13630b57cec5SDimitry Andric       if (custom_format == eFormatEnum)
13640b57cec5SDimitry Andric         return false;
13650b57cec5SDimitry Andric 
13660b57cec5SDimitry Andric       // this only works for arrays, because I have no way to know when the
13670b57cec5SDimitry Andric       // pointed memory ends, and no special \0 end of data marker
13680b57cec5SDimitry Andric       if (flags.Test(eTypeIsArray)) {
13690b57cec5SDimitry Andric         if ((custom_format == eFormatBytes) ||
13700b57cec5SDimitry Andric             (custom_format == eFormatBytesWithASCII)) {
1371*0fca6ea1SDimitry Andric           const size_t count = GetNumChildrenIgnoringErrors();
13720b57cec5SDimitry Andric 
13730b57cec5SDimitry Andric           s << '[';
13740b57cec5SDimitry Andric           for (size_t low = 0; low < count; low++) {
13750b57cec5SDimitry Andric 
13760b57cec5SDimitry Andric             if (low)
13770b57cec5SDimitry Andric               s << ',';
13780b57cec5SDimitry Andric 
137906c3fb27SDimitry Andric             ValueObjectSP child = GetChildAtIndex(low);
13800b57cec5SDimitry Andric             if (!child.get()) {
13810b57cec5SDimitry Andric               s << "<invalid child>";
13820b57cec5SDimitry Andric               continue;
13830b57cec5SDimitry Andric             }
13840b57cec5SDimitry Andric             child->DumpPrintableRepresentation(
13850b57cec5SDimitry Andric                 s, ValueObject::eValueObjectRepresentationStyleValue,
13860b57cec5SDimitry Andric                 custom_format);
13870b57cec5SDimitry Andric           }
13880b57cec5SDimitry Andric 
13890b57cec5SDimitry Andric           s << ']';
13900b57cec5SDimitry Andric 
13910b57cec5SDimitry Andric           return true;
13920b57cec5SDimitry Andric         }
13930b57cec5SDimitry Andric 
13940b57cec5SDimitry Andric         if ((custom_format == eFormatVectorOfChar) ||
13950b57cec5SDimitry Andric             (custom_format == eFormatVectorOfFloat32) ||
13960b57cec5SDimitry Andric             (custom_format == eFormatVectorOfFloat64) ||
13970b57cec5SDimitry Andric             (custom_format == eFormatVectorOfSInt16) ||
13980b57cec5SDimitry Andric             (custom_format == eFormatVectorOfSInt32) ||
13990b57cec5SDimitry Andric             (custom_format == eFormatVectorOfSInt64) ||
14000b57cec5SDimitry Andric             (custom_format == eFormatVectorOfSInt8) ||
14010b57cec5SDimitry Andric             (custom_format == eFormatVectorOfUInt128) ||
14020b57cec5SDimitry Andric             (custom_format == eFormatVectorOfUInt16) ||
14030b57cec5SDimitry Andric             (custom_format == eFormatVectorOfUInt32) ||
14040b57cec5SDimitry Andric             (custom_format == eFormatVectorOfUInt64) ||
14050b57cec5SDimitry Andric             (custom_format == eFormatVectorOfUInt8)) // arrays of bytes, bytes
14060b57cec5SDimitry Andric                                                      // with ASCII or any vector
14070b57cec5SDimitry Andric                                                      // format should be printed
14080b57cec5SDimitry Andric                                                      // directly
14090b57cec5SDimitry Andric         {
1410*0fca6ea1SDimitry Andric           const size_t count = GetNumChildrenIgnoringErrors();
14110b57cec5SDimitry Andric 
14120b57cec5SDimitry Andric           Format format = FormatManager::GetSingleItemFormat(custom_format);
14130b57cec5SDimitry Andric 
14140b57cec5SDimitry Andric           s << '[';
14150b57cec5SDimitry Andric           for (size_t low = 0; low < count; low++) {
14160b57cec5SDimitry Andric 
14170b57cec5SDimitry Andric             if (low)
14180b57cec5SDimitry Andric               s << ',';
14190b57cec5SDimitry Andric 
142006c3fb27SDimitry Andric             ValueObjectSP child = GetChildAtIndex(low);
14210b57cec5SDimitry Andric             if (!child.get()) {
14220b57cec5SDimitry Andric               s << "<invalid child>";
14230b57cec5SDimitry Andric               continue;
14240b57cec5SDimitry Andric             }
14250b57cec5SDimitry Andric             child->DumpPrintableRepresentation(
14260b57cec5SDimitry Andric                 s, ValueObject::eValueObjectRepresentationStyleValue, format);
14270b57cec5SDimitry Andric           }
14280b57cec5SDimitry Andric 
14290b57cec5SDimitry Andric           s << ']';
14300b57cec5SDimitry Andric 
14310b57cec5SDimitry Andric           return true;
14320b57cec5SDimitry Andric         }
14330b57cec5SDimitry Andric       }
14340b57cec5SDimitry Andric 
14350b57cec5SDimitry Andric       if ((custom_format == eFormatBoolean) ||
14360b57cec5SDimitry Andric           (custom_format == eFormatBinary) || (custom_format == eFormatChar) ||
14370b57cec5SDimitry Andric           (custom_format == eFormatCharPrintable) ||
14380b57cec5SDimitry Andric           (custom_format == eFormatComplexFloat) ||
14390b57cec5SDimitry Andric           (custom_format == eFormatDecimal) || (custom_format == eFormatHex) ||
14400b57cec5SDimitry Andric           (custom_format == eFormatHexUppercase) ||
14410b57cec5SDimitry Andric           (custom_format == eFormatFloat) || (custom_format == eFormatOctal) ||
14420b57cec5SDimitry Andric           (custom_format == eFormatOSType) ||
14430b57cec5SDimitry Andric           (custom_format == eFormatUnicode16) ||
14440b57cec5SDimitry Andric           (custom_format == eFormatUnicode32) ||
14450b57cec5SDimitry Andric           (custom_format == eFormatUnsigned) ||
14460b57cec5SDimitry Andric           (custom_format == eFormatPointer) ||
14470b57cec5SDimitry Andric           (custom_format == eFormatComplexInteger) ||
14480b57cec5SDimitry Andric           (custom_format == eFormatComplex) ||
14490b57cec5SDimitry Andric           (custom_format == eFormatDefault)) // use the [] operator
14500b57cec5SDimitry Andric         return false;
14510b57cec5SDimitry Andric     }
14520b57cec5SDimitry Andric   }
14530b57cec5SDimitry Andric 
14540b57cec5SDimitry Andric   if (only_special)
14550b57cec5SDimitry Andric     return false;
14560b57cec5SDimitry Andric 
14570b57cec5SDimitry Andric   bool var_success = false;
14580b57cec5SDimitry Andric 
14590b57cec5SDimitry Andric   {
14600b57cec5SDimitry Andric     llvm::StringRef str;
14610b57cec5SDimitry Andric 
14620b57cec5SDimitry Andric     // this is a local stream that we are using to ensure that the data pointed
14630b57cec5SDimitry Andric     // to by cstr survives long enough for us to copy it to its destination -
14640b57cec5SDimitry Andric     // it is necessary to have this temporary storage area for cases where our
14650b57cec5SDimitry Andric     // desired output is not backed by some other longer-term storage
14660b57cec5SDimitry Andric     StreamString strm;
14670b57cec5SDimitry Andric 
14680b57cec5SDimitry Andric     if (custom_format != eFormatInvalid)
14690b57cec5SDimitry Andric       SetFormat(custom_format);
14700b57cec5SDimitry Andric 
14710b57cec5SDimitry Andric     switch (val_obj_display) {
14720b57cec5SDimitry Andric     case eValueObjectRepresentationStyleValue:
14730b57cec5SDimitry Andric       str = GetValueAsCString();
14740b57cec5SDimitry Andric       break;
14750b57cec5SDimitry Andric 
14760b57cec5SDimitry Andric     case eValueObjectRepresentationStyleSummary:
14770b57cec5SDimitry Andric       str = GetSummaryAsCString();
14780b57cec5SDimitry Andric       break;
14790b57cec5SDimitry Andric 
1480*0fca6ea1SDimitry Andric     case eValueObjectRepresentationStyleLanguageSpecific: {
1481*0fca6ea1SDimitry Andric       llvm::Expected<std::string> desc = GetObjectDescription();
1482*0fca6ea1SDimitry Andric       if (!desc) {
1483*0fca6ea1SDimitry Andric         strm << "error: " << toString(desc.takeError());
1484*0fca6ea1SDimitry Andric         str = strm.GetString();
1485*0fca6ea1SDimitry Andric       } else {
1486*0fca6ea1SDimitry Andric         strm << *desc;
1487*0fca6ea1SDimitry Andric         str = strm.GetString();
1488*0fca6ea1SDimitry Andric       }
1489*0fca6ea1SDimitry Andric     } break;
14900b57cec5SDimitry Andric 
14910b57cec5SDimitry Andric     case eValueObjectRepresentationStyleLocation:
14920b57cec5SDimitry Andric       str = GetLocationAsCString();
14930b57cec5SDimitry Andric       break;
14940b57cec5SDimitry Andric 
14950b57cec5SDimitry Andric     case eValueObjectRepresentationStyleChildrenCount:
1496*0fca6ea1SDimitry Andric       strm.Printf("%" PRIu64 "", (uint64_t)GetNumChildrenIgnoringErrors());
14970b57cec5SDimitry Andric       str = strm.GetString();
14980b57cec5SDimitry Andric       break;
14990b57cec5SDimitry Andric 
15000b57cec5SDimitry Andric     case eValueObjectRepresentationStyleType:
15010b57cec5SDimitry Andric       str = GetTypeName().GetStringRef();
15020b57cec5SDimitry Andric       break;
15030b57cec5SDimitry Andric 
15040b57cec5SDimitry Andric     case eValueObjectRepresentationStyleName:
15050b57cec5SDimitry Andric       str = GetName().GetStringRef();
15060b57cec5SDimitry Andric       break;
15070b57cec5SDimitry Andric 
15080b57cec5SDimitry Andric     case eValueObjectRepresentationStyleExpressionPath:
15095ffd83dbSDimitry Andric       GetExpressionPath(strm);
15100b57cec5SDimitry Andric       str = strm.GetString();
15110b57cec5SDimitry Andric       break;
15120b57cec5SDimitry Andric     }
15130b57cec5SDimitry Andric 
1514*0fca6ea1SDimitry Andric     // If the requested display style produced no output, try falling back to
1515*0fca6ea1SDimitry Andric     // alternative presentations.
15160b57cec5SDimitry Andric     if (str.empty()) {
15170b57cec5SDimitry Andric       if (val_obj_display == eValueObjectRepresentationStyleValue)
15180b57cec5SDimitry Andric         str = GetSummaryAsCString();
15190b57cec5SDimitry Andric       else if (val_obj_display == eValueObjectRepresentationStyleSummary) {
15200b57cec5SDimitry Andric         if (!CanProvideValue()) {
15210b57cec5SDimitry Andric           strm.Printf("%s @ %s", GetTypeName().AsCString(),
15220b57cec5SDimitry Andric                       GetLocationAsCString());
15230b57cec5SDimitry Andric           str = strm.GetString();
15240b57cec5SDimitry Andric         } else
15250b57cec5SDimitry Andric           str = GetValueAsCString();
15260b57cec5SDimitry Andric       }
15270b57cec5SDimitry Andric     }
15280b57cec5SDimitry Andric 
15290b57cec5SDimitry Andric     if (!str.empty())
15300b57cec5SDimitry Andric       s << str;
15310b57cec5SDimitry Andric     else {
153206c3fb27SDimitry Andric       // We checked for errors at the start, but do it again here in case
153306c3fb27SDimitry Andric       // realizing the value for dumping produced an error.
15340b57cec5SDimitry Andric       if (m_error.Fail()) {
15350b57cec5SDimitry Andric         if (do_dump_error)
15360b57cec5SDimitry Andric           s.Printf("<%s>", m_error.AsCString());
15370b57cec5SDimitry Andric         else
15380b57cec5SDimitry Andric           return false;
15390b57cec5SDimitry Andric       } else if (val_obj_display == eValueObjectRepresentationStyleSummary)
15400b57cec5SDimitry Andric         s.PutCString("<no summary available>");
15410b57cec5SDimitry Andric       else if (val_obj_display == eValueObjectRepresentationStyleValue)
15420b57cec5SDimitry Andric         s.PutCString("<no value available>");
15430b57cec5SDimitry Andric       else if (val_obj_display ==
15440b57cec5SDimitry Andric                eValueObjectRepresentationStyleLanguageSpecific)
15450b57cec5SDimitry Andric         s.PutCString("<not a valid Objective-C object>"); // edit this if we
15460b57cec5SDimitry Andric                                                           // have other runtimes
15470b57cec5SDimitry Andric                                                           // that support a
15480b57cec5SDimitry Andric                                                           // description
15490b57cec5SDimitry Andric       else
15500b57cec5SDimitry Andric         s.PutCString("<no printable representation>");
15510b57cec5SDimitry Andric     }
15520b57cec5SDimitry Andric 
15530b57cec5SDimitry Andric     // we should only return false here if we could not do *anything* even if
15540b57cec5SDimitry Andric     // we have an error message as output, that's a success from our callers'
15550b57cec5SDimitry Andric     // perspective, so return true
15560b57cec5SDimitry Andric     var_success = true;
15570b57cec5SDimitry Andric 
15580b57cec5SDimitry Andric     if (custom_format != eFormatInvalid)
15590b57cec5SDimitry Andric       SetFormat(eFormatDefault);
15600b57cec5SDimitry Andric   }
15610b57cec5SDimitry Andric 
15620b57cec5SDimitry Andric   return var_success;
15630b57cec5SDimitry Andric }
15640b57cec5SDimitry Andric 
15650b57cec5SDimitry Andric addr_t ValueObject::GetAddressOf(bool scalar_is_load_address,
15660b57cec5SDimitry Andric                                  AddressType *address_type) {
15670b57cec5SDimitry Andric   // Can't take address of a bitfield
15680b57cec5SDimitry Andric   if (IsBitfield())
15690b57cec5SDimitry Andric     return LLDB_INVALID_ADDRESS;
15700b57cec5SDimitry Andric 
15710b57cec5SDimitry Andric   if (!UpdateValueIfNeeded(false))
15720b57cec5SDimitry Andric     return LLDB_INVALID_ADDRESS;
15730b57cec5SDimitry Andric 
15740b57cec5SDimitry Andric   switch (m_value.GetValueType()) {
1575fe6060f1SDimitry Andric   case Value::ValueType::Invalid:
1576fe6060f1SDimitry Andric     return LLDB_INVALID_ADDRESS;
1577fe6060f1SDimitry Andric   case Value::ValueType::Scalar:
15780b57cec5SDimitry Andric     if (scalar_is_load_address) {
15790b57cec5SDimitry Andric       if (address_type)
15800b57cec5SDimitry Andric         *address_type = eAddressTypeLoad;
15810b57cec5SDimitry Andric       return m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
15820b57cec5SDimitry Andric     }
15830b57cec5SDimitry Andric     break;
15840b57cec5SDimitry Andric 
1585fe6060f1SDimitry Andric   case Value::ValueType::LoadAddress:
1586fe6060f1SDimitry Andric   case Value::ValueType::FileAddress: {
15870b57cec5SDimitry Andric     if (address_type)
15880b57cec5SDimitry Andric       *address_type = m_value.GetValueAddressType();
15890b57cec5SDimitry Andric     return m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
15900b57cec5SDimitry Andric   } break;
1591fe6060f1SDimitry Andric   case Value::ValueType::HostAddress: {
15920b57cec5SDimitry Andric     if (address_type)
15930b57cec5SDimitry Andric       *address_type = m_value.GetValueAddressType();
15940b57cec5SDimitry Andric     return LLDB_INVALID_ADDRESS;
15950b57cec5SDimitry Andric   } break;
15960b57cec5SDimitry Andric   }
15970b57cec5SDimitry Andric   if (address_type)
15980b57cec5SDimitry Andric     *address_type = eAddressTypeInvalid;
15990b57cec5SDimitry Andric   return LLDB_INVALID_ADDRESS;
16000b57cec5SDimitry Andric }
16010b57cec5SDimitry Andric 
16020b57cec5SDimitry Andric addr_t ValueObject::GetPointerValue(AddressType *address_type) {
16030b57cec5SDimitry Andric   addr_t address = LLDB_INVALID_ADDRESS;
16040b57cec5SDimitry Andric   if (address_type)
16050b57cec5SDimitry Andric     *address_type = eAddressTypeInvalid;
16060b57cec5SDimitry Andric 
16070b57cec5SDimitry Andric   if (!UpdateValueIfNeeded(false))
16080b57cec5SDimitry Andric     return address;
16090b57cec5SDimitry Andric 
16100b57cec5SDimitry Andric   switch (m_value.GetValueType()) {
1611fe6060f1SDimitry Andric   case Value::ValueType::Invalid:
1612fe6060f1SDimitry Andric     return LLDB_INVALID_ADDRESS;
1613fe6060f1SDimitry Andric   case Value::ValueType::Scalar:
16140b57cec5SDimitry Andric     address = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
16150b57cec5SDimitry Andric     break;
16160b57cec5SDimitry Andric 
1617fe6060f1SDimitry Andric   case Value::ValueType::HostAddress:
1618fe6060f1SDimitry Andric   case Value::ValueType::LoadAddress:
1619fe6060f1SDimitry Andric   case Value::ValueType::FileAddress: {
16200b57cec5SDimitry Andric     lldb::offset_t data_offset = 0;
16215ffd83dbSDimitry Andric     address = m_data.GetAddress(&data_offset);
16220b57cec5SDimitry Andric   } break;
16230b57cec5SDimitry Andric   }
16240b57cec5SDimitry Andric 
16250b57cec5SDimitry Andric   if (address_type)
16260b57cec5SDimitry Andric     *address_type = GetAddressTypeOfChildren();
16270b57cec5SDimitry Andric 
16280b57cec5SDimitry Andric   return address;
16290b57cec5SDimitry Andric }
16300b57cec5SDimitry Andric 
16310b57cec5SDimitry Andric bool ValueObject::SetValueFromCString(const char *value_str, Status &error) {
16320b57cec5SDimitry Andric   error.Clear();
16330b57cec5SDimitry Andric   // Make sure our value is up to date first so that our location and location
16340b57cec5SDimitry Andric   // type is valid.
16350b57cec5SDimitry Andric   if (!UpdateValueIfNeeded(false)) {
16360b57cec5SDimitry Andric     error.SetErrorString("unable to read value");
16370b57cec5SDimitry Andric     return false;
16380b57cec5SDimitry Andric   }
16390b57cec5SDimitry Andric 
16400b57cec5SDimitry Andric   uint64_t count = 0;
16410b57cec5SDimitry Andric   const Encoding encoding = GetCompilerType().GetEncoding(count);
16420b57cec5SDimitry Andric 
164381ad6265SDimitry Andric   const size_t byte_size = GetByteSize().value_or(0);
16440b57cec5SDimitry Andric 
16450b57cec5SDimitry Andric   Value::ValueType value_type = m_value.GetValueType();
16460b57cec5SDimitry Andric 
1647fe6060f1SDimitry Andric   if (value_type == Value::ValueType::Scalar) {
16480b57cec5SDimitry Andric     // If the value is already a scalar, then let the scalar change itself:
16490b57cec5SDimitry Andric     m_value.GetScalar().SetValueFromCString(value_str, encoding, byte_size);
16500b57cec5SDimitry Andric   } else if (byte_size <= 16) {
16510b57cec5SDimitry Andric     // If the value fits in a scalar, then make a new scalar and again let the
16520b57cec5SDimitry Andric     // scalar code do the conversion, then figure out where to put the new
16530b57cec5SDimitry Andric     // value.
16540b57cec5SDimitry Andric     Scalar new_scalar;
16550b57cec5SDimitry Andric     error = new_scalar.SetValueFromCString(value_str, encoding, byte_size);
16560b57cec5SDimitry Andric     if (error.Success()) {
16570b57cec5SDimitry Andric       switch (value_type) {
1658fe6060f1SDimitry Andric       case Value::ValueType::LoadAddress: {
16590b57cec5SDimitry Andric         // If it is a load address, then the scalar value is the storage
16600b57cec5SDimitry Andric         // location of the data, and we have to shove this value down to that
16610b57cec5SDimitry Andric         // load location.
16620b57cec5SDimitry Andric         ExecutionContext exe_ctx(GetExecutionContextRef());
16630b57cec5SDimitry Andric         Process *process = exe_ctx.GetProcessPtr();
16640b57cec5SDimitry Andric         if (process) {
16650b57cec5SDimitry Andric           addr_t target_addr =
16660b57cec5SDimitry Andric               m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
16670b57cec5SDimitry Andric           size_t bytes_written = process->WriteScalarToMemory(
16680b57cec5SDimitry Andric               target_addr, new_scalar, byte_size, error);
16690b57cec5SDimitry Andric           if (!error.Success())
16700b57cec5SDimitry Andric             return false;
16710b57cec5SDimitry Andric           if (bytes_written != byte_size) {
16720b57cec5SDimitry Andric             error.SetErrorString("unable to write value to memory");
16730b57cec5SDimitry Andric             return false;
16740b57cec5SDimitry Andric           }
16750b57cec5SDimitry Andric         }
16760b57cec5SDimitry Andric       } break;
1677fe6060f1SDimitry Andric       case Value::ValueType::HostAddress: {
16780b57cec5SDimitry Andric         // If it is a host address, then we stuff the scalar as a DataBuffer
16790b57cec5SDimitry Andric         // into the Value's data.
16800b57cec5SDimitry Andric         DataExtractor new_data;
16810b57cec5SDimitry Andric         new_data.SetByteOrder(m_data.GetByteOrder());
16820b57cec5SDimitry Andric 
16830b57cec5SDimitry Andric         DataBufferSP buffer_sp(new DataBufferHeap(byte_size, 0));
16840b57cec5SDimitry Andric         m_data.SetData(buffer_sp, 0);
16850b57cec5SDimitry Andric         bool success = new_scalar.GetData(new_data);
16860b57cec5SDimitry Andric         if (success) {
16870b57cec5SDimitry Andric           new_data.CopyByteOrderedData(
16880b57cec5SDimitry Andric               0, byte_size, const_cast<uint8_t *>(m_data.GetDataStart()),
16890b57cec5SDimitry Andric               byte_size, m_data.GetByteOrder());
16900b57cec5SDimitry Andric         }
16910b57cec5SDimitry Andric         m_value.GetScalar() = (uintptr_t)m_data.GetDataStart();
16920b57cec5SDimitry Andric 
16930b57cec5SDimitry Andric       } break;
1694fe6060f1SDimitry Andric       case Value::ValueType::Invalid:
1695fe6060f1SDimitry Andric         error.SetErrorString("invalid location");
1696fe6060f1SDimitry Andric         return false;
1697fe6060f1SDimitry Andric       case Value::ValueType::FileAddress:
1698fe6060f1SDimitry Andric       case Value::ValueType::Scalar:
16990b57cec5SDimitry Andric         break;
17000b57cec5SDimitry Andric       }
17010b57cec5SDimitry Andric     } else {
17020b57cec5SDimitry Andric       return false;
17030b57cec5SDimitry Andric     }
17040b57cec5SDimitry Andric   } else {
17050b57cec5SDimitry Andric     // We don't support setting things bigger than a scalar at present.
17060b57cec5SDimitry Andric     error.SetErrorString("unable to write aggregate data type");
17070b57cec5SDimitry Andric     return false;
17080b57cec5SDimitry Andric   }
17090b57cec5SDimitry Andric 
17100b57cec5SDimitry Andric   // If we have reached this point, then we have successfully changed the
17110b57cec5SDimitry Andric   // value.
17120b57cec5SDimitry Andric   SetNeedsUpdate();
17130b57cec5SDimitry Andric   return true;
17140b57cec5SDimitry Andric }
17150b57cec5SDimitry Andric 
17160b57cec5SDimitry Andric bool ValueObject::GetDeclaration(Declaration &decl) {
17170b57cec5SDimitry Andric   decl.Clear();
17180b57cec5SDimitry Andric   return false;
17190b57cec5SDimitry Andric }
17200b57cec5SDimitry Andric 
17210b57cec5SDimitry Andric void ValueObject::AddSyntheticChild(ConstString key,
17220b57cec5SDimitry Andric                                     ValueObject *valobj) {
17230b57cec5SDimitry Andric   m_synthetic_children[key] = valobj;
17240b57cec5SDimitry Andric }
17250b57cec5SDimitry Andric 
17260b57cec5SDimitry Andric ValueObjectSP ValueObject::GetSyntheticChild(ConstString key) const {
17270b57cec5SDimitry Andric   ValueObjectSP synthetic_child_sp;
17280b57cec5SDimitry Andric   std::map<ConstString, ValueObject *>::const_iterator pos =
17290b57cec5SDimitry Andric       m_synthetic_children.find(key);
17300b57cec5SDimitry Andric   if (pos != m_synthetic_children.end())
17310b57cec5SDimitry Andric     synthetic_child_sp = pos->second->GetSP();
17320b57cec5SDimitry Andric   return synthetic_child_sp;
17330b57cec5SDimitry Andric }
17340b57cec5SDimitry Andric 
17350b57cec5SDimitry Andric bool ValueObject::IsPossibleDynamicType() {
17360b57cec5SDimitry Andric   ExecutionContext exe_ctx(GetExecutionContextRef());
17370b57cec5SDimitry Andric   Process *process = exe_ctx.GetProcessPtr();
17380b57cec5SDimitry Andric   if (process)
17390b57cec5SDimitry Andric     return process->IsPossibleDynamicValue(*this);
17400b57cec5SDimitry Andric   else
17410b57cec5SDimitry Andric     return GetCompilerType().IsPossibleDynamicType(nullptr, true, true);
17420b57cec5SDimitry Andric }
17430b57cec5SDimitry Andric 
17440b57cec5SDimitry Andric bool ValueObject::IsRuntimeSupportValue() {
17450b57cec5SDimitry Andric   Process *process(GetProcessSP().get());
17460b57cec5SDimitry Andric   if (!process)
17470b57cec5SDimitry Andric     return false;
17480b57cec5SDimitry Andric 
1749fe6060f1SDimitry Andric   // We trust that the compiler did the right thing and marked runtime support
17500b57cec5SDimitry Andric   // values as artificial.
17510b57cec5SDimitry Andric   if (!GetVariable() || !GetVariable()->IsArtificial())
17520b57cec5SDimitry Andric     return false;
17530b57cec5SDimitry Andric 
17549dba64beSDimitry Andric   if (auto *runtime = process->GetLanguageRuntime(GetVariable()->GetLanguage()))
17555ffd83dbSDimitry Andric     if (runtime->IsAllowedRuntimeValue(GetName()))
17560b57cec5SDimitry Andric       return false;
17570b57cec5SDimitry Andric 
17580b57cec5SDimitry Andric   return true;
17590b57cec5SDimitry Andric }
17600b57cec5SDimitry Andric 
17610b57cec5SDimitry Andric bool ValueObject::IsNilReference() {
17620b57cec5SDimitry Andric   if (Language *language = Language::FindPlugin(GetObjectRuntimeLanguage())) {
17630b57cec5SDimitry Andric     return language->IsNilReference(*this);
17640b57cec5SDimitry Andric   }
17650b57cec5SDimitry Andric   return false;
17660b57cec5SDimitry Andric }
17670b57cec5SDimitry Andric 
17680b57cec5SDimitry Andric bool ValueObject::IsUninitializedReference() {
17690b57cec5SDimitry Andric   if (Language *language = Language::FindPlugin(GetObjectRuntimeLanguage())) {
17700b57cec5SDimitry Andric     return language->IsUninitializedReference(*this);
17710b57cec5SDimitry Andric   }
17720b57cec5SDimitry Andric   return false;
17730b57cec5SDimitry Andric }
17740b57cec5SDimitry Andric 
17750b57cec5SDimitry Andric // This allows you to create an array member using and index that doesn't not
17760b57cec5SDimitry Andric // fall in the normal bounds of the array. Many times structure can be defined
17770b57cec5SDimitry Andric // as: struct Collection {
17780b57cec5SDimitry Andric //     uint32_t item_count;
17790b57cec5SDimitry Andric //     Item item_array[0];
17800b57cec5SDimitry Andric // };
17810b57cec5SDimitry Andric // The size of the "item_array" is 1, but many times in practice there are more
17820b57cec5SDimitry Andric // items in "item_array".
17830b57cec5SDimitry Andric 
17840b57cec5SDimitry Andric ValueObjectSP ValueObject::GetSyntheticArrayMember(size_t index,
17850b57cec5SDimitry Andric                                                    bool can_create) {
1786*0fca6ea1SDimitry Andric   ValueObjectSP synthetic_child_sp;
1787*0fca6ea1SDimitry Andric   if (IsPointerType() || IsArrayType()) {
1788e8d8bef9SDimitry Andric     std::string index_str = llvm::formatv("[{0}]", index);
17890b57cec5SDimitry Andric     ConstString index_const_str(index_str);
17900b57cec5SDimitry Andric     // Check if we have already created a synthetic array member in this valid
17910b57cec5SDimitry Andric     // object. If we have we will re-use it.
1792*0fca6ea1SDimitry Andric     synthetic_child_sp = GetSyntheticChild(index_const_str);
1793*0fca6ea1SDimitry Andric     if (!synthetic_child_sp) {
1794*0fca6ea1SDimitry Andric       ValueObject *synthetic_child;
17950b57cec5SDimitry Andric       // We haven't made a synthetic array member for INDEX yet, so lets make
17960b57cec5SDimitry Andric       // one and cache it for any future reference.
1797*0fca6ea1SDimitry Andric       synthetic_child = CreateSyntheticArrayMember(index);
17980b57cec5SDimitry Andric 
1799*0fca6ea1SDimitry Andric       // Cache the value if we got one back...
1800*0fca6ea1SDimitry Andric       if (synthetic_child) {
18010b57cec5SDimitry Andric         AddSyntheticChild(index_const_str, synthetic_child);
1802*0fca6ea1SDimitry Andric         synthetic_child_sp = synthetic_child->GetSP();
18030b57cec5SDimitry Andric         synthetic_child_sp->SetName(ConstString(index_str));
1804fe6060f1SDimitry Andric         synthetic_child_sp->m_flags.m_is_array_item_for_pointer = true;
1805*0fca6ea1SDimitry Andric       }
1806*0fca6ea1SDimitry Andric     }
1807*0fca6ea1SDimitry Andric   }
18080b57cec5SDimitry Andric   return synthetic_child_sp;
18090b57cec5SDimitry Andric }
18100b57cec5SDimitry Andric 
18110b57cec5SDimitry Andric ValueObjectSP ValueObject::GetSyntheticBitFieldChild(uint32_t from, uint32_t to,
18120b57cec5SDimitry Andric                                                      bool can_create) {
1813*0fca6ea1SDimitry Andric   ValueObjectSP synthetic_child_sp;
1814*0fca6ea1SDimitry Andric   if (IsScalarType()) {
1815e8d8bef9SDimitry Andric     std::string index_str = llvm::formatv("[{0}-{1}]", from, to);
18160b57cec5SDimitry Andric     ConstString index_const_str(index_str);
18170b57cec5SDimitry Andric     // Check if we have already created a synthetic array member in this valid
18180b57cec5SDimitry Andric     // object. If we have we will re-use it.
1819*0fca6ea1SDimitry Andric     synthetic_child_sp = GetSyntheticChild(index_const_str);
1820*0fca6ea1SDimitry Andric     if (!synthetic_child_sp) {
18210b57cec5SDimitry Andric       uint32_t bit_field_size = to - from + 1;
18220b57cec5SDimitry Andric       uint32_t bit_field_offset = from;
18230b57cec5SDimitry Andric       if (GetDataExtractor().GetByteOrder() == eByteOrderBig)
18240b57cec5SDimitry Andric         bit_field_offset =
182581ad6265SDimitry Andric             GetByteSize().value_or(0) * 8 - bit_field_size - bit_field_offset;
18260b57cec5SDimitry Andric       // We haven't made a synthetic array member for INDEX yet, so lets make
18270b57cec5SDimitry Andric       // one and cache it for any future reference.
18280b57cec5SDimitry Andric       ValueObjectChild *synthetic_child = new ValueObjectChild(
1829*0fca6ea1SDimitry Andric           *this, GetCompilerType(), index_const_str, GetByteSize().value_or(0),
1830*0fca6ea1SDimitry Andric           0, bit_field_size, bit_field_offset, false, false,
1831*0fca6ea1SDimitry Andric           eAddressTypeInvalid, 0);
18320b57cec5SDimitry Andric 
1833*0fca6ea1SDimitry Andric       // Cache the value if we got one back...
1834*0fca6ea1SDimitry Andric       if (synthetic_child) {
18350b57cec5SDimitry Andric         AddSyntheticChild(index_const_str, synthetic_child);
1836*0fca6ea1SDimitry Andric         synthetic_child_sp = synthetic_child->GetSP();
18370b57cec5SDimitry Andric         synthetic_child_sp->SetName(ConstString(index_str));
1838fe6060f1SDimitry Andric         synthetic_child_sp->m_flags.m_is_bitfield_for_scalar = true;
1839*0fca6ea1SDimitry Andric       }
1840*0fca6ea1SDimitry Andric     }
1841*0fca6ea1SDimitry Andric   }
18420b57cec5SDimitry Andric   return synthetic_child_sp;
18430b57cec5SDimitry Andric }
18440b57cec5SDimitry Andric 
18450b57cec5SDimitry Andric ValueObjectSP ValueObject::GetSyntheticChildAtOffset(
18460b57cec5SDimitry Andric     uint32_t offset, const CompilerType &type, bool can_create,
18470b57cec5SDimitry Andric     ConstString name_const_str) {
18480b57cec5SDimitry Andric 
18490b57cec5SDimitry Andric   ValueObjectSP synthetic_child_sp;
18500b57cec5SDimitry Andric 
1851*0fca6ea1SDimitry Andric   if (name_const_str.IsEmpty()) {
1852e8d8bef9SDimitry Andric     name_const_str.SetString("@" + std::to_string(offset));
1853*0fca6ea1SDimitry Andric   }
18540b57cec5SDimitry Andric 
18550b57cec5SDimitry Andric   // Check if we have already created a synthetic array member in this valid
18560b57cec5SDimitry Andric   // object. If we have we will re-use it.
18570b57cec5SDimitry Andric   synthetic_child_sp = GetSyntheticChild(name_const_str);
18580b57cec5SDimitry Andric 
18590b57cec5SDimitry Andric   if (synthetic_child_sp.get())
18600b57cec5SDimitry Andric     return synthetic_child_sp;
18610b57cec5SDimitry Andric 
18620b57cec5SDimitry Andric   if (!can_create)
1863*0fca6ea1SDimitry Andric     return {};
18640b57cec5SDimitry Andric 
18650b57cec5SDimitry Andric   ExecutionContext exe_ctx(GetExecutionContextRef());
1866bdd1243dSDimitry Andric   std::optional<uint64_t> size =
18670b57cec5SDimitry Andric       type.GetByteSize(exe_ctx.GetBestExecutionContextScope());
18680b57cec5SDimitry Andric   if (!size)
1869*0fca6ea1SDimitry Andric     return {};
18700b57cec5SDimitry Andric   ValueObjectChild *synthetic_child =
18710b57cec5SDimitry Andric       new ValueObjectChild(*this, type, name_const_str, *size, offset, 0, 0,
18720b57cec5SDimitry Andric                            false, false, eAddressTypeInvalid, 0);
18730b57cec5SDimitry Andric   if (synthetic_child) {
18740b57cec5SDimitry Andric     AddSyntheticChild(name_const_str, synthetic_child);
18750b57cec5SDimitry Andric     synthetic_child_sp = synthetic_child->GetSP();
18760b57cec5SDimitry Andric     synthetic_child_sp->SetName(name_const_str);
1877fe6060f1SDimitry Andric     synthetic_child_sp->m_flags.m_is_child_at_offset = true;
18780b57cec5SDimitry Andric   }
18790b57cec5SDimitry Andric   return synthetic_child_sp;
18800b57cec5SDimitry Andric }
18810b57cec5SDimitry Andric 
18820b57cec5SDimitry Andric ValueObjectSP ValueObject::GetSyntheticBase(uint32_t offset,
18830b57cec5SDimitry Andric                                             const CompilerType &type,
18840b57cec5SDimitry Andric                                             bool can_create,
18850b57cec5SDimitry Andric                                             ConstString name_const_str) {
18860b57cec5SDimitry Andric   ValueObjectSP synthetic_child_sp;
18870b57cec5SDimitry Andric 
18880b57cec5SDimitry Andric   if (name_const_str.IsEmpty()) {
18890b57cec5SDimitry Andric     char name_str[128];
18900b57cec5SDimitry Andric     snprintf(name_str, sizeof(name_str), "base%s@%i",
18910b57cec5SDimitry Andric              type.GetTypeName().AsCString("<unknown>"), offset);
18920b57cec5SDimitry Andric     name_const_str.SetCString(name_str);
18930b57cec5SDimitry Andric   }
18940b57cec5SDimitry Andric 
18950b57cec5SDimitry Andric   // Check if we have already created a synthetic array member in this valid
18960b57cec5SDimitry Andric   // object. If we have we will re-use it.
18970b57cec5SDimitry Andric   synthetic_child_sp = GetSyntheticChild(name_const_str);
18980b57cec5SDimitry Andric 
18990b57cec5SDimitry Andric   if (synthetic_child_sp.get())
19000b57cec5SDimitry Andric     return synthetic_child_sp;
19010b57cec5SDimitry Andric 
19020b57cec5SDimitry Andric   if (!can_create)
1903*0fca6ea1SDimitry Andric     return {};
19040b57cec5SDimitry Andric 
19050b57cec5SDimitry Andric   const bool is_base_class = true;
19060b57cec5SDimitry Andric 
19070b57cec5SDimitry Andric   ExecutionContext exe_ctx(GetExecutionContextRef());
1908bdd1243dSDimitry Andric   std::optional<uint64_t> size =
19090b57cec5SDimitry Andric       type.GetByteSize(exe_ctx.GetBestExecutionContextScope());
19100b57cec5SDimitry Andric   if (!size)
1911*0fca6ea1SDimitry Andric     return {};
19120b57cec5SDimitry Andric   ValueObjectChild *synthetic_child =
19130b57cec5SDimitry Andric       new ValueObjectChild(*this, type, name_const_str, *size, offset, 0, 0,
19140b57cec5SDimitry Andric                            is_base_class, false, eAddressTypeInvalid, 0);
19150b57cec5SDimitry Andric   if (synthetic_child) {
19160b57cec5SDimitry Andric     AddSyntheticChild(name_const_str, synthetic_child);
19170b57cec5SDimitry Andric     synthetic_child_sp = synthetic_child->GetSP();
19180b57cec5SDimitry Andric     synthetic_child_sp->SetName(name_const_str);
19190b57cec5SDimitry Andric   }
19200b57cec5SDimitry Andric   return synthetic_child_sp;
19210b57cec5SDimitry Andric }
19220b57cec5SDimitry Andric 
19230b57cec5SDimitry Andric // your expression path needs to have a leading . or -> (unless it somehow
19240b57cec5SDimitry Andric // "looks like" an array, in which case it has a leading [ symbol). while the [
19250b57cec5SDimitry Andric // is meaningful and should be shown to the user, . and -> are just parser
19260b57cec5SDimitry Andric // design, but by no means added information for the user.. strip them off
19270b57cec5SDimitry Andric static const char *SkipLeadingExpressionPathSeparators(const char *expression) {
19280b57cec5SDimitry Andric   if (!expression || !expression[0])
19290b57cec5SDimitry Andric     return expression;
19300b57cec5SDimitry Andric   if (expression[0] == '.')
19310b57cec5SDimitry Andric     return expression + 1;
19320b57cec5SDimitry Andric   if (expression[0] == '-' && expression[1] == '>')
19330b57cec5SDimitry Andric     return expression + 2;
19340b57cec5SDimitry Andric   return expression;
19350b57cec5SDimitry Andric }
19360b57cec5SDimitry Andric 
19370b57cec5SDimitry Andric ValueObjectSP
19380b57cec5SDimitry Andric ValueObject::GetSyntheticExpressionPathChild(const char *expression,
19390b57cec5SDimitry Andric                                              bool can_create) {
1940*0fca6ea1SDimitry Andric   ValueObjectSP synthetic_child_sp;
19410b57cec5SDimitry Andric   ConstString name_const_string(expression);
19420b57cec5SDimitry Andric   // Check if we have already created a synthetic array member in this valid
19430b57cec5SDimitry Andric   // object. If we have we will re-use it.
1944*0fca6ea1SDimitry Andric   synthetic_child_sp = GetSyntheticChild(name_const_string);
1945*0fca6ea1SDimitry Andric   if (!synthetic_child_sp) {
19460b57cec5SDimitry Andric     // We haven't made a synthetic array member for expression yet, so lets
19470b57cec5SDimitry Andric     // make one and cache it for any future reference.
1948*0fca6ea1SDimitry Andric     synthetic_child_sp = GetValueForExpressionPath(
1949*0fca6ea1SDimitry Andric         expression, nullptr, nullptr,
1950*0fca6ea1SDimitry Andric         GetValueForExpressionPathOptions().SetSyntheticChildrenTraversal(
1951*0fca6ea1SDimitry Andric             GetValueForExpressionPathOptions::SyntheticChildrenTraversal::
1952*0fca6ea1SDimitry Andric                 None));
19530b57cec5SDimitry Andric 
1954*0fca6ea1SDimitry Andric     // Cache the value if we got one back...
1955*0fca6ea1SDimitry Andric     if (synthetic_child_sp.get()) {
19560b57cec5SDimitry Andric       // FIXME: this causes a "real" child to end up with its name changed to
19570b57cec5SDimitry Andric       // the contents of expression
1958*0fca6ea1SDimitry Andric       AddSyntheticChild(name_const_string, synthetic_child_sp.get());
1959*0fca6ea1SDimitry Andric       synthetic_child_sp->SetName(
19600b57cec5SDimitry Andric           ConstString(SkipLeadingExpressionPathSeparators(expression)));
1961*0fca6ea1SDimitry Andric     }
1962*0fca6ea1SDimitry Andric   }
1963*0fca6ea1SDimitry Andric   return synthetic_child_sp;
19640b57cec5SDimitry Andric }
19650b57cec5SDimitry Andric 
19665ffd83dbSDimitry Andric void ValueObject::CalculateSyntheticValue() {
19670b57cec5SDimitry Andric   TargetSP target_sp(GetTargetSP());
19680b57cec5SDimitry Andric   if (target_sp && !target_sp->GetEnableSyntheticValue()) {
19690b57cec5SDimitry Andric     m_synthetic_value = nullptr;
19700b57cec5SDimitry Andric     return;
19710b57cec5SDimitry Andric   }
19720b57cec5SDimitry Andric 
19730b57cec5SDimitry Andric   lldb::SyntheticChildrenSP current_synth_sp(m_synthetic_children_sp);
19740b57cec5SDimitry Andric 
19750b57cec5SDimitry Andric   if (!UpdateFormatsIfNeeded() && m_synthetic_value)
19760b57cec5SDimitry Andric     return;
19770b57cec5SDimitry Andric 
19780b57cec5SDimitry Andric   if (m_synthetic_children_sp.get() == nullptr)
19790b57cec5SDimitry Andric     return;
19800b57cec5SDimitry Andric 
19810b57cec5SDimitry Andric   if (current_synth_sp == m_synthetic_children_sp && m_synthetic_value)
19820b57cec5SDimitry Andric     return;
19830b57cec5SDimitry Andric 
19840b57cec5SDimitry Andric   m_synthetic_value = new ValueObjectSynthetic(*this, m_synthetic_children_sp);
19850b57cec5SDimitry Andric }
19860b57cec5SDimitry Andric 
19870b57cec5SDimitry Andric void ValueObject::CalculateDynamicValue(DynamicValueType use_dynamic) {
19880b57cec5SDimitry Andric   if (use_dynamic == eNoDynamicValues)
19890b57cec5SDimitry Andric     return;
19900b57cec5SDimitry Andric 
19910b57cec5SDimitry Andric   if (!m_dynamic_value && !IsDynamic()) {
19920b57cec5SDimitry Andric     ExecutionContext exe_ctx(GetExecutionContextRef());
19930b57cec5SDimitry Andric     Process *process = exe_ctx.GetProcessPtr();
19940b57cec5SDimitry Andric     if (process && process->IsPossibleDynamicValue(*this)) {
19950b57cec5SDimitry Andric       ClearDynamicTypeInformation();
19960b57cec5SDimitry Andric       m_dynamic_value = new ValueObjectDynamicValue(*this, use_dynamic);
19970b57cec5SDimitry Andric     }
19980b57cec5SDimitry Andric   }
19990b57cec5SDimitry Andric }
20000b57cec5SDimitry Andric 
20010b57cec5SDimitry Andric ValueObjectSP ValueObject::GetDynamicValue(DynamicValueType use_dynamic) {
20020b57cec5SDimitry Andric   if (use_dynamic == eNoDynamicValues)
20030b57cec5SDimitry Andric     return ValueObjectSP();
20040b57cec5SDimitry Andric 
20050b57cec5SDimitry Andric   if (!IsDynamic() && m_dynamic_value == nullptr) {
20060b57cec5SDimitry Andric     CalculateDynamicValue(use_dynamic);
20070b57cec5SDimitry Andric   }
200806c3fb27SDimitry Andric   if (m_dynamic_value && m_dynamic_value->GetError().Success())
20090b57cec5SDimitry Andric     return m_dynamic_value->GetSP();
20100b57cec5SDimitry Andric   else
20110b57cec5SDimitry Andric     return ValueObjectSP();
20120b57cec5SDimitry Andric }
20130b57cec5SDimitry Andric 
20145ffd83dbSDimitry Andric ValueObjectSP ValueObject::GetSyntheticValue() {
20155ffd83dbSDimitry Andric   CalculateSyntheticValue();
20160b57cec5SDimitry Andric 
20170b57cec5SDimitry Andric   if (m_synthetic_value)
20180b57cec5SDimitry Andric     return m_synthetic_value->GetSP();
20190b57cec5SDimitry Andric   else
20200b57cec5SDimitry Andric     return ValueObjectSP();
20210b57cec5SDimitry Andric }
20220b57cec5SDimitry Andric 
20230b57cec5SDimitry Andric bool ValueObject::HasSyntheticValue() {
20240b57cec5SDimitry Andric   UpdateFormatsIfNeeded();
20250b57cec5SDimitry Andric 
20260b57cec5SDimitry Andric   if (m_synthetic_children_sp.get() == nullptr)
20270b57cec5SDimitry Andric     return false;
20280b57cec5SDimitry Andric 
20295ffd83dbSDimitry Andric   CalculateSyntheticValue();
20300b57cec5SDimitry Andric 
20310b57cec5SDimitry Andric   return m_synthetic_value != nullptr;
20320b57cec5SDimitry Andric }
20330b57cec5SDimitry Andric 
20340b57cec5SDimitry Andric ValueObject *ValueObject::GetNonBaseClassParent() {
20350b57cec5SDimitry Andric   if (GetParent()) {
20360b57cec5SDimitry Andric     if (GetParent()->IsBaseClass())
20370b57cec5SDimitry Andric       return GetParent()->GetNonBaseClassParent();
20380b57cec5SDimitry Andric     else
20390b57cec5SDimitry Andric       return GetParent();
20400b57cec5SDimitry Andric   }
20410b57cec5SDimitry Andric   return nullptr;
20420b57cec5SDimitry Andric }
20430b57cec5SDimitry Andric 
20440b57cec5SDimitry Andric bool ValueObject::IsBaseClass(uint32_t &depth) {
20450b57cec5SDimitry Andric   if (!IsBaseClass()) {
20460b57cec5SDimitry Andric     depth = 0;
20470b57cec5SDimitry Andric     return false;
20480b57cec5SDimitry Andric   }
20490b57cec5SDimitry Andric   if (GetParent()) {
20500b57cec5SDimitry Andric     GetParent()->IsBaseClass(depth);
20510b57cec5SDimitry Andric     depth = depth + 1;
20520b57cec5SDimitry Andric     return true;
20530b57cec5SDimitry Andric   }
20540b57cec5SDimitry Andric   // TODO: a base of no parent? weird..
20550b57cec5SDimitry Andric   depth = 1;
20560b57cec5SDimitry Andric   return true;
20570b57cec5SDimitry Andric }
20580b57cec5SDimitry Andric 
20595ffd83dbSDimitry Andric void ValueObject::GetExpressionPath(Stream &s,
20600b57cec5SDimitry Andric                                     GetExpressionPathFormat epformat) {
20610b57cec5SDimitry Andric   // synthetic children do not actually "exist" as part of the hierarchy, and
20620b57cec5SDimitry Andric   // sometimes they are consed up in ways that don't make sense from an
20630b57cec5SDimitry Andric   // underlying language/API standpoint. So, use a special code path here to
20640b57cec5SDimitry Andric   // return something that can hopefully be used in expression
2065fe6060f1SDimitry Andric   if (m_flags.m_is_synthetic_children_generated) {
20660b57cec5SDimitry Andric     UpdateValueIfNeeded();
20670b57cec5SDimitry Andric 
2068fe6060f1SDimitry Andric     if (m_value.GetValueType() == Value::ValueType::LoadAddress) {
20690b57cec5SDimitry Andric       if (IsPointerOrReferenceType()) {
20700b57cec5SDimitry Andric         s.Printf("((%s)0x%" PRIx64 ")", GetTypeName().AsCString("void"),
20710b57cec5SDimitry Andric                  GetValueAsUnsigned(0));
20720b57cec5SDimitry Andric         return;
20730b57cec5SDimitry Andric       } else {
20740b57cec5SDimitry Andric         uint64_t load_addr =
20750b57cec5SDimitry Andric             m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
20760b57cec5SDimitry Andric         if (load_addr != LLDB_INVALID_ADDRESS) {
20770b57cec5SDimitry Andric           s.Printf("(*( (%s *)0x%" PRIx64 "))", GetTypeName().AsCString("void"),
20780b57cec5SDimitry Andric                    load_addr);
20790b57cec5SDimitry Andric           return;
20800b57cec5SDimitry Andric         }
20810b57cec5SDimitry Andric       }
20820b57cec5SDimitry Andric     }
20830b57cec5SDimitry Andric 
20840b57cec5SDimitry Andric     if (CanProvideValue()) {
20850b57cec5SDimitry Andric       s.Printf("((%s)%s)", GetTypeName().AsCString("void"),
20860b57cec5SDimitry Andric                GetValueAsCString());
20870b57cec5SDimitry Andric       return;
20880b57cec5SDimitry Andric     }
20890b57cec5SDimitry Andric 
20900b57cec5SDimitry Andric     return;
20910b57cec5SDimitry Andric   }
20920b57cec5SDimitry Andric 
20930b57cec5SDimitry Andric   const bool is_deref_of_parent = IsDereferenceOfParent();
20940b57cec5SDimitry Andric 
20950b57cec5SDimitry Andric   if (is_deref_of_parent &&
20960b57cec5SDimitry Andric       epformat == eGetExpressionPathFormatDereferencePointers) {
20970b57cec5SDimitry Andric     // this is the original format of GetExpressionPath() producing code like
20980b57cec5SDimitry Andric     // *(a_ptr).memberName, which is entirely fine, until you put this into
20990b57cec5SDimitry Andric     // StackFrame::GetValueForVariableExpressionPath() which prefers to see
21000b57cec5SDimitry Andric     // a_ptr->memberName. the eHonorPointers mode is meant to produce strings
21010b57cec5SDimitry Andric     // in this latter format
21020b57cec5SDimitry Andric     s.PutCString("*(");
21030b57cec5SDimitry Andric   }
21040b57cec5SDimitry Andric 
21050b57cec5SDimitry Andric   ValueObject *parent = GetParent();
21060b57cec5SDimitry Andric 
21070b57cec5SDimitry Andric   if (parent)
21085ffd83dbSDimitry Andric     parent->GetExpressionPath(s, epformat);
21090b57cec5SDimitry Andric 
21100b57cec5SDimitry Andric   // if we are a deref_of_parent just because we are synthetic array members
21110b57cec5SDimitry Andric   // made up to allow ptr[%d] syntax to work in variable printing, then add our
21120b57cec5SDimitry Andric   // name ([%d]) to the expression path
2113fe6060f1SDimitry Andric   if (m_flags.m_is_array_item_for_pointer &&
21140b57cec5SDimitry Andric       epformat == eGetExpressionPathFormatHonorPointers)
21155ffd83dbSDimitry Andric     s.PutCString(m_name.GetStringRef());
21160b57cec5SDimitry Andric 
21170b57cec5SDimitry Andric   if (!IsBaseClass()) {
21180b57cec5SDimitry Andric     if (!is_deref_of_parent) {
21190b57cec5SDimitry Andric       ValueObject *non_base_class_parent = GetNonBaseClassParent();
21200b57cec5SDimitry Andric       if (non_base_class_parent &&
21210b57cec5SDimitry Andric           !non_base_class_parent->GetName().IsEmpty()) {
21220b57cec5SDimitry Andric         CompilerType non_base_class_parent_compiler_type =
21230b57cec5SDimitry Andric             non_base_class_parent->GetCompilerType();
21240b57cec5SDimitry Andric         if (non_base_class_parent_compiler_type) {
21250b57cec5SDimitry Andric           if (parent && parent->IsDereferenceOfParent() &&
21260b57cec5SDimitry Andric               epformat == eGetExpressionPathFormatHonorPointers) {
21270b57cec5SDimitry Andric             s.PutCString("->");
21280b57cec5SDimitry Andric           } else {
21290b57cec5SDimitry Andric             const uint32_t non_base_class_parent_type_info =
21300b57cec5SDimitry Andric                 non_base_class_parent_compiler_type.GetTypeInfo();
21310b57cec5SDimitry Andric 
21320b57cec5SDimitry Andric             if (non_base_class_parent_type_info & eTypeIsPointer) {
21330b57cec5SDimitry Andric               s.PutCString("->");
21340b57cec5SDimitry Andric             } else if ((non_base_class_parent_type_info & eTypeHasChildren) &&
21350b57cec5SDimitry Andric                        !(non_base_class_parent_type_info & eTypeIsArray)) {
21360b57cec5SDimitry Andric               s.PutChar('.');
21370b57cec5SDimitry Andric             }
21380b57cec5SDimitry Andric           }
21390b57cec5SDimitry Andric         }
21400b57cec5SDimitry Andric       }
21410b57cec5SDimitry Andric 
21420b57cec5SDimitry Andric       const char *name = GetName().GetCString();
21435ffd83dbSDimitry Andric       if (name)
21440b57cec5SDimitry Andric         s.PutCString(name);
21450b57cec5SDimitry Andric     }
21460b57cec5SDimitry Andric   }
21470b57cec5SDimitry Andric 
21480b57cec5SDimitry Andric   if (is_deref_of_parent &&
21490b57cec5SDimitry Andric       epformat == eGetExpressionPathFormatDereferencePointers) {
21500b57cec5SDimitry Andric     s.PutChar(')');
21510b57cec5SDimitry Andric   }
21520b57cec5SDimitry Andric }
21530b57cec5SDimitry Andric 
21540b57cec5SDimitry Andric ValueObjectSP ValueObject::GetValueForExpressionPath(
21550b57cec5SDimitry Andric     llvm::StringRef expression, ExpressionPathScanEndReason *reason_to_stop,
21560b57cec5SDimitry Andric     ExpressionPathEndResultType *final_value_type,
21570b57cec5SDimitry Andric     const GetValueForExpressionPathOptions &options,
21580b57cec5SDimitry Andric     ExpressionPathAftermath *final_task_on_target) {
21590b57cec5SDimitry Andric 
2160*0fca6ea1SDimitry Andric   ExpressionPathScanEndReason dummy_reason_to_stop =
2161*0fca6ea1SDimitry Andric       ValueObject::eExpressionPathScanEndReasonUnknown;
2162*0fca6ea1SDimitry Andric   ExpressionPathEndResultType dummy_final_value_type =
2163*0fca6ea1SDimitry Andric       ValueObject::eExpressionPathEndResultTypeInvalid;
2164*0fca6ea1SDimitry Andric   ExpressionPathAftermath dummy_final_task_on_target =
2165*0fca6ea1SDimitry Andric       ValueObject::eExpressionPathAftermathNothing;
21660b57cec5SDimitry Andric 
2167*0fca6ea1SDimitry Andric   ValueObjectSP ret_val = GetValueForExpressionPath_Impl(
2168*0fca6ea1SDimitry Andric       expression, reason_to_stop ? reason_to_stop : &dummy_reason_to_stop,
2169*0fca6ea1SDimitry Andric       final_value_type ? final_value_type : &dummy_final_value_type, options,
2170*0fca6ea1SDimitry Andric       final_task_on_target ? final_task_on_target
2171*0fca6ea1SDimitry Andric                            : &dummy_final_task_on_target);
21720b57cec5SDimitry Andric 
2173*0fca6ea1SDimitry Andric   if (!final_task_on_target ||
2174*0fca6ea1SDimitry Andric       *final_task_on_target == ValueObject::eExpressionPathAftermathNothing)
2175*0fca6ea1SDimitry Andric     return ret_val;
21760b57cec5SDimitry Andric 
2177*0fca6ea1SDimitry Andric   if (ret_val.get() &&
2178*0fca6ea1SDimitry Andric       ((final_value_type ? *final_value_type : dummy_final_value_type) ==
2179*0fca6ea1SDimitry Andric        eExpressionPathEndResultTypePlain)) // I can only deref and takeaddress
2180*0fca6ea1SDimitry Andric                                            // of plain objects
2181*0fca6ea1SDimitry Andric   {
2182*0fca6ea1SDimitry Andric     if ((final_task_on_target ? *final_task_on_target
2183*0fca6ea1SDimitry Andric                               : dummy_final_task_on_target) ==
2184*0fca6ea1SDimitry Andric         ValueObject::eExpressionPathAftermathDereference) {
21850b57cec5SDimitry Andric       Status error;
2186*0fca6ea1SDimitry Andric       ValueObjectSP final_value = ret_val->Dereference(error);
2187*0fca6ea1SDimitry Andric       if (error.Fail() || !final_value.get()) {
21880b57cec5SDimitry Andric         if (reason_to_stop)
2189*0fca6ea1SDimitry Andric           *reason_to_stop =
2190*0fca6ea1SDimitry Andric               ValueObject::eExpressionPathScanEndReasonDereferencingFailed;
21910b57cec5SDimitry Andric         if (final_value_type)
2192*0fca6ea1SDimitry Andric           *final_value_type = ValueObject::eExpressionPathEndResultTypeInvalid;
21930b57cec5SDimitry Andric         return ValueObjectSP();
2194*0fca6ea1SDimitry Andric       } else {
2195*0fca6ea1SDimitry Andric         if (final_task_on_target)
2196*0fca6ea1SDimitry Andric           *final_task_on_target = ValueObject::eExpressionPathAftermathNothing;
2197*0fca6ea1SDimitry Andric         return final_value;
2198*0fca6ea1SDimitry Andric       }
2199*0fca6ea1SDimitry Andric     }
2200*0fca6ea1SDimitry Andric     if (*final_task_on_target ==
2201*0fca6ea1SDimitry Andric         ValueObject::eExpressionPathAftermathTakeAddress) {
2202*0fca6ea1SDimitry Andric       Status error;
2203*0fca6ea1SDimitry Andric       ValueObjectSP final_value = ret_val->AddressOf(error);
2204*0fca6ea1SDimitry Andric       if (error.Fail() || !final_value.get()) {
2205*0fca6ea1SDimitry Andric         if (reason_to_stop)
2206*0fca6ea1SDimitry Andric           *reason_to_stop =
2207*0fca6ea1SDimitry Andric               ValueObject::eExpressionPathScanEndReasonTakingAddressFailed;
2208*0fca6ea1SDimitry Andric         if (final_value_type)
2209*0fca6ea1SDimitry Andric           *final_value_type = ValueObject::eExpressionPathEndResultTypeInvalid;
2210*0fca6ea1SDimitry Andric         return ValueObjectSP();
2211*0fca6ea1SDimitry Andric       } else {
2212*0fca6ea1SDimitry Andric         if (final_task_on_target)
2213*0fca6ea1SDimitry Andric           *final_task_on_target = ValueObject::eExpressionPathAftermathNothing;
2214*0fca6ea1SDimitry Andric         return final_value;
2215*0fca6ea1SDimitry Andric       }
2216*0fca6ea1SDimitry Andric     }
2217*0fca6ea1SDimitry Andric   }
2218*0fca6ea1SDimitry Andric   return ret_val; // final_task_on_target will still have its original value, so
2219*0fca6ea1SDimitry Andric                   // you know I did not do it
22200b57cec5SDimitry Andric }
22210b57cec5SDimitry Andric 
22220b57cec5SDimitry Andric ValueObjectSP ValueObject::GetValueForExpressionPath_Impl(
22230b57cec5SDimitry Andric     llvm::StringRef expression, ExpressionPathScanEndReason *reason_to_stop,
22240b57cec5SDimitry Andric     ExpressionPathEndResultType *final_result,
22250b57cec5SDimitry Andric     const GetValueForExpressionPathOptions &options,
22260b57cec5SDimitry Andric     ExpressionPathAftermath *what_next) {
22270b57cec5SDimitry Andric   ValueObjectSP root = GetSP();
22280b57cec5SDimitry Andric 
22290b57cec5SDimitry Andric   if (!root)
22300b57cec5SDimitry Andric     return nullptr;
22310b57cec5SDimitry Andric 
22320b57cec5SDimitry Andric   llvm::StringRef remainder = expression;
22330b57cec5SDimitry Andric 
22340b57cec5SDimitry Andric   while (true) {
22350b57cec5SDimitry Andric     llvm::StringRef temp_expression = remainder;
22360b57cec5SDimitry Andric 
22370b57cec5SDimitry Andric     CompilerType root_compiler_type = root->GetCompilerType();
22380b57cec5SDimitry Andric     CompilerType pointee_compiler_type;
22390b57cec5SDimitry Andric     Flags pointee_compiler_type_info;
22400b57cec5SDimitry Andric 
22410b57cec5SDimitry Andric     Flags root_compiler_type_info(
22420b57cec5SDimitry Andric         root_compiler_type.GetTypeInfo(&pointee_compiler_type));
22430b57cec5SDimitry Andric     if (pointee_compiler_type)
22440b57cec5SDimitry Andric       pointee_compiler_type_info.Reset(pointee_compiler_type.GetTypeInfo());
22450b57cec5SDimitry Andric 
22460b57cec5SDimitry Andric     if (temp_expression.empty()) {
22470b57cec5SDimitry Andric       *reason_to_stop = ValueObject::eExpressionPathScanEndReasonEndOfString;
22480b57cec5SDimitry Andric       return root;
22490b57cec5SDimitry Andric     }
22500b57cec5SDimitry Andric 
22510b57cec5SDimitry Andric     switch (temp_expression.front()) {
22520b57cec5SDimitry Andric     case '-': {
22530b57cec5SDimitry Andric       temp_expression = temp_expression.drop_front();
22540b57cec5SDimitry Andric       if (options.m_check_dot_vs_arrow_syntax &&
22550b57cec5SDimitry Andric           root_compiler_type_info.Test(eTypeIsPointer)) // if you are trying to
22560b57cec5SDimitry Andric                                                         // use -> on a
22570b57cec5SDimitry Andric                                                         // non-pointer and I
22580b57cec5SDimitry Andric                                                         // must catch the error
22590b57cec5SDimitry Andric       {
22600b57cec5SDimitry Andric         *reason_to_stop =
22610b57cec5SDimitry Andric             ValueObject::eExpressionPathScanEndReasonArrowInsteadOfDot;
22620b57cec5SDimitry Andric         *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
22630b57cec5SDimitry Andric         return ValueObjectSP();
22640b57cec5SDimitry Andric       }
22650b57cec5SDimitry Andric       if (root_compiler_type_info.Test(eTypeIsObjC) && // if yo are trying to
22660b57cec5SDimitry Andric                                                        // extract an ObjC IVar
22670b57cec5SDimitry Andric                                                        // when this is forbidden
22680b57cec5SDimitry Andric           root_compiler_type_info.Test(eTypeIsPointer) &&
22690b57cec5SDimitry Andric           options.m_no_fragile_ivar) {
22700b57cec5SDimitry Andric         *reason_to_stop =
22710b57cec5SDimitry Andric             ValueObject::eExpressionPathScanEndReasonFragileIVarNotAllowed;
22720b57cec5SDimitry Andric         *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
22730b57cec5SDimitry Andric         return ValueObjectSP();
22740b57cec5SDimitry Andric       }
22755f757f3fSDimitry Andric       if (!temp_expression.starts_with(">")) {
22760b57cec5SDimitry Andric         *reason_to_stop =
22770b57cec5SDimitry Andric             ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol;
22780b57cec5SDimitry Andric         *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
22790b57cec5SDimitry Andric         return ValueObjectSP();
22800b57cec5SDimitry Andric       }
22810b57cec5SDimitry Andric     }
2282bdd1243dSDimitry Andric       [[fallthrough]];
22830b57cec5SDimitry Andric     case '.': // or fallthrough from ->
22840b57cec5SDimitry Andric     {
22850b57cec5SDimitry Andric       if (options.m_check_dot_vs_arrow_syntax &&
22860b57cec5SDimitry Andric           temp_expression.front() == '.' &&
22870b57cec5SDimitry Andric           root_compiler_type_info.Test(eTypeIsPointer)) // if you are trying to
22880b57cec5SDimitry Andric                                                         // use . on a pointer
22890b57cec5SDimitry Andric                                                         // and I must catch the
22900b57cec5SDimitry Andric                                                         // error
22910b57cec5SDimitry Andric       {
22920b57cec5SDimitry Andric         *reason_to_stop =
22930b57cec5SDimitry Andric             ValueObject::eExpressionPathScanEndReasonDotInsteadOfArrow;
22940b57cec5SDimitry Andric         *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
22950b57cec5SDimitry Andric         return nullptr;
22960b57cec5SDimitry Andric       }
22970b57cec5SDimitry Andric       temp_expression = temp_expression.drop_front(); // skip . or >
22980b57cec5SDimitry Andric 
22990b57cec5SDimitry Andric       size_t next_sep_pos = temp_expression.find_first_of("-.[", 1);
23000b57cec5SDimitry Andric       if (next_sep_pos == llvm::StringRef::npos) // if no other separator just
23010b57cec5SDimitry Andric                                                  // expand this last layer
23020b57cec5SDimitry Andric       {
23035f757f3fSDimitry Andric         llvm::StringRef child_name = temp_expression;
23040b57cec5SDimitry Andric         ValueObjectSP child_valobj_sp =
230506c3fb27SDimitry Andric             root->GetChildMemberWithName(child_name);
23060b57cec5SDimitry Andric 
23070b57cec5SDimitry Andric         if (child_valobj_sp.get()) // we know we are done, so just return
23080b57cec5SDimitry Andric         {
23090b57cec5SDimitry Andric           *reason_to_stop =
23100b57cec5SDimitry Andric               ValueObject::eExpressionPathScanEndReasonEndOfString;
23110b57cec5SDimitry Andric           *final_result = ValueObject::eExpressionPathEndResultTypePlain;
23120b57cec5SDimitry Andric           return child_valobj_sp;
23130b57cec5SDimitry Andric         } else {
23140b57cec5SDimitry Andric           switch (options.m_synthetic_children_traversal) {
23150b57cec5SDimitry Andric           case GetValueForExpressionPathOptions::SyntheticChildrenTraversal::
23160b57cec5SDimitry Andric               None:
23170b57cec5SDimitry Andric             break;
23180b57cec5SDimitry Andric           case GetValueForExpressionPathOptions::SyntheticChildrenTraversal::
23190b57cec5SDimitry Andric               FromSynthetic:
23200b57cec5SDimitry Andric             if (root->IsSynthetic()) {
23210b57cec5SDimitry Andric               child_valobj_sp = root->GetNonSyntheticValue();
23220b57cec5SDimitry Andric               if (child_valobj_sp.get())
23230b57cec5SDimitry Andric                 child_valobj_sp =
232406c3fb27SDimitry Andric                     child_valobj_sp->GetChildMemberWithName(child_name);
23250b57cec5SDimitry Andric             }
23260b57cec5SDimitry Andric             break;
23270b57cec5SDimitry Andric           case GetValueForExpressionPathOptions::SyntheticChildrenTraversal::
23280b57cec5SDimitry Andric               ToSynthetic:
23290b57cec5SDimitry Andric             if (!root->IsSynthetic()) {
23300b57cec5SDimitry Andric               child_valobj_sp = root->GetSyntheticValue();
23310b57cec5SDimitry Andric               if (child_valobj_sp.get())
23320b57cec5SDimitry Andric                 child_valobj_sp =
233306c3fb27SDimitry Andric                     child_valobj_sp->GetChildMemberWithName(child_name);
23340b57cec5SDimitry Andric             }
23350b57cec5SDimitry Andric             break;
23360b57cec5SDimitry Andric           case GetValueForExpressionPathOptions::SyntheticChildrenTraversal::
23370b57cec5SDimitry Andric               Both:
23380b57cec5SDimitry Andric             if (root->IsSynthetic()) {
23390b57cec5SDimitry Andric               child_valobj_sp = root->GetNonSyntheticValue();
23400b57cec5SDimitry Andric               if (child_valobj_sp.get())
23410b57cec5SDimitry Andric                 child_valobj_sp =
234206c3fb27SDimitry Andric                     child_valobj_sp->GetChildMemberWithName(child_name);
23430b57cec5SDimitry Andric             } else {
23440b57cec5SDimitry Andric               child_valobj_sp = root->GetSyntheticValue();
23450b57cec5SDimitry Andric               if (child_valobj_sp.get())
23460b57cec5SDimitry Andric                 child_valobj_sp =
234706c3fb27SDimitry Andric                     child_valobj_sp->GetChildMemberWithName(child_name);
23480b57cec5SDimitry Andric             }
23490b57cec5SDimitry Andric             break;
23500b57cec5SDimitry Andric           }
23510b57cec5SDimitry Andric         }
23520b57cec5SDimitry Andric 
23530b57cec5SDimitry Andric         // if we are here and options.m_no_synthetic_children is true,
23540b57cec5SDimitry Andric         // child_valobj_sp is going to be a NULL SP, so we hit the "else"
23550b57cec5SDimitry Andric         // branch, and return an error
23560b57cec5SDimitry Andric         if (child_valobj_sp.get()) // if it worked, just return
23570b57cec5SDimitry Andric         {
23580b57cec5SDimitry Andric           *reason_to_stop =
23590b57cec5SDimitry Andric               ValueObject::eExpressionPathScanEndReasonEndOfString;
23600b57cec5SDimitry Andric           *final_result = ValueObject::eExpressionPathEndResultTypePlain;
23610b57cec5SDimitry Andric           return child_valobj_sp;
23620b57cec5SDimitry Andric         } else {
23630b57cec5SDimitry Andric           *reason_to_stop =
23640b57cec5SDimitry Andric               ValueObject::eExpressionPathScanEndReasonNoSuchChild;
23650b57cec5SDimitry Andric           *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
23660b57cec5SDimitry Andric           return nullptr;
23670b57cec5SDimitry Andric         }
23680b57cec5SDimitry Andric       } else // other layers do expand
23690b57cec5SDimitry Andric       {
23700b57cec5SDimitry Andric         llvm::StringRef next_separator = temp_expression.substr(next_sep_pos);
23715f757f3fSDimitry Andric         llvm::StringRef child_name = temp_expression.slice(0, next_sep_pos);
23720b57cec5SDimitry Andric 
23730b57cec5SDimitry Andric         ValueObjectSP child_valobj_sp =
237406c3fb27SDimitry Andric             root->GetChildMemberWithName(child_name);
23750b57cec5SDimitry Andric         if (child_valobj_sp.get()) // store the new root and move on
23760b57cec5SDimitry Andric         {
23770b57cec5SDimitry Andric           root = child_valobj_sp;
23780b57cec5SDimitry Andric           remainder = next_separator;
23790b57cec5SDimitry Andric           *final_result = ValueObject::eExpressionPathEndResultTypePlain;
23800b57cec5SDimitry Andric           continue;
23810b57cec5SDimitry Andric         } else {
23820b57cec5SDimitry Andric           switch (options.m_synthetic_children_traversal) {
23830b57cec5SDimitry Andric           case GetValueForExpressionPathOptions::SyntheticChildrenTraversal::
23840b57cec5SDimitry Andric               None:
23850b57cec5SDimitry Andric             break;
23860b57cec5SDimitry Andric           case GetValueForExpressionPathOptions::SyntheticChildrenTraversal::
23870b57cec5SDimitry Andric               FromSynthetic:
23880b57cec5SDimitry Andric             if (root->IsSynthetic()) {
23890b57cec5SDimitry Andric               child_valobj_sp = root->GetNonSyntheticValue();
23900b57cec5SDimitry Andric               if (child_valobj_sp.get())
23910b57cec5SDimitry Andric                 child_valobj_sp =
239206c3fb27SDimitry Andric                     child_valobj_sp->GetChildMemberWithName(child_name);
23930b57cec5SDimitry Andric             }
23940b57cec5SDimitry Andric             break;
23950b57cec5SDimitry Andric           case GetValueForExpressionPathOptions::SyntheticChildrenTraversal::
23960b57cec5SDimitry Andric               ToSynthetic:
23970b57cec5SDimitry Andric             if (!root->IsSynthetic()) {
23980b57cec5SDimitry Andric               child_valobj_sp = root->GetSyntheticValue();
23990b57cec5SDimitry Andric               if (child_valobj_sp.get())
24000b57cec5SDimitry Andric                 child_valobj_sp =
240106c3fb27SDimitry Andric                     child_valobj_sp->GetChildMemberWithName(child_name);
24020b57cec5SDimitry Andric             }
24030b57cec5SDimitry Andric             break;
24040b57cec5SDimitry Andric           case GetValueForExpressionPathOptions::SyntheticChildrenTraversal::
24050b57cec5SDimitry Andric               Both:
24060b57cec5SDimitry Andric             if (root->IsSynthetic()) {
24070b57cec5SDimitry Andric               child_valobj_sp = root->GetNonSyntheticValue();
24080b57cec5SDimitry Andric               if (child_valobj_sp.get())
24090b57cec5SDimitry Andric                 child_valobj_sp =
241006c3fb27SDimitry Andric                     child_valobj_sp->GetChildMemberWithName(child_name);
24110b57cec5SDimitry Andric             } else {
24120b57cec5SDimitry Andric               child_valobj_sp = root->GetSyntheticValue();
24130b57cec5SDimitry Andric               if (child_valobj_sp.get())
24140b57cec5SDimitry Andric                 child_valobj_sp =
241506c3fb27SDimitry Andric                     child_valobj_sp->GetChildMemberWithName(child_name);
24160b57cec5SDimitry Andric             }
24170b57cec5SDimitry Andric             break;
24180b57cec5SDimitry Andric           }
24190b57cec5SDimitry Andric         }
24200b57cec5SDimitry Andric 
24210b57cec5SDimitry Andric         // if we are here and options.m_no_synthetic_children is true,
24220b57cec5SDimitry Andric         // child_valobj_sp is going to be a NULL SP, so we hit the "else"
24230b57cec5SDimitry Andric         // branch, and return an error
24240b57cec5SDimitry Andric         if (child_valobj_sp.get()) // if it worked, move on
24250b57cec5SDimitry Andric         {
24260b57cec5SDimitry Andric           root = child_valobj_sp;
24270b57cec5SDimitry Andric           remainder = next_separator;
24280b57cec5SDimitry Andric           *final_result = ValueObject::eExpressionPathEndResultTypePlain;
24290b57cec5SDimitry Andric           continue;
24300b57cec5SDimitry Andric         } else {
24310b57cec5SDimitry Andric           *reason_to_stop =
24320b57cec5SDimitry Andric               ValueObject::eExpressionPathScanEndReasonNoSuchChild;
24330b57cec5SDimitry Andric           *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
24340b57cec5SDimitry Andric           return nullptr;
24350b57cec5SDimitry Andric         }
24360b57cec5SDimitry Andric       }
24370b57cec5SDimitry Andric       break;
24380b57cec5SDimitry Andric     }
24390b57cec5SDimitry Andric     case '[': {
24400b57cec5SDimitry Andric       if (!root_compiler_type_info.Test(eTypeIsArray) &&
24410b57cec5SDimitry Andric           !root_compiler_type_info.Test(eTypeIsPointer) &&
24420b57cec5SDimitry Andric           !root_compiler_type_info.Test(
24430b57cec5SDimitry Andric               eTypeIsVector)) // if this is not a T[] nor a T*
24440b57cec5SDimitry Andric       {
24450b57cec5SDimitry Andric         if (!root_compiler_type_info.Test(
24460b57cec5SDimitry Andric                 eTypeIsScalar)) // if this is not even a scalar...
24470b57cec5SDimitry Andric         {
24480b57cec5SDimitry Andric           if (options.m_synthetic_children_traversal ==
24490b57cec5SDimitry Andric               GetValueForExpressionPathOptions::SyntheticChildrenTraversal::
24500b57cec5SDimitry Andric                   None) // ...only chance left is synthetic
24510b57cec5SDimitry Andric           {
24520b57cec5SDimitry Andric             *reason_to_stop =
24530b57cec5SDimitry Andric                 ValueObject::eExpressionPathScanEndReasonRangeOperatorInvalid;
24540b57cec5SDimitry Andric             *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
24550b57cec5SDimitry Andric             return ValueObjectSP();
24560b57cec5SDimitry Andric           }
24570b57cec5SDimitry Andric         } else if (!options.m_allow_bitfields_syntax) // if this is a scalar,
24580b57cec5SDimitry Andric                                                       // check that we can
24590b57cec5SDimitry Andric                                                       // expand bitfields
24600b57cec5SDimitry Andric         {
24610b57cec5SDimitry Andric           *reason_to_stop =
24620b57cec5SDimitry Andric               ValueObject::eExpressionPathScanEndReasonRangeOperatorNotAllowed;
24630b57cec5SDimitry Andric           *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
24640b57cec5SDimitry Andric           return ValueObjectSP();
24650b57cec5SDimitry Andric         }
24660b57cec5SDimitry Andric       }
24670b57cec5SDimitry Andric       if (temp_expression[1] ==
24680b57cec5SDimitry Andric           ']') // if this is an unbounded range it only works for arrays
24690b57cec5SDimitry Andric       {
24700b57cec5SDimitry Andric         if (!root_compiler_type_info.Test(eTypeIsArray)) {
24710b57cec5SDimitry Andric           *reason_to_stop =
24720b57cec5SDimitry Andric               ValueObject::eExpressionPathScanEndReasonEmptyRangeNotAllowed;
24730b57cec5SDimitry Andric           *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
24740b57cec5SDimitry Andric           return nullptr;
24750b57cec5SDimitry Andric         } else // even if something follows, we cannot expand unbounded ranges,
24760b57cec5SDimitry Andric                // just let the caller do it
24770b57cec5SDimitry Andric         {
24780b57cec5SDimitry Andric           *reason_to_stop =
24790b57cec5SDimitry Andric               ValueObject::eExpressionPathScanEndReasonArrayRangeOperatorMet;
24800b57cec5SDimitry Andric           *final_result =
24810b57cec5SDimitry Andric               ValueObject::eExpressionPathEndResultTypeUnboundedRange;
24820b57cec5SDimitry Andric           return root;
24830b57cec5SDimitry Andric         }
24840b57cec5SDimitry Andric       }
24850b57cec5SDimitry Andric 
24860b57cec5SDimitry Andric       size_t close_bracket_position = temp_expression.find(']', 1);
24870b57cec5SDimitry Andric       if (close_bracket_position ==
24880b57cec5SDimitry Andric           llvm::StringRef::npos) // if there is no ], this is a syntax error
24890b57cec5SDimitry Andric       {
24900b57cec5SDimitry Andric         *reason_to_stop =
24910b57cec5SDimitry Andric             ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol;
24920b57cec5SDimitry Andric         *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
24930b57cec5SDimitry Andric         return nullptr;
24940b57cec5SDimitry Andric       }
24950b57cec5SDimitry Andric 
24960b57cec5SDimitry Andric       llvm::StringRef bracket_expr =
24970b57cec5SDimitry Andric           temp_expression.slice(1, close_bracket_position);
24980b57cec5SDimitry Andric 
24990b57cec5SDimitry Andric       // If this was an empty expression it would have been caught by the if
25000b57cec5SDimitry Andric       // above.
25010b57cec5SDimitry Andric       assert(!bracket_expr.empty());
25020b57cec5SDimitry Andric 
25030b57cec5SDimitry Andric       if (!bracket_expr.contains('-')) {
25040b57cec5SDimitry Andric         // if no separator, this is of the form [N].  Note that this cannot be
25050b57cec5SDimitry Andric         // an unbounded range of the form [], because that case was handled
25060b57cec5SDimitry Andric         // above with an unconditional return.
25070b57cec5SDimitry Andric         unsigned long index = 0;
25080b57cec5SDimitry Andric         if (bracket_expr.getAsInteger(0, index)) {
25090b57cec5SDimitry Andric           *reason_to_stop =
25100b57cec5SDimitry Andric               ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol;
25110b57cec5SDimitry Andric           *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
25120b57cec5SDimitry Andric           return nullptr;
25130b57cec5SDimitry Andric         }
25140b57cec5SDimitry Andric 
25150b57cec5SDimitry Andric         // from here on we do have a valid index
25160b57cec5SDimitry Andric         if (root_compiler_type_info.Test(eTypeIsArray)) {
251706c3fb27SDimitry Andric           ValueObjectSP child_valobj_sp = root->GetChildAtIndex(index);
25180b57cec5SDimitry Andric           if (!child_valobj_sp)
25190b57cec5SDimitry Andric             child_valobj_sp = root->GetSyntheticArrayMember(index, true);
25200b57cec5SDimitry Andric           if (!child_valobj_sp)
25210b57cec5SDimitry Andric             if (root->HasSyntheticValue() &&
2522*0fca6ea1SDimitry Andric                 llvm::expectedToStdOptional(
2523*0fca6ea1SDimitry Andric                     root->GetSyntheticValue()->GetNumChildren())
2524*0fca6ea1SDimitry Andric                         .value_or(0) > index)
25250b57cec5SDimitry Andric               child_valobj_sp =
252606c3fb27SDimitry Andric                   root->GetSyntheticValue()->GetChildAtIndex(index);
25270b57cec5SDimitry Andric           if (child_valobj_sp) {
25280b57cec5SDimitry Andric             root = child_valobj_sp;
25290b57cec5SDimitry Andric             remainder =
25300b57cec5SDimitry Andric                 temp_expression.substr(close_bracket_position + 1); // skip ]
25310b57cec5SDimitry Andric             *final_result = ValueObject::eExpressionPathEndResultTypePlain;
25320b57cec5SDimitry Andric             continue;
25330b57cec5SDimitry Andric           } else {
25340b57cec5SDimitry Andric             *reason_to_stop =
25350b57cec5SDimitry Andric                 ValueObject::eExpressionPathScanEndReasonNoSuchChild;
25360b57cec5SDimitry Andric             *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
25370b57cec5SDimitry Andric             return nullptr;
25380b57cec5SDimitry Andric           }
25390b57cec5SDimitry Andric         } else if (root_compiler_type_info.Test(eTypeIsPointer)) {
25400b57cec5SDimitry Andric           if (*what_next ==
25410b57cec5SDimitry Andric                   ValueObject::
25420b57cec5SDimitry Andric                       eExpressionPathAftermathDereference && // if this is a
25430b57cec5SDimitry Andric                                                              // ptr-to-scalar, I
25440b57cec5SDimitry Andric                                                              // am accessing it
25450b57cec5SDimitry Andric                                                              // by index and I
25460b57cec5SDimitry Andric                                                              // would have
25470b57cec5SDimitry Andric                                                              // deref'ed anyway,
25480b57cec5SDimitry Andric                                                              // then do it now
25490b57cec5SDimitry Andric                                                              // and use this as
25500b57cec5SDimitry Andric                                                              // a bitfield
25510b57cec5SDimitry Andric               pointee_compiler_type_info.Test(eTypeIsScalar)) {
25520b57cec5SDimitry Andric             Status error;
25530b57cec5SDimitry Andric             root = root->Dereference(error);
25540b57cec5SDimitry Andric             if (error.Fail() || !root) {
25550b57cec5SDimitry Andric               *reason_to_stop =
25560b57cec5SDimitry Andric                   ValueObject::eExpressionPathScanEndReasonDereferencingFailed;
25570b57cec5SDimitry Andric               *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
25580b57cec5SDimitry Andric               return nullptr;
25590b57cec5SDimitry Andric             } else {
25600b57cec5SDimitry Andric               *what_next = eExpressionPathAftermathNothing;
25610b57cec5SDimitry Andric               continue;
25620b57cec5SDimitry Andric             }
25630b57cec5SDimitry Andric           } else {
25640b57cec5SDimitry Andric             if (root->GetCompilerType().GetMinimumLanguage() ==
25650b57cec5SDimitry Andric                     eLanguageTypeObjC &&
25660b57cec5SDimitry Andric                 pointee_compiler_type_info.AllClear(eTypeIsPointer) &&
25670b57cec5SDimitry Andric                 root->HasSyntheticValue() &&
25680b57cec5SDimitry Andric                 (options.m_synthetic_children_traversal ==
25690b57cec5SDimitry Andric                      GetValueForExpressionPathOptions::
25700b57cec5SDimitry Andric                          SyntheticChildrenTraversal::ToSynthetic ||
25710b57cec5SDimitry Andric                  options.m_synthetic_children_traversal ==
25720b57cec5SDimitry Andric                      GetValueForExpressionPathOptions::
25730b57cec5SDimitry Andric                          SyntheticChildrenTraversal::Both)) {
257406c3fb27SDimitry Andric               root = root->GetSyntheticValue()->GetChildAtIndex(index);
25750b57cec5SDimitry Andric             } else
25760b57cec5SDimitry Andric               root = root->GetSyntheticArrayMember(index, true);
25770b57cec5SDimitry Andric             if (!root) {
25780b57cec5SDimitry Andric               *reason_to_stop =
25790b57cec5SDimitry Andric                   ValueObject::eExpressionPathScanEndReasonNoSuchChild;
25800b57cec5SDimitry Andric               *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
25810b57cec5SDimitry Andric               return nullptr;
25820b57cec5SDimitry Andric             } else {
25830b57cec5SDimitry Andric               remainder =
25840b57cec5SDimitry Andric                   temp_expression.substr(close_bracket_position + 1); // skip ]
25850b57cec5SDimitry Andric               *final_result = ValueObject::eExpressionPathEndResultTypePlain;
25860b57cec5SDimitry Andric               continue;
25870b57cec5SDimitry Andric             }
25880b57cec5SDimitry Andric           }
25890b57cec5SDimitry Andric         } else if (root_compiler_type_info.Test(eTypeIsScalar)) {
25900b57cec5SDimitry Andric           root = root->GetSyntheticBitFieldChild(index, index, true);
25910b57cec5SDimitry Andric           if (!root) {
25920b57cec5SDimitry Andric             *reason_to_stop =
25930b57cec5SDimitry Andric                 ValueObject::eExpressionPathScanEndReasonNoSuchChild;
25940b57cec5SDimitry Andric             *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
25950b57cec5SDimitry Andric             return nullptr;
25960b57cec5SDimitry Andric           } else // we do not know how to expand members of bitfields, so we
25970b57cec5SDimitry Andric                  // just return and let the caller do any further processing
25980b57cec5SDimitry Andric           {
25990b57cec5SDimitry Andric             *reason_to_stop = ValueObject::
26000b57cec5SDimitry Andric                 eExpressionPathScanEndReasonBitfieldRangeOperatorMet;
26010b57cec5SDimitry Andric             *final_result = ValueObject::eExpressionPathEndResultTypeBitfield;
26020b57cec5SDimitry Andric             return root;
26030b57cec5SDimitry Andric           }
26040b57cec5SDimitry Andric         } else if (root_compiler_type_info.Test(eTypeIsVector)) {
260506c3fb27SDimitry Andric           root = root->GetChildAtIndex(index);
26060b57cec5SDimitry Andric           if (!root) {
26070b57cec5SDimitry Andric             *reason_to_stop =
26080b57cec5SDimitry Andric                 ValueObject::eExpressionPathScanEndReasonNoSuchChild;
26090b57cec5SDimitry Andric             *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
26100b57cec5SDimitry Andric             return ValueObjectSP();
26110b57cec5SDimitry Andric           } else {
26120b57cec5SDimitry Andric             remainder =
26130b57cec5SDimitry Andric                 temp_expression.substr(close_bracket_position + 1); // skip ]
26140b57cec5SDimitry Andric             *final_result = ValueObject::eExpressionPathEndResultTypePlain;
26150b57cec5SDimitry Andric             continue;
26160b57cec5SDimitry Andric           }
26170b57cec5SDimitry Andric         } else if (options.m_synthetic_children_traversal ==
26180b57cec5SDimitry Andric                        GetValueForExpressionPathOptions::
26190b57cec5SDimitry Andric                            SyntheticChildrenTraversal::ToSynthetic ||
26200b57cec5SDimitry Andric                    options.m_synthetic_children_traversal ==
26210b57cec5SDimitry Andric                        GetValueForExpressionPathOptions::
26220b57cec5SDimitry Andric                            SyntheticChildrenTraversal::Both) {
26230b57cec5SDimitry Andric           if (root->HasSyntheticValue())
26240b57cec5SDimitry Andric             root = root->GetSyntheticValue();
26250b57cec5SDimitry Andric           else if (!root->IsSynthetic()) {
26260b57cec5SDimitry Andric             *reason_to_stop =
26270b57cec5SDimitry Andric                 ValueObject::eExpressionPathScanEndReasonSyntheticValueMissing;
26280b57cec5SDimitry Andric             *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
26290b57cec5SDimitry Andric             return nullptr;
26300b57cec5SDimitry Andric           }
26310b57cec5SDimitry Andric           // if we are here, then root itself is a synthetic VO.. should be
26320b57cec5SDimitry Andric           // good to go
26330b57cec5SDimitry Andric 
26340b57cec5SDimitry Andric           if (!root) {
26350b57cec5SDimitry Andric             *reason_to_stop =
26360b57cec5SDimitry Andric                 ValueObject::eExpressionPathScanEndReasonSyntheticValueMissing;
26370b57cec5SDimitry Andric             *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
26380b57cec5SDimitry Andric             return nullptr;
26390b57cec5SDimitry Andric           }
264006c3fb27SDimitry Andric           root = root->GetChildAtIndex(index);
26410b57cec5SDimitry Andric           if (!root) {
26420b57cec5SDimitry Andric             *reason_to_stop =
26430b57cec5SDimitry Andric                 ValueObject::eExpressionPathScanEndReasonNoSuchChild;
26440b57cec5SDimitry Andric             *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
26450b57cec5SDimitry Andric             return nullptr;
26460b57cec5SDimitry Andric           } else {
26470b57cec5SDimitry Andric             remainder =
26480b57cec5SDimitry Andric                 temp_expression.substr(close_bracket_position + 1); // skip ]
26490b57cec5SDimitry Andric             *final_result = ValueObject::eExpressionPathEndResultTypePlain;
26500b57cec5SDimitry Andric             continue;
26510b57cec5SDimitry Andric           }
26520b57cec5SDimitry Andric         } else {
26530b57cec5SDimitry Andric           *reason_to_stop =
26540b57cec5SDimitry Andric               ValueObject::eExpressionPathScanEndReasonNoSuchChild;
26550b57cec5SDimitry Andric           *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
26560b57cec5SDimitry Andric           return nullptr;
26570b57cec5SDimitry Andric         }
26580b57cec5SDimitry Andric       } else {
26590b57cec5SDimitry Andric         // we have a low and a high index
26600b57cec5SDimitry Andric         llvm::StringRef sleft, sright;
26610b57cec5SDimitry Andric         unsigned long low_index, high_index;
26620b57cec5SDimitry Andric         std::tie(sleft, sright) = bracket_expr.split('-');
26630b57cec5SDimitry Andric         if (sleft.getAsInteger(0, low_index) ||
26640b57cec5SDimitry Andric             sright.getAsInteger(0, high_index)) {
26650b57cec5SDimitry Andric           *reason_to_stop =
26660b57cec5SDimitry Andric               ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol;
26670b57cec5SDimitry Andric           *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
26680b57cec5SDimitry Andric           return nullptr;
26690b57cec5SDimitry Andric         }
26700b57cec5SDimitry Andric 
26710b57cec5SDimitry Andric         if (low_index > high_index) // swap indices if required
26720b57cec5SDimitry Andric           std::swap(low_index, high_index);
26730b57cec5SDimitry Andric 
26740b57cec5SDimitry Andric         if (root_compiler_type_info.Test(
26750b57cec5SDimitry Andric                 eTypeIsScalar)) // expansion only works for scalars
26760b57cec5SDimitry Andric         {
26770b57cec5SDimitry Andric           root = root->GetSyntheticBitFieldChild(low_index, high_index, true);
26780b57cec5SDimitry Andric           if (!root) {
26790b57cec5SDimitry Andric             *reason_to_stop =
26800b57cec5SDimitry Andric                 ValueObject::eExpressionPathScanEndReasonNoSuchChild;
26810b57cec5SDimitry Andric             *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
26820b57cec5SDimitry Andric             return nullptr;
26830b57cec5SDimitry Andric           } else {
26840b57cec5SDimitry Andric             *reason_to_stop = ValueObject::
26850b57cec5SDimitry Andric                 eExpressionPathScanEndReasonBitfieldRangeOperatorMet;
26860b57cec5SDimitry Andric             *final_result = ValueObject::eExpressionPathEndResultTypeBitfield;
26870b57cec5SDimitry Andric             return root;
26880b57cec5SDimitry Andric           }
26890b57cec5SDimitry Andric         } else if (root_compiler_type_info.Test(
26900b57cec5SDimitry Andric                        eTypeIsPointer) && // if this is a ptr-to-scalar, I am
26910b57cec5SDimitry Andric                                           // accessing it by index and I would
26920b57cec5SDimitry Andric                                           // have deref'ed anyway, then do it
26930b57cec5SDimitry Andric                                           // now and use this as a bitfield
26940b57cec5SDimitry Andric                    *what_next ==
26950b57cec5SDimitry Andric                        ValueObject::eExpressionPathAftermathDereference &&
26960b57cec5SDimitry Andric                    pointee_compiler_type_info.Test(eTypeIsScalar)) {
26970b57cec5SDimitry Andric           Status error;
26980b57cec5SDimitry Andric           root = root->Dereference(error);
26990b57cec5SDimitry Andric           if (error.Fail() || !root) {
27000b57cec5SDimitry Andric             *reason_to_stop =
27010b57cec5SDimitry Andric                 ValueObject::eExpressionPathScanEndReasonDereferencingFailed;
27020b57cec5SDimitry Andric             *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
27030b57cec5SDimitry Andric             return nullptr;
27040b57cec5SDimitry Andric           } else {
27050b57cec5SDimitry Andric             *what_next = ValueObject::eExpressionPathAftermathNothing;
27060b57cec5SDimitry Andric             continue;
27070b57cec5SDimitry Andric           }
27080b57cec5SDimitry Andric         } else {
27090b57cec5SDimitry Andric           *reason_to_stop =
27100b57cec5SDimitry Andric               ValueObject::eExpressionPathScanEndReasonArrayRangeOperatorMet;
27110b57cec5SDimitry Andric           *final_result = ValueObject::eExpressionPathEndResultTypeBoundedRange;
27120b57cec5SDimitry Andric           return root;
27130b57cec5SDimitry Andric         }
27140b57cec5SDimitry Andric       }
27150b57cec5SDimitry Andric       break;
27160b57cec5SDimitry Andric     }
27170b57cec5SDimitry Andric     default: // some non-separator is in the way
27180b57cec5SDimitry Andric     {
27190b57cec5SDimitry Andric       *reason_to_stop =
27200b57cec5SDimitry Andric           ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol;
27210b57cec5SDimitry Andric       *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
27220b57cec5SDimitry Andric       return nullptr;
27230b57cec5SDimitry Andric     }
27240b57cec5SDimitry Andric     }
27250b57cec5SDimitry Andric   }
27260b57cec5SDimitry Andric }
27270b57cec5SDimitry Andric 
2728*0fca6ea1SDimitry Andric llvm::Error ValueObject::Dump(Stream &s) {
2729*0fca6ea1SDimitry Andric   return Dump(s, DumpValueObjectOptions(*this));
2730*0fca6ea1SDimitry Andric }
27310b57cec5SDimitry Andric 
2732*0fca6ea1SDimitry Andric llvm::Error ValueObject::Dump(Stream &s,
2733*0fca6ea1SDimitry Andric                               const DumpValueObjectOptions &options) {
2734*0fca6ea1SDimitry Andric   ValueObjectPrinter printer(*this, &s, options);
2735*0fca6ea1SDimitry Andric   return printer.PrintValueObject();
27360b57cec5SDimitry Andric }
27370b57cec5SDimitry Andric 
27380b57cec5SDimitry Andric ValueObjectSP ValueObject::CreateConstantValue(ConstString name) {
27390b57cec5SDimitry Andric   ValueObjectSP valobj_sp;
27400b57cec5SDimitry Andric 
27410b57cec5SDimitry Andric   if (UpdateValueIfNeeded(false) && m_error.Success()) {
27420b57cec5SDimitry Andric     ExecutionContext exe_ctx(GetExecutionContextRef());
27430b57cec5SDimitry Andric 
27440b57cec5SDimitry Andric     DataExtractor data;
27450b57cec5SDimitry Andric     data.SetByteOrder(m_data.GetByteOrder());
27460b57cec5SDimitry Andric     data.SetAddressByteSize(m_data.GetAddressByteSize());
27470b57cec5SDimitry Andric 
27480b57cec5SDimitry Andric     if (IsBitfield()) {
27490b57cec5SDimitry Andric       Value v(Scalar(GetValueAsUnsigned(UINT64_MAX)));
27509dba64beSDimitry Andric       m_error = v.GetValueAsData(&exe_ctx, data, GetModule().get());
27510b57cec5SDimitry Andric     } else
27529dba64beSDimitry Andric       m_error = m_value.GetValueAsData(&exe_ctx, data, GetModule().get());
27530b57cec5SDimitry Andric 
27540b57cec5SDimitry Andric     valobj_sp = ValueObjectConstResult::Create(
27550b57cec5SDimitry Andric         exe_ctx.GetBestExecutionContextScope(), GetCompilerType(), name, data,
27560b57cec5SDimitry Andric         GetAddressOf());
27570b57cec5SDimitry Andric   }
27580b57cec5SDimitry Andric 
27590b57cec5SDimitry Andric   if (!valobj_sp) {
27600b57cec5SDimitry Andric     ExecutionContext exe_ctx(GetExecutionContextRef());
27610b57cec5SDimitry Andric     valobj_sp = ValueObjectConstResult::Create(
27620b57cec5SDimitry Andric         exe_ctx.GetBestExecutionContextScope(), m_error);
27630b57cec5SDimitry Andric   }
27640b57cec5SDimitry Andric   return valobj_sp;
27650b57cec5SDimitry Andric }
27660b57cec5SDimitry Andric 
27670b57cec5SDimitry Andric ValueObjectSP ValueObject::GetQualifiedRepresentationIfAvailable(
27680b57cec5SDimitry Andric     lldb::DynamicValueType dynValue, bool synthValue) {
27695f757f3fSDimitry Andric   ValueObjectSP result_sp;
27700b57cec5SDimitry Andric   switch (dynValue) {
27710b57cec5SDimitry Andric   case lldb::eDynamicCanRunTarget:
27720b57cec5SDimitry Andric   case lldb::eDynamicDontRunTarget: {
27735f757f3fSDimitry Andric     if (!IsDynamic())
27745f757f3fSDimitry Andric       result_sp = GetDynamicValue(dynValue);
27750b57cec5SDimitry Andric   } break;
27760b57cec5SDimitry Andric   case lldb::eNoDynamicValues: {
27775f757f3fSDimitry Andric     if (IsDynamic())
27785f757f3fSDimitry Andric       result_sp = GetStaticValue();
27790b57cec5SDimitry Andric   } break;
27800b57cec5SDimitry Andric   }
27815f757f3fSDimitry Andric   if (!result_sp)
27825f757f3fSDimitry Andric     result_sp = GetSP();
27835f757f3fSDimitry Andric   assert(result_sp);
27840b57cec5SDimitry Andric 
27855f757f3fSDimitry Andric   bool is_synthetic = result_sp->IsSynthetic();
27865f757f3fSDimitry Andric   if (synthValue && !is_synthetic) {
27875f757f3fSDimitry Andric     if (auto synth_sp = result_sp->GetSyntheticValue())
27885f757f3fSDimitry Andric       return synth_sp;
27890b57cec5SDimitry Andric   }
27905f757f3fSDimitry Andric   if (!synthValue && is_synthetic) {
27915f757f3fSDimitry Andric     if (auto non_synth_sp = result_sp->GetNonSyntheticValue())
27925f757f3fSDimitry Andric       return non_synth_sp;
27930b57cec5SDimitry Andric   }
27940b57cec5SDimitry Andric 
27950b57cec5SDimitry Andric   return result_sp;
27960b57cec5SDimitry Andric }
27970b57cec5SDimitry Andric 
27980b57cec5SDimitry Andric ValueObjectSP ValueObject::Dereference(Status &error) {
27990b57cec5SDimitry Andric   if (m_deref_valobj)
28000b57cec5SDimitry Andric     return m_deref_valobj->GetSP();
28010b57cec5SDimitry Andric 
28020b57cec5SDimitry Andric   const bool is_pointer_or_reference_type = IsPointerOrReferenceType();
28030b57cec5SDimitry Andric   if (is_pointer_or_reference_type) {
28040b57cec5SDimitry Andric     bool omit_empty_base_classes = true;
28050b57cec5SDimitry Andric     bool ignore_array_bounds = false;
28060b57cec5SDimitry Andric 
28070b57cec5SDimitry Andric     std::string child_name_str;
28080b57cec5SDimitry Andric     uint32_t child_byte_size = 0;
28090b57cec5SDimitry Andric     int32_t child_byte_offset = 0;
28100b57cec5SDimitry Andric     uint32_t child_bitfield_bit_size = 0;
28110b57cec5SDimitry Andric     uint32_t child_bitfield_bit_offset = 0;
28120b57cec5SDimitry Andric     bool child_is_base_class = false;
28130b57cec5SDimitry Andric     bool child_is_deref_of_parent = false;
28140b57cec5SDimitry Andric     const bool transparent_pointers = false;
28150b57cec5SDimitry Andric     CompilerType compiler_type = GetCompilerType();
28165ffd83dbSDimitry Andric     uint64_t language_flags = 0;
28170b57cec5SDimitry Andric 
28180b57cec5SDimitry Andric     ExecutionContext exe_ctx(GetExecutionContextRef());
28190b57cec5SDimitry Andric 
2820*0fca6ea1SDimitry Andric     CompilerType child_compiler_type;
2821*0fca6ea1SDimitry Andric     auto child_compiler_type_or_err = compiler_type.GetChildCompilerTypeAtIndex(
28220b57cec5SDimitry Andric         &exe_ctx, 0, transparent_pointers, omit_empty_base_classes,
28230b57cec5SDimitry Andric         ignore_array_bounds, child_name_str, child_byte_size, child_byte_offset,
28240b57cec5SDimitry Andric         child_bitfield_bit_size, child_bitfield_bit_offset, child_is_base_class,
28250b57cec5SDimitry Andric         child_is_deref_of_parent, this, language_flags);
2826*0fca6ea1SDimitry Andric     if (!child_compiler_type_or_err)
2827*0fca6ea1SDimitry Andric       LLDB_LOG_ERROR(GetLog(LLDBLog::Types),
2828*0fca6ea1SDimitry Andric                      child_compiler_type_or_err.takeError(),
2829*0fca6ea1SDimitry Andric                      "could not find child: {0}");
2830*0fca6ea1SDimitry Andric     else
2831*0fca6ea1SDimitry Andric       child_compiler_type = *child_compiler_type_or_err;
2832*0fca6ea1SDimitry Andric 
28330b57cec5SDimitry Andric     if (child_compiler_type && child_byte_size) {
28340b57cec5SDimitry Andric       ConstString child_name;
28350b57cec5SDimitry Andric       if (!child_name_str.empty())
28360b57cec5SDimitry Andric         child_name.SetCString(child_name_str.c_str());
28370b57cec5SDimitry Andric 
28380b57cec5SDimitry Andric       m_deref_valobj = new ValueObjectChild(
28390b57cec5SDimitry Andric           *this, child_compiler_type, child_name, child_byte_size,
28400b57cec5SDimitry Andric           child_byte_offset, child_bitfield_bit_size, child_bitfield_bit_offset,
28410b57cec5SDimitry Andric           child_is_base_class, child_is_deref_of_parent, eAddressTypeInvalid,
28420b57cec5SDimitry Andric           language_flags);
28430b57cec5SDimitry Andric     }
28445ffd83dbSDimitry Andric 
28455ffd83dbSDimitry Andric     // In case of incomplete child compiler type, use the pointee type and try
28465ffd83dbSDimitry Andric     // to recreate a new ValueObjectChild using it.
28475ffd83dbSDimitry Andric     if (!m_deref_valobj) {
2848bdd1243dSDimitry Andric       // FIXME(#59012): C++ stdlib formatters break with incomplete types (e.g.
2849bdd1243dSDimitry Andric       // `std::vector<int> &`). Remove ObjC restriction once that's resolved.
2850bdd1243dSDimitry Andric       if (Language::LanguageIsObjC(GetPreferredDisplayLanguage()) &&
2851bdd1243dSDimitry Andric           HasSyntheticValue()) {
28525ffd83dbSDimitry Andric         child_compiler_type = compiler_type.GetPointeeType();
28535ffd83dbSDimitry Andric 
28545ffd83dbSDimitry Andric         if (child_compiler_type) {
28555ffd83dbSDimitry Andric           ConstString child_name;
28565ffd83dbSDimitry Andric           if (!child_name_str.empty())
28575ffd83dbSDimitry Andric             child_name.SetCString(child_name_str.c_str());
28585ffd83dbSDimitry Andric 
28595ffd83dbSDimitry Andric           m_deref_valobj = new ValueObjectChild(
28605ffd83dbSDimitry Andric               *this, child_compiler_type, child_name, child_byte_size,
28615ffd83dbSDimitry Andric               child_byte_offset, child_bitfield_bit_size,
28625ffd83dbSDimitry Andric               child_bitfield_bit_offset, child_is_base_class,
28635ffd83dbSDimitry Andric               child_is_deref_of_parent, eAddressTypeInvalid, language_flags);
28645ffd83dbSDimitry Andric         }
28655ffd83dbSDimitry Andric       }
28665ffd83dbSDimitry Andric     }
28675ffd83dbSDimitry Andric 
28680b57cec5SDimitry Andric   } else if (HasSyntheticValue()) {
28690b57cec5SDimitry Andric     m_deref_valobj =
287006c3fb27SDimitry Andric         GetSyntheticValue()->GetChildMemberWithName("$$dereference$$").get();
28715ffd83dbSDimitry Andric   } else if (IsSynthetic()) {
287206c3fb27SDimitry Andric     m_deref_valobj = GetChildMemberWithName("$$dereference$$").get();
28730b57cec5SDimitry Andric   }
28740b57cec5SDimitry Andric 
28750b57cec5SDimitry Andric   if (m_deref_valobj) {
28760b57cec5SDimitry Andric     error.Clear();
28770b57cec5SDimitry Andric     return m_deref_valobj->GetSP();
28780b57cec5SDimitry Andric   } else {
28790b57cec5SDimitry Andric     StreamString strm;
28805ffd83dbSDimitry Andric     GetExpressionPath(strm);
28810b57cec5SDimitry Andric 
28820b57cec5SDimitry Andric     if (is_pointer_or_reference_type)
28830b57cec5SDimitry Andric       error.SetErrorStringWithFormat("dereference failed: (%s) %s",
28840b57cec5SDimitry Andric                                      GetTypeName().AsCString("<invalid type>"),
28850b57cec5SDimitry Andric                                      strm.GetData());
28860b57cec5SDimitry Andric     else
28870b57cec5SDimitry Andric       error.SetErrorStringWithFormat("not a pointer or reference type: (%s) %s",
28880b57cec5SDimitry Andric                                      GetTypeName().AsCString("<invalid type>"),
28890b57cec5SDimitry Andric                                      strm.GetData());
28900b57cec5SDimitry Andric     return ValueObjectSP();
28910b57cec5SDimitry Andric   }
28920b57cec5SDimitry Andric }
28930b57cec5SDimitry Andric 
28940b57cec5SDimitry Andric ValueObjectSP ValueObject::AddressOf(Status &error) {
28950b57cec5SDimitry Andric   if (m_addr_of_valobj_sp)
28960b57cec5SDimitry Andric     return m_addr_of_valobj_sp;
28970b57cec5SDimitry Andric 
28980b57cec5SDimitry Andric   AddressType address_type = eAddressTypeInvalid;
28990b57cec5SDimitry Andric   const bool scalar_is_load_address = false;
29000b57cec5SDimitry Andric   addr_t addr = GetAddressOf(scalar_is_load_address, &address_type);
29010b57cec5SDimitry Andric   error.Clear();
2902*0fca6ea1SDimitry Andric   if (addr != LLDB_INVALID_ADDRESS && address_type != eAddressTypeHost) {
2903*0fca6ea1SDimitry Andric     switch (address_type) {
2904*0fca6ea1SDimitry Andric     case eAddressTypeInvalid: {
29050b57cec5SDimitry Andric       StreamString expr_path_strm;
29065ffd83dbSDimitry Andric       GetExpressionPath(expr_path_strm);
2907*0fca6ea1SDimitry Andric       error.SetErrorStringWithFormat("'%s' is not in memory",
2908*0fca6ea1SDimitry Andric                                      expr_path_strm.GetData());
2909*0fca6ea1SDimitry Andric     } break;
29100b57cec5SDimitry Andric 
29110b57cec5SDimitry Andric     case eAddressTypeFile:
29120b57cec5SDimitry Andric     case eAddressTypeLoad: {
29130b57cec5SDimitry Andric       CompilerType compiler_type = GetCompilerType();
2914*0fca6ea1SDimitry Andric       if (compiler_type) {
29157a6dacacSDimitry Andric         std::string name(1, '&');
29167a6dacacSDimitry Andric         name.append(m_name.AsCString(""));
2917*0fca6ea1SDimitry Andric         ExecutionContext exe_ctx(GetExecutionContextRef());
29187a6dacacSDimitry Andric         m_addr_of_valobj_sp = ValueObjectConstResult::Create(
2919*0fca6ea1SDimitry Andric             exe_ctx.GetBestExecutionContextScope(),
2920*0fca6ea1SDimitry Andric             compiler_type.GetPointerType(), ConstString(name.c_str()), addr,
29217a6dacacSDimitry Andric             eAddressTypeInvalid, m_data.GetAddressByteSize());
2922*0fca6ea1SDimitry Andric       }
2923*0fca6ea1SDimitry Andric     } break;
2924*0fca6ea1SDimitry Andric     default:
2925*0fca6ea1SDimitry Andric       break;
2926*0fca6ea1SDimitry Andric     }
2927*0fca6ea1SDimitry Andric   } else {
2928*0fca6ea1SDimitry Andric     StreamString expr_path_strm;
2929*0fca6ea1SDimitry Andric     GetExpressionPath(expr_path_strm);
2930*0fca6ea1SDimitry Andric     error.SetErrorStringWithFormat("'%s' doesn't have a valid address",
2931*0fca6ea1SDimitry Andric                                    expr_path_strm.GetData());
2932*0fca6ea1SDimitry Andric   }
2933*0fca6ea1SDimitry Andric 
29340b57cec5SDimitry Andric   return m_addr_of_valobj_sp;
29350b57cec5SDimitry Andric }
29360b57cec5SDimitry Andric 
293706c3fb27SDimitry Andric ValueObjectSP ValueObject::DoCast(const CompilerType &compiler_type) {
29380b57cec5SDimitry Andric     return ValueObjectCast::Create(*this, GetName(), compiler_type);
29390b57cec5SDimitry Andric }
29400b57cec5SDimitry Andric 
294106c3fb27SDimitry Andric ValueObjectSP ValueObject::Cast(const CompilerType &compiler_type) {
294206c3fb27SDimitry Andric   // Only allow casts if the original type is equal or larger than the cast
2943*0fca6ea1SDimitry Andric   // type, unless we know this is a load address.  Getting the size wrong for
2944*0fca6ea1SDimitry Andric   // a host side storage could leak lldb memory, so we absolutely want to
2945*0fca6ea1SDimitry Andric   // prevent that.  We may not always get the right value, for instance if we
2946*0fca6ea1SDimitry Andric   // have an expression result value that's copied into a storage location in
2947*0fca6ea1SDimitry Andric   // the target may not have copied enough memory.  I'm not trying to fix that
2948*0fca6ea1SDimitry Andric   // here, I'm just making Cast from a smaller to a larger possible in all the
2949*0fca6ea1SDimitry Andric   // cases where that doesn't risk making a Value out of random lldb memory.
2950*0fca6ea1SDimitry Andric   // You have to check the ValueObject's Value for the address types, since
2951*0fca6ea1SDimitry Andric   // ValueObjects that use live addresses will tell you they fetch data from the
2952*0fca6ea1SDimitry Andric   // live address, but once they are made, they actually don't.
2953*0fca6ea1SDimitry Andric   // FIXME: Can we make ValueObject's with a live address fetch "more data" from
2954*0fca6ea1SDimitry Andric   // the live address if it is still valid?
2955*0fca6ea1SDimitry Andric 
295606c3fb27SDimitry Andric   Status error;
295706c3fb27SDimitry Andric   CompilerType my_type = GetCompilerType();
295806c3fb27SDimitry Andric 
295906c3fb27SDimitry Andric   ExecutionContextScope *exe_scope
296006c3fb27SDimitry Andric       = ExecutionContext(GetExecutionContextRef())
296106c3fb27SDimitry Andric           .GetBestExecutionContextScope();
296206c3fb27SDimitry Andric   if (compiler_type.GetByteSize(exe_scope)
2963*0fca6ea1SDimitry Andric       <= GetCompilerType().GetByteSize(exe_scope)
2964*0fca6ea1SDimitry Andric       || m_value.GetValueType() == Value::ValueType::LoadAddress)
296506c3fb27SDimitry Andric         return DoCast(compiler_type);
2966*0fca6ea1SDimitry Andric 
296706c3fb27SDimitry Andric   error.SetErrorString("Can only cast to a type that is equal to or smaller "
296806c3fb27SDimitry Andric                        "than the orignal type.");
296906c3fb27SDimitry Andric 
297006c3fb27SDimitry Andric   return ValueObjectConstResult::Create(
297106c3fb27SDimitry Andric       ExecutionContext(GetExecutionContextRef()).GetBestExecutionContextScope(),
297206c3fb27SDimitry Andric                        error);
297306c3fb27SDimitry Andric }
297406c3fb27SDimitry Andric 
29750b57cec5SDimitry Andric lldb::ValueObjectSP ValueObject::Clone(ConstString new_name) {
29760b57cec5SDimitry Andric   return ValueObjectCast::Create(*this, new_name, GetCompilerType());
29770b57cec5SDimitry Andric }
29780b57cec5SDimitry Andric 
29790b57cec5SDimitry Andric ValueObjectSP ValueObject::CastPointerType(const char *name,
29800b57cec5SDimitry Andric                                            CompilerType &compiler_type) {
29810b57cec5SDimitry Andric   ValueObjectSP valobj_sp;
29820b57cec5SDimitry Andric   AddressType address_type;
29830b57cec5SDimitry Andric   addr_t ptr_value = GetPointerValue(&address_type);
29840b57cec5SDimitry Andric 
29850b57cec5SDimitry Andric   if (ptr_value != LLDB_INVALID_ADDRESS) {
29860b57cec5SDimitry Andric     Address ptr_addr(ptr_value);
29870b57cec5SDimitry Andric     ExecutionContext exe_ctx(GetExecutionContextRef());
29880b57cec5SDimitry Andric     valobj_sp = ValueObjectMemory::Create(
29890b57cec5SDimitry Andric         exe_ctx.GetBestExecutionContextScope(), name, ptr_addr, compiler_type);
29900b57cec5SDimitry Andric   }
29910b57cec5SDimitry Andric   return valobj_sp;
29920b57cec5SDimitry Andric }
29930b57cec5SDimitry Andric 
29940b57cec5SDimitry Andric ValueObjectSP ValueObject::CastPointerType(const char *name, TypeSP &type_sp) {
29950b57cec5SDimitry Andric   ValueObjectSP valobj_sp;
29960b57cec5SDimitry Andric   AddressType address_type;
29970b57cec5SDimitry Andric   addr_t ptr_value = GetPointerValue(&address_type);
29980b57cec5SDimitry Andric 
29990b57cec5SDimitry Andric   if (ptr_value != LLDB_INVALID_ADDRESS) {
30000b57cec5SDimitry Andric     Address ptr_addr(ptr_value);
30010b57cec5SDimitry Andric     ExecutionContext exe_ctx(GetExecutionContextRef());
30020b57cec5SDimitry Andric     valobj_sp = ValueObjectMemory::Create(
30030b57cec5SDimitry Andric         exe_ctx.GetBestExecutionContextScope(), name, ptr_addr, type_sp);
30040b57cec5SDimitry Andric   }
30050b57cec5SDimitry Andric   return valobj_sp;
30060b57cec5SDimitry Andric }
30070b57cec5SDimitry Andric 
3008*0fca6ea1SDimitry Andric lldb::addr_t ValueObject::GetLoadAddress() {
3009*0fca6ea1SDimitry Andric   lldb::addr_t addr_value = LLDB_INVALID_ADDRESS;
3010*0fca6ea1SDimitry Andric   if (auto target_sp = GetTargetSP()) {
3011*0fca6ea1SDimitry Andric     const bool scalar_is_load_address = true;
3012*0fca6ea1SDimitry Andric     AddressType addr_type;
3013*0fca6ea1SDimitry Andric     addr_value = GetAddressOf(scalar_is_load_address, &addr_type);
3014*0fca6ea1SDimitry Andric     if (addr_type == eAddressTypeFile) {
3015*0fca6ea1SDimitry Andric       lldb::ModuleSP module_sp(GetModule());
3016*0fca6ea1SDimitry Andric       if (!module_sp)
3017*0fca6ea1SDimitry Andric         addr_value = LLDB_INVALID_ADDRESS;
3018*0fca6ea1SDimitry Andric       else {
3019*0fca6ea1SDimitry Andric         Address tmp_addr;
3020*0fca6ea1SDimitry Andric         module_sp->ResolveFileAddress(addr_value, tmp_addr);
3021*0fca6ea1SDimitry Andric         addr_value = tmp_addr.GetLoadAddress(target_sp.get());
3022*0fca6ea1SDimitry Andric       }
3023*0fca6ea1SDimitry Andric     } else if (addr_type == eAddressTypeHost ||
3024*0fca6ea1SDimitry Andric                addr_type == eAddressTypeInvalid)
3025*0fca6ea1SDimitry Andric       addr_value = LLDB_INVALID_ADDRESS;
3026*0fca6ea1SDimitry Andric   }
3027*0fca6ea1SDimitry Andric   return addr_value;
3028*0fca6ea1SDimitry Andric }
3029*0fca6ea1SDimitry Andric 
3030*0fca6ea1SDimitry Andric llvm::Expected<lldb::ValueObjectSP> ValueObject::CastDerivedToBaseType(
3031*0fca6ea1SDimitry Andric     CompilerType type, const llvm::ArrayRef<uint32_t> &base_type_indices) {
3032*0fca6ea1SDimitry Andric   // Make sure the starting type and the target type are both valid for this
3033*0fca6ea1SDimitry Andric   // type of cast; otherwise return the shared pointer to the original
3034*0fca6ea1SDimitry Andric   // (unchanged) ValueObject.
3035*0fca6ea1SDimitry Andric   if (!type.IsPointerType() && !type.IsReferenceType())
3036*0fca6ea1SDimitry Andric     return llvm::make_error<llvm::StringError>(
3037*0fca6ea1SDimitry Andric         "Invalid target type: should be a pointer or a reference",
3038*0fca6ea1SDimitry Andric         llvm::inconvertibleErrorCode());
3039*0fca6ea1SDimitry Andric 
3040*0fca6ea1SDimitry Andric   CompilerType start_type = GetCompilerType();
3041*0fca6ea1SDimitry Andric   if (start_type.IsReferenceType())
3042*0fca6ea1SDimitry Andric     start_type = start_type.GetNonReferenceType();
3043*0fca6ea1SDimitry Andric 
3044*0fca6ea1SDimitry Andric   auto target_record_type =
3045*0fca6ea1SDimitry Andric       type.IsPointerType() ? type.GetPointeeType() : type.GetNonReferenceType();
3046*0fca6ea1SDimitry Andric   auto start_record_type =
3047*0fca6ea1SDimitry Andric       start_type.IsPointerType() ? start_type.GetPointeeType() : start_type;
3048*0fca6ea1SDimitry Andric 
3049*0fca6ea1SDimitry Andric   if (!target_record_type.IsRecordType() || !start_record_type.IsRecordType())
3050*0fca6ea1SDimitry Andric     return llvm::make_error<llvm::StringError>(
3051*0fca6ea1SDimitry Andric         "Underlying start & target types should be record types",
3052*0fca6ea1SDimitry Andric         llvm::inconvertibleErrorCode());
3053*0fca6ea1SDimitry Andric 
3054*0fca6ea1SDimitry Andric   if (target_record_type.CompareTypes(start_record_type))
3055*0fca6ea1SDimitry Andric     return llvm::make_error<llvm::StringError>(
3056*0fca6ea1SDimitry Andric         "Underlying start & target types should be different",
3057*0fca6ea1SDimitry Andric         llvm::inconvertibleErrorCode());
3058*0fca6ea1SDimitry Andric 
3059*0fca6ea1SDimitry Andric   if (base_type_indices.empty())
3060*0fca6ea1SDimitry Andric     return llvm::make_error<llvm::StringError>(
3061*0fca6ea1SDimitry Andric         "Children sequence must be non-empty", llvm::inconvertibleErrorCode());
3062*0fca6ea1SDimitry Andric 
3063*0fca6ea1SDimitry Andric   // Both the starting & target types are valid for the cast, and the list of
3064*0fca6ea1SDimitry Andric   // base class indices is non-empty, so we can proceed with the cast.
3065*0fca6ea1SDimitry Andric 
3066*0fca6ea1SDimitry Andric   lldb::TargetSP target = GetTargetSP();
3067*0fca6ea1SDimitry Andric   // The `value` can be a pointer, but GetChildAtIndex works for pointers too.
3068*0fca6ea1SDimitry Andric   lldb::ValueObjectSP inner_value = GetSP();
3069*0fca6ea1SDimitry Andric 
3070*0fca6ea1SDimitry Andric   for (const uint32_t i : base_type_indices)
3071*0fca6ea1SDimitry Andric     // Create synthetic value if needed.
3072*0fca6ea1SDimitry Andric     inner_value =
3073*0fca6ea1SDimitry Andric         inner_value->GetChildAtIndex(i, /*can_create_synthetic*/ true);
3074*0fca6ea1SDimitry Andric 
3075*0fca6ea1SDimitry Andric   // At this point type of `inner_value` should be the dereferenced target
3076*0fca6ea1SDimitry Andric   // type.
3077*0fca6ea1SDimitry Andric   CompilerType inner_value_type = inner_value->GetCompilerType();
3078*0fca6ea1SDimitry Andric   if (type.IsPointerType()) {
3079*0fca6ea1SDimitry Andric     if (!inner_value_type.CompareTypes(type.GetPointeeType()))
3080*0fca6ea1SDimitry Andric       return llvm::make_error<llvm::StringError>(
3081*0fca6ea1SDimitry Andric           "casted value doesn't match the desired type",
3082*0fca6ea1SDimitry Andric           llvm::inconvertibleErrorCode());
3083*0fca6ea1SDimitry Andric 
3084*0fca6ea1SDimitry Andric     uintptr_t addr = inner_value->GetLoadAddress();
3085*0fca6ea1SDimitry Andric     llvm::StringRef name = "";
3086*0fca6ea1SDimitry Andric     ExecutionContext exe_ctx(target.get(), false);
3087*0fca6ea1SDimitry Andric     return ValueObject::CreateValueObjectFromAddress(name, addr, exe_ctx, type,
3088*0fca6ea1SDimitry Andric                                                      /* do deref */ false);
3089*0fca6ea1SDimitry Andric   }
3090*0fca6ea1SDimitry Andric 
3091*0fca6ea1SDimitry Andric   // At this point the target type should be a reference.
3092*0fca6ea1SDimitry Andric   if (!inner_value_type.CompareTypes(type.GetNonReferenceType()))
3093*0fca6ea1SDimitry Andric     return llvm::make_error<llvm::StringError>(
3094*0fca6ea1SDimitry Andric         "casted value doesn't match the desired type",
3095*0fca6ea1SDimitry Andric         llvm::inconvertibleErrorCode());
3096*0fca6ea1SDimitry Andric 
3097*0fca6ea1SDimitry Andric   return lldb::ValueObjectSP(inner_value->Cast(type.GetNonReferenceType()));
3098*0fca6ea1SDimitry Andric }
3099*0fca6ea1SDimitry Andric 
3100*0fca6ea1SDimitry Andric llvm::Expected<lldb::ValueObjectSP>
3101*0fca6ea1SDimitry Andric ValueObject::CastBaseToDerivedType(CompilerType type, uint64_t offset) {
3102*0fca6ea1SDimitry Andric   // Make sure the starting type and the target type are both valid for this
3103*0fca6ea1SDimitry Andric   // type of cast; otherwise return the shared pointer to the original
3104*0fca6ea1SDimitry Andric   // (unchanged) ValueObject.
3105*0fca6ea1SDimitry Andric   if (!type.IsPointerType() && !type.IsReferenceType())
3106*0fca6ea1SDimitry Andric     return llvm::make_error<llvm::StringError>(
3107*0fca6ea1SDimitry Andric         "Invalid target type: should be a pointer or a reference",
3108*0fca6ea1SDimitry Andric         llvm::inconvertibleErrorCode());
3109*0fca6ea1SDimitry Andric 
3110*0fca6ea1SDimitry Andric   CompilerType start_type = GetCompilerType();
3111*0fca6ea1SDimitry Andric   if (start_type.IsReferenceType())
3112*0fca6ea1SDimitry Andric     start_type = start_type.GetNonReferenceType();
3113*0fca6ea1SDimitry Andric 
3114*0fca6ea1SDimitry Andric   auto target_record_type =
3115*0fca6ea1SDimitry Andric       type.IsPointerType() ? type.GetPointeeType() : type.GetNonReferenceType();
3116*0fca6ea1SDimitry Andric   auto start_record_type =
3117*0fca6ea1SDimitry Andric       start_type.IsPointerType() ? start_type.GetPointeeType() : start_type;
3118*0fca6ea1SDimitry Andric 
3119*0fca6ea1SDimitry Andric   if (!target_record_type.IsRecordType() || !start_record_type.IsRecordType())
3120*0fca6ea1SDimitry Andric     return llvm::make_error<llvm::StringError>(
3121*0fca6ea1SDimitry Andric         "Underlying start & target types should be record types",
3122*0fca6ea1SDimitry Andric         llvm::inconvertibleErrorCode());
3123*0fca6ea1SDimitry Andric 
3124*0fca6ea1SDimitry Andric   if (target_record_type.CompareTypes(start_record_type))
3125*0fca6ea1SDimitry Andric     return llvm::make_error<llvm::StringError>(
3126*0fca6ea1SDimitry Andric         "Underlying start & target types should be different",
3127*0fca6ea1SDimitry Andric         llvm::inconvertibleErrorCode());
3128*0fca6ea1SDimitry Andric 
3129*0fca6ea1SDimitry Andric   CompilerType virtual_base;
3130*0fca6ea1SDimitry Andric   if (target_record_type.IsVirtualBase(start_record_type, &virtual_base)) {
3131*0fca6ea1SDimitry Andric     if (!virtual_base.IsValid())
3132*0fca6ea1SDimitry Andric       return llvm::make_error<llvm::StringError>(
3133*0fca6ea1SDimitry Andric           "virtual base should be valid", llvm::inconvertibleErrorCode());
3134*0fca6ea1SDimitry Andric     return llvm::make_error<llvm::StringError>(
3135*0fca6ea1SDimitry Andric         llvm::Twine("cannot cast " + start_type.TypeDescription() + " to " +
3136*0fca6ea1SDimitry Andric                     type.TypeDescription() + " via virtual base " +
3137*0fca6ea1SDimitry Andric                     virtual_base.TypeDescription()),
3138*0fca6ea1SDimitry Andric         llvm::inconvertibleErrorCode());
3139*0fca6ea1SDimitry Andric   }
3140*0fca6ea1SDimitry Andric 
3141*0fca6ea1SDimitry Andric   // Both the starting & target types are valid for the cast,  so we can
3142*0fca6ea1SDimitry Andric   // proceed with the cast.
3143*0fca6ea1SDimitry Andric 
3144*0fca6ea1SDimitry Andric   lldb::TargetSP target = GetTargetSP();
3145*0fca6ea1SDimitry Andric   auto pointer_type =
3146*0fca6ea1SDimitry Andric       type.IsPointerType() ? type : type.GetNonReferenceType().GetPointerType();
3147*0fca6ea1SDimitry Andric 
3148*0fca6ea1SDimitry Andric   uintptr_t addr =
3149*0fca6ea1SDimitry Andric       type.IsPointerType() ? GetValueAsUnsigned(0) : GetLoadAddress();
3150*0fca6ea1SDimitry Andric 
3151*0fca6ea1SDimitry Andric   llvm::StringRef name = "";
3152*0fca6ea1SDimitry Andric   ExecutionContext exe_ctx(target.get(), false);
3153*0fca6ea1SDimitry Andric   lldb::ValueObjectSP value = ValueObject::CreateValueObjectFromAddress(
3154*0fca6ea1SDimitry Andric       name, addr - offset, exe_ctx, pointer_type, /* do_deref */ false);
3155*0fca6ea1SDimitry Andric 
3156*0fca6ea1SDimitry Andric   if (type.IsPointerType())
3157*0fca6ea1SDimitry Andric     return value;
3158*0fca6ea1SDimitry Andric 
3159*0fca6ea1SDimitry Andric   // At this point the target type is a reference. Since `value` is a pointer,
3160*0fca6ea1SDimitry Andric   // it has to be dereferenced.
3161*0fca6ea1SDimitry Andric   Status error;
3162*0fca6ea1SDimitry Andric   return value->Dereference(error);
3163*0fca6ea1SDimitry Andric }
3164*0fca6ea1SDimitry Andric 
3165*0fca6ea1SDimitry Andric lldb::ValueObjectSP ValueObject::CastToBasicType(CompilerType type) {
3166*0fca6ea1SDimitry Andric   bool is_scalar = GetCompilerType().IsScalarType();
3167*0fca6ea1SDimitry Andric   bool is_enum = GetCompilerType().IsEnumerationType();
3168*0fca6ea1SDimitry Andric   bool is_pointer =
3169*0fca6ea1SDimitry Andric       GetCompilerType().IsPointerType() || GetCompilerType().IsNullPtrType();
3170*0fca6ea1SDimitry Andric   bool is_float = GetCompilerType().IsFloat();
3171*0fca6ea1SDimitry Andric   bool is_integer = GetCompilerType().IsInteger();
3172*0fca6ea1SDimitry Andric 
3173*0fca6ea1SDimitry Andric   if (!type.IsScalarType()) {
3174*0fca6ea1SDimitry Andric     m_error.SetErrorString("target type must be a scalar");
3175*0fca6ea1SDimitry Andric     return GetSP();
3176*0fca6ea1SDimitry Andric   }
3177*0fca6ea1SDimitry Andric 
3178*0fca6ea1SDimitry Andric   if (!is_scalar && !is_enum && !is_pointer) {
3179*0fca6ea1SDimitry Andric     m_error.SetErrorString("argument must be a scalar, enum, or pointer");
3180*0fca6ea1SDimitry Andric     return GetSP();
3181*0fca6ea1SDimitry Andric   }
3182*0fca6ea1SDimitry Andric 
3183*0fca6ea1SDimitry Andric   lldb::TargetSP target = GetTargetSP();
3184*0fca6ea1SDimitry Andric   uint64_t type_byte_size = 0;
3185*0fca6ea1SDimitry Andric   uint64_t val_byte_size = 0;
3186*0fca6ea1SDimitry Andric   if (auto temp = type.GetByteSize(target.get()))
3187*0fca6ea1SDimitry Andric     type_byte_size = temp.value();
3188*0fca6ea1SDimitry Andric   if (auto temp = GetCompilerType().GetByteSize(target.get()))
3189*0fca6ea1SDimitry Andric     val_byte_size = temp.value();
3190*0fca6ea1SDimitry Andric 
3191*0fca6ea1SDimitry Andric   if (is_pointer) {
3192*0fca6ea1SDimitry Andric     if (!type.IsInteger() && !type.IsBoolean()) {
3193*0fca6ea1SDimitry Andric       m_error.SetErrorString("target type must be an integer or boolean");
3194*0fca6ea1SDimitry Andric       return GetSP();
3195*0fca6ea1SDimitry Andric     }
3196*0fca6ea1SDimitry Andric     if (!type.IsBoolean() && type_byte_size < val_byte_size) {
3197*0fca6ea1SDimitry Andric       m_error.SetErrorString(
3198*0fca6ea1SDimitry Andric           "target type cannot be smaller than the pointer type");
3199*0fca6ea1SDimitry Andric       return GetSP();
3200*0fca6ea1SDimitry Andric     }
3201*0fca6ea1SDimitry Andric   }
3202*0fca6ea1SDimitry Andric 
3203*0fca6ea1SDimitry Andric   if (type.IsBoolean()) {
3204*0fca6ea1SDimitry Andric     if (!is_scalar || is_integer)
3205*0fca6ea1SDimitry Andric       return ValueObject::CreateValueObjectFromBool(
3206*0fca6ea1SDimitry Andric           target, GetValueAsUnsigned(0) != 0, "result");
3207*0fca6ea1SDimitry Andric     else if (is_scalar && is_float) {
3208*0fca6ea1SDimitry Andric       auto float_value_or_err = GetValueAsAPFloat();
3209*0fca6ea1SDimitry Andric       if (float_value_or_err)
3210*0fca6ea1SDimitry Andric         return ValueObject::CreateValueObjectFromBool(
3211*0fca6ea1SDimitry Andric             target, !float_value_or_err->isZero(), "result");
3212*0fca6ea1SDimitry Andric       else {
3213*0fca6ea1SDimitry Andric         m_error.SetErrorStringWithFormat(
3214*0fca6ea1SDimitry Andric             "cannot get value as APFloat: %s",
3215*0fca6ea1SDimitry Andric             llvm::toString(float_value_or_err.takeError()).c_str());
3216*0fca6ea1SDimitry Andric         return GetSP();
3217*0fca6ea1SDimitry Andric       }
3218*0fca6ea1SDimitry Andric     }
3219*0fca6ea1SDimitry Andric   }
3220*0fca6ea1SDimitry Andric 
3221*0fca6ea1SDimitry Andric   if (type.IsInteger()) {
3222*0fca6ea1SDimitry Andric     if (!is_scalar || is_integer) {
3223*0fca6ea1SDimitry Andric       auto int_value_or_err = GetValueAsAPSInt();
3224*0fca6ea1SDimitry Andric       if (int_value_or_err) {
3225*0fca6ea1SDimitry Andric         // Get the value as APSInt and extend or truncate it to the requested
3226*0fca6ea1SDimitry Andric         // size.
3227*0fca6ea1SDimitry Andric         llvm::APSInt ext =
3228*0fca6ea1SDimitry Andric             int_value_or_err->extOrTrunc(type_byte_size * CHAR_BIT);
3229*0fca6ea1SDimitry Andric         return ValueObject::CreateValueObjectFromAPInt(target, ext, type,
3230*0fca6ea1SDimitry Andric                                                        "result");
3231*0fca6ea1SDimitry Andric       } else {
3232*0fca6ea1SDimitry Andric         m_error.SetErrorStringWithFormat(
3233*0fca6ea1SDimitry Andric             "cannot get value as APSInt: %s",
3234*0fca6ea1SDimitry Andric             llvm::toString(int_value_or_err.takeError()).c_str());
3235*0fca6ea1SDimitry Andric         ;
3236*0fca6ea1SDimitry Andric         return GetSP();
3237*0fca6ea1SDimitry Andric       }
3238*0fca6ea1SDimitry Andric     } else if (is_scalar && is_float) {
3239*0fca6ea1SDimitry Andric       llvm::APSInt integer(type_byte_size * CHAR_BIT, !type.IsSigned());
3240*0fca6ea1SDimitry Andric       bool is_exact;
3241*0fca6ea1SDimitry Andric       auto float_value_or_err = GetValueAsAPFloat();
3242*0fca6ea1SDimitry Andric       if (float_value_or_err) {
3243*0fca6ea1SDimitry Andric         llvm::APFloatBase::opStatus status =
3244*0fca6ea1SDimitry Andric             float_value_or_err->convertToInteger(
3245*0fca6ea1SDimitry Andric                 integer, llvm::APFloat::rmTowardZero, &is_exact);
3246*0fca6ea1SDimitry Andric 
3247*0fca6ea1SDimitry Andric         // Casting floating point values that are out of bounds of the target
3248*0fca6ea1SDimitry Andric         // type is undefined behaviour.
3249*0fca6ea1SDimitry Andric         if (status & llvm::APFloatBase::opInvalidOp) {
3250*0fca6ea1SDimitry Andric           m_error.SetErrorStringWithFormat(
3251*0fca6ea1SDimitry Andric               "invalid type cast detected: %s",
3252*0fca6ea1SDimitry Andric               llvm::toString(float_value_or_err.takeError()).c_str());
3253*0fca6ea1SDimitry Andric           return GetSP();
3254*0fca6ea1SDimitry Andric         }
3255*0fca6ea1SDimitry Andric         return ValueObject::CreateValueObjectFromAPInt(target, integer, type,
3256*0fca6ea1SDimitry Andric                                                        "result");
3257*0fca6ea1SDimitry Andric       }
3258*0fca6ea1SDimitry Andric     }
3259*0fca6ea1SDimitry Andric   }
3260*0fca6ea1SDimitry Andric 
3261*0fca6ea1SDimitry Andric   if (type.IsFloat()) {
3262*0fca6ea1SDimitry Andric     if (!is_scalar) {
3263*0fca6ea1SDimitry Andric       auto int_value_or_err = GetValueAsAPSInt();
3264*0fca6ea1SDimitry Andric       if (int_value_or_err) {
3265*0fca6ea1SDimitry Andric         llvm::APSInt ext =
3266*0fca6ea1SDimitry Andric             int_value_or_err->extOrTrunc(type_byte_size * CHAR_BIT);
3267*0fca6ea1SDimitry Andric         Scalar scalar_int(ext);
3268*0fca6ea1SDimitry Andric         llvm::APFloat f = scalar_int.CreateAPFloatFromAPSInt(
3269*0fca6ea1SDimitry Andric             type.GetCanonicalType().GetBasicTypeEnumeration());
3270*0fca6ea1SDimitry Andric         return ValueObject::CreateValueObjectFromAPFloat(target, f, type,
3271*0fca6ea1SDimitry Andric                                                          "result");
3272*0fca6ea1SDimitry Andric       } else {
3273*0fca6ea1SDimitry Andric         m_error.SetErrorStringWithFormat(
3274*0fca6ea1SDimitry Andric             "cannot get value as APSInt: %s",
3275*0fca6ea1SDimitry Andric             llvm::toString(int_value_or_err.takeError()).c_str());
3276*0fca6ea1SDimitry Andric         return GetSP();
3277*0fca6ea1SDimitry Andric       }
3278*0fca6ea1SDimitry Andric     } else {
3279*0fca6ea1SDimitry Andric       if (is_integer) {
3280*0fca6ea1SDimitry Andric         auto int_value_or_err = GetValueAsAPSInt();
3281*0fca6ea1SDimitry Andric         if (int_value_or_err) {
3282*0fca6ea1SDimitry Andric           Scalar scalar_int(*int_value_or_err);
3283*0fca6ea1SDimitry Andric           llvm::APFloat f = scalar_int.CreateAPFloatFromAPSInt(
3284*0fca6ea1SDimitry Andric               type.GetCanonicalType().GetBasicTypeEnumeration());
3285*0fca6ea1SDimitry Andric           return ValueObject::CreateValueObjectFromAPFloat(target, f, type,
3286*0fca6ea1SDimitry Andric                                                            "result");
3287*0fca6ea1SDimitry Andric         } else {
3288*0fca6ea1SDimitry Andric           m_error.SetErrorStringWithFormat(
3289*0fca6ea1SDimitry Andric               "cannot get value as APSInt: %s",
3290*0fca6ea1SDimitry Andric               llvm::toString(int_value_or_err.takeError()).c_str());
3291*0fca6ea1SDimitry Andric           return GetSP();
3292*0fca6ea1SDimitry Andric         }
3293*0fca6ea1SDimitry Andric       }
3294*0fca6ea1SDimitry Andric       if (is_float) {
3295*0fca6ea1SDimitry Andric         auto float_value_or_err = GetValueAsAPFloat();
3296*0fca6ea1SDimitry Andric         if (float_value_or_err) {
3297*0fca6ea1SDimitry Andric           Scalar scalar_float(*float_value_or_err);
3298*0fca6ea1SDimitry Andric           llvm::APFloat f = scalar_float.CreateAPFloatFromAPFloat(
3299*0fca6ea1SDimitry Andric               type.GetCanonicalType().GetBasicTypeEnumeration());
3300*0fca6ea1SDimitry Andric           return ValueObject::CreateValueObjectFromAPFloat(target, f, type,
3301*0fca6ea1SDimitry Andric                                                            "result");
3302*0fca6ea1SDimitry Andric         } else {
3303*0fca6ea1SDimitry Andric           m_error.SetErrorStringWithFormat(
3304*0fca6ea1SDimitry Andric               "cannot get value as APFloat: %s",
3305*0fca6ea1SDimitry Andric               llvm::toString(float_value_or_err.takeError()).c_str());
3306*0fca6ea1SDimitry Andric           return GetSP();
3307*0fca6ea1SDimitry Andric         }
3308*0fca6ea1SDimitry Andric       }
3309*0fca6ea1SDimitry Andric     }
3310*0fca6ea1SDimitry Andric   }
3311*0fca6ea1SDimitry Andric 
3312*0fca6ea1SDimitry Andric   m_error.SetErrorString("Unable to perform requested cast");
3313*0fca6ea1SDimitry Andric   return GetSP();
3314*0fca6ea1SDimitry Andric }
3315*0fca6ea1SDimitry Andric 
3316*0fca6ea1SDimitry Andric lldb::ValueObjectSP ValueObject::CastToEnumType(CompilerType type) {
3317*0fca6ea1SDimitry Andric   bool is_enum = GetCompilerType().IsEnumerationType();
3318*0fca6ea1SDimitry Andric   bool is_integer = GetCompilerType().IsInteger();
3319*0fca6ea1SDimitry Andric   bool is_float = GetCompilerType().IsFloat();
3320*0fca6ea1SDimitry Andric 
3321*0fca6ea1SDimitry Andric   if (!is_enum && !is_integer && !is_float) {
3322*0fca6ea1SDimitry Andric     m_error.SetErrorString("argument must be an integer, a float, or an enum");
3323*0fca6ea1SDimitry Andric     return GetSP();
3324*0fca6ea1SDimitry Andric   }
3325*0fca6ea1SDimitry Andric 
3326*0fca6ea1SDimitry Andric   if (!type.IsEnumerationType()) {
3327*0fca6ea1SDimitry Andric     m_error.SetErrorString("target type must be an enum");
3328*0fca6ea1SDimitry Andric     return GetSP();
3329*0fca6ea1SDimitry Andric   }
3330*0fca6ea1SDimitry Andric 
3331*0fca6ea1SDimitry Andric   lldb::TargetSP target = GetTargetSP();
3332*0fca6ea1SDimitry Andric   uint64_t byte_size = 0;
3333*0fca6ea1SDimitry Andric   if (auto temp = type.GetByteSize(target.get()))
3334*0fca6ea1SDimitry Andric     byte_size = temp.value();
3335*0fca6ea1SDimitry Andric 
3336*0fca6ea1SDimitry Andric   if (is_float) {
3337*0fca6ea1SDimitry Andric     llvm::APSInt integer(byte_size * CHAR_BIT, !type.IsSigned());
3338*0fca6ea1SDimitry Andric     bool is_exact;
3339*0fca6ea1SDimitry Andric     auto value_or_err = GetValueAsAPFloat();
3340*0fca6ea1SDimitry Andric     if (value_or_err) {
3341*0fca6ea1SDimitry Andric       llvm::APFloatBase::opStatus status = value_or_err->convertToInteger(
3342*0fca6ea1SDimitry Andric           integer, llvm::APFloat::rmTowardZero, &is_exact);
3343*0fca6ea1SDimitry Andric 
3344*0fca6ea1SDimitry Andric       // Casting floating point values that are out of bounds of the target
3345*0fca6ea1SDimitry Andric       // type is undefined behaviour.
3346*0fca6ea1SDimitry Andric       if (status & llvm::APFloatBase::opInvalidOp) {
3347*0fca6ea1SDimitry Andric         m_error.SetErrorStringWithFormat(
3348*0fca6ea1SDimitry Andric             "invalid type cast detected: %s",
3349*0fca6ea1SDimitry Andric             llvm::toString(value_or_err.takeError()).c_str());
3350*0fca6ea1SDimitry Andric         return GetSP();
3351*0fca6ea1SDimitry Andric       }
3352*0fca6ea1SDimitry Andric       return ValueObject::CreateValueObjectFromAPInt(target, integer, type,
3353*0fca6ea1SDimitry Andric                                                      "result");
3354*0fca6ea1SDimitry Andric     } else {
3355*0fca6ea1SDimitry Andric       m_error.SetErrorString("cannot get value as APFloat");
3356*0fca6ea1SDimitry Andric       return GetSP();
3357*0fca6ea1SDimitry Andric     }
3358*0fca6ea1SDimitry Andric   } else {
3359*0fca6ea1SDimitry Andric     // Get the value as APSInt and extend or truncate it to the requested size.
3360*0fca6ea1SDimitry Andric     auto value_or_err = GetValueAsAPSInt();
3361*0fca6ea1SDimitry Andric     if (value_or_err) {
3362*0fca6ea1SDimitry Andric       llvm::APSInt ext = value_or_err->extOrTrunc(byte_size * CHAR_BIT);
3363*0fca6ea1SDimitry Andric       return ValueObject::CreateValueObjectFromAPInt(target, ext, type,
3364*0fca6ea1SDimitry Andric                                                      "result");
3365*0fca6ea1SDimitry Andric     } else {
3366*0fca6ea1SDimitry Andric       m_error.SetErrorStringWithFormat(
3367*0fca6ea1SDimitry Andric           "cannot get value as APSInt: %s",
3368*0fca6ea1SDimitry Andric           llvm::toString(value_or_err.takeError()).c_str());
3369*0fca6ea1SDimitry Andric       return GetSP();
3370*0fca6ea1SDimitry Andric     }
3371*0fca6ea1SDimitry Andric   }
3372*0fca6ea1SDimitry Andric   m_error.SetErrorString("Cannot perform requested cast");
3373*0fca6ea1SDimitry Andric   return GetSP();
3374*0fca6ea1SDimitry Andric }
3375*0fca6ea1SDimitry Andric 
3376fe6060f1SDimitry Andric ValueObject::EvaluationPoint::EvaluationPoint() : m_mod_id(), m_exe_ctx_ref() {}
33770b57cec5SDimitry Andric 
33780b57cec5SDimitry Andric ValueObject::EvaluationPoint::EvaluationPoint(ExecutionContextScope *exe_scope,
33790b57cec5SDimitry Andric                                               bool use_selected)
338081ad6265SDimitry Andric     : m_mod_id(), m_exe_ctx_ref() {
33810b57cec5SDimitry Andric   ExecutionContext exe_ctx(exe_scope);
33820b57cec5SDimitry Andric   TargetSP target_sp(exe_ctx.GetTargetSP());
33830b57cec5SDimitry Andric   if (target_sp) {
33840b57cec5SDimitry Andric     m_exe_ctx_ref.SetTargetSP(target_sp);
33850b57cec5SDimitry Andric     ProcessSP process_sp(exe_ctx.GetProcessSP());
33860b57cec5SDimitry Andric     if (!process_sp)
33870b57cec5SDimitry Andric       process_sp = target_sp->GetProcessSP();
33880b57cec5SDimitry Andric 
33890b57cec5SDimitry Andric     if (process_sp) {
33900b57cec5SDimitry Andric       m_mod_id = process_sp->GetModID();
33910b57cec5SDimitry Andric       m_exe_ctx_ref.SetProcessSP(process_sp);
33920b57cec5SDimitry Andric 
33930b57cec5SDimitry Andric       ThreadSP thread_sp(exe_ctx.GetThreadSP());
33940b57cec5SDimitry Andric 
33950b57cec5SDimitry Andric       if (!thread_sp) {
33960b57cec5SDimitry Andric         if (use_selected)
33970b57cec5SDimitry Andric           thread_sp = process_sp->GetThreadList().GetSelectedThread();
33980b57cec5SDimitry Andric       }
33990b57cec5SDimitry Andric 
34000b57cec5SDimitry Andric       if (thread_sp) {
34010b57cec5SDimitry Andric         m_exe_ctx_ref.SetThreadSP(thread_sp);
34020b57cec5SDimitry Andric 
34030b57cec5SDimitry Andric         StackFrameSP frame_sp(exe_ctx.GetFrameSP());
34040b57cec5SDimitry Andric         if (!frame_sp) {
34050b57cec5SDimitry Andric           if (use_selected)
340606c3fb27SDimitry Andric             frame_sp = thread_sp->GetSelectedFrame(DoNoSelectMostRelevantFrame);
34070b57cec5SDimitry Andric         }
34080b57cec5SDimitry Andric         if (frame_sp)
34090b57cec5SDimitry Andric           m_exe_ctx_ref.SetFrameSP(frame_sp);
34100b57cec5SDimitry Andric       }
34110b57cec5SDimitry Andric     }
34120b57cec5SDimitry Andric   }
34130b57cec5SDimitry Andric }
34140b57cec5SDimitry Andric 
34150b57cec5SDimitry Andric ValueObject::EvaluationPoint::EvaluationPoint(
34160b57cec5SDimitry Andric     const ValueObject::EvaluationPoint &rhs)
341781ad6265SDimitry Andric     : m_mod_id(), m_exe_ctx_ref(rhs.m_exe_ctx_ref) {}
34180b57cec5SDimitry Andric 
3419fe6060f1SDimitry Andric ValueObject::EvaluationPoint::~EvaluationPoint() = default;
34200b57cec5SDimitry Andric 
34210b57cec5SDimitry Andric // This function checks the EvaluationPoint against the current process state.
34220b57cec5SDimitry Andric // If the current state matches the evaluation point, or the evaluation point
34230b57cec5SDimitry Andric // is already invalid, then we return false, meaning "no change".  If the
34240b57cec5SDimitry Andric // current state is different, we update our state, and return true meaning
34250b57cec5SDimitry Andric // "yes, change".  If we did see a change, we also set m_needs_update to true,
34260b57cec5SDimitry Andric // so future calls to NeedsUpdate will return true. exe_scope will be set to
34270b57cec5SDimitry Andric // the current execution context scope.
34280b57cec5SDimitry Andric 
34290b57cec5SDimitry Andric bool ValueObject::EvaluationPoint::SyncWithProcessState(
34300b57cec5SDimitry Andric     bool accept_invalid_exe_ctx) {
34310b57cec5SDimitry Andric   // Start with the target, if it is NULL, then we're obviously not going to
34320b57cec5SDimitry Andric   // get any further:
34330b57cec5SDimitry Andric   const bool thread_and_frame_only_if_stopped = true;
34340b57cec5SDimitry Andric   ExecutionContext exe_ctx(
34350b57cec5SDimitry Andric       m_exe_ctx_ref.Lock(thread_and_frame_only_if_stopped));
34360b57cec5SDimitry Andric 
34370b57cec5SDimitry Andric   if (exe_ctx.GetTargetPtr() == nullptr)
34380b57cec5SDimitry Andric     return false;
34390b57cec5SDimitry Andric 
34400b57cec5SDimitry Andric   // If we don't have a process nothing can change.
34410b57cec5SDimitry Andric   Process *process = exe_ctx.GetProcessPtr();
34420b57cec5SDimitry Andric   if (process == nullptr)
34430b57cec5SDimitry Andric     return false;
34440b57cec5SDimitry Andric 
34450b57cec5SDimitry Andric   // If our stop id is the current stop ID, nothing has changed:
34460b57cec5SDimitry Andric   ProcessModID current_mod_id = process->GetModID();
34470b57cec5SDimitry Andric 
34480b57cec5SDimitry Andric   // If the current stop id is 0, either we haven't run yet, or the process
34490b57cec5SDimitry Andric   // state has been cleared. In either case, we aren't going to be able to sync
34500b57cec5SDimitry Andric   // with the process state.
34510b57cec5SDimitry Andric   if (current_mod_id.GetStopID() == 0)
34520b57cec5SDimitry Andric     return false;
34530b57cec5SDimitry Andric 
34540b57cec5SDimitry Andric   bool changed = false;
34550b57cec5SDimitry Andric   const bool was_valid = m_mod_id.IsValid();
34560b57cec5SDimitry Andric   if (was_valid) {
34570b57cec5SDimitry Andric     if (m_mod_id == current_mod_id) {
34580b57cec5SDimitry Andric       // Everything is already up to date in this object, no need to update the
34590b57cec5SDimitry Andric       // execution context scope.
34600b57cec5SDimitry Andric       changed = false;
34610b57cec5SDimitry Andric     } else {
34620b57cec5SDimitry Andric       m_mod_id = current_mod_id;
34630b57cec5SDimitry Andric       m_needs_update = true;
34640b57cec5SDimitry Andric       changed = true;
34650b57cec5SDimitry Andric     }
34660b57cec5SDimitry Andric   }
34670b57cec5SDimitry Andric 
34680b57cec5SDimitry Andric   // Now re-look up the thread and frame in case the underlying objects have
34690b57cec5SDimitry Andric   // gone away & been recreated. That way we'll be sure to return a valid
34700b57cec5SDimitry Andric   // exe_scope. If we used to have a thread or a frame but can't find it
34710b57cec5SDimitry Andric   // anymore, then mark ourselves as invalid.
34720b57cec5SDimitry Andric 
34730b57cec5SDimitry Andric   if (!accept_invalid_exe_ctx) {
34740b57cec5SDimitry Andric     if (m_exe_ctx_ref.HasThreadRef()) {
34750b57cec5SDimitry Andric       ThreadSP thread_sp(m_exe_ctx_ref.GetThreadSP());
34760b57cec5SDimitry Andric       if (thread_sp) {
34770b57cec5SDimitry Andric         if (m_exe_ctx_ref.HasFrameRef()) {
34780b57cec5SDimitry Andric           StackFrameSP frame_sp(m_exe_ctx_ref.GetFrameSP());
34790b57cec5SDimitry Andric           if (!frame_sp) {
34800b57cec5SDimitry Andric             // We used to have a frame, but now it is gone
34810b57cec5SDimitry Andric             SetInvalid();
34820b57cec5SDimitry Andric             changed = was_valid;
34830b57cec5SDimitry Andric           }
34840b57cec5SDimitry Andric         }
34850b57cec5SDimitry Andric       } else {
34860b57cec5SDimitry Andric         // We used to have a thread, but now it is gone
34870b57cec5SDimitry Andric         SetInvalid();
34880b57cec5SDimitry Andric         changed = was_valid;
34890b57cec5SDimitry Andric       }
34900b57cec5SDimitry Andric     }
34910b57cec5SDimitry Andric   }
34920b57cec5SDimitry Andric 
34930b57cec5SDimitry Andric   return changed;
34940b57cec5SDimitry Andric }
34950b57cec5SDimitry Andric 
34960b57cec5SDimitry Andric void ValueObject::EvaluationPoint::SetUpdated() {
34970b57cec5SDimitry Andric   ProcessSP process_sp(m_exe_ctx_ref.GetProcessSP());
34980b57cec5SDimitry Andric   if (process_sp)
34990b57cec5SDimitry Andric     m_mod_id = process_sp->GetModID();
35000b57cec5SDimitry Andric   m_needs_update = false;
35010b57cec5SDimitry Andric }
35020b57cec5SDimitry Andric 
35030b57cec5SDimitry Andric void ValueObject::ClearUserVisibleData(uint32_t clear_mask) {
35040b57cec5SDimitry Andric   if ((clear_mask & eClearUserVisibleDataItemsValue) ==
35050b57cec5SDimitry Andric       eClearUserVisibleDataItemsValue)
35060b57cec5SDimitry Andric     m_value_str.clear();
35070b57cec5SDimitry Andric 
35080b57cec5SDimitry Andric   if ((clear_mask & eClearUserVisibleDataItemsLocation) ==
35090b57cec5SDimitry Andric       eClearUserVisibleDataItemsLocation)
35100b57cec5SDimitry Andric     m_location_str.clear();
35110b57cec5SDimitry Andric 
35120b57cec5SDimitry Andric   if ((clear_mask & eClearUserVisibleDataItemsSummary) ==
35130b57cec5SDimitry Andric       eClearUserVisibleDataItemsSummary)
35140b57cec5SDimitry Andric     m_summary_str.clear();
35150b57cec5SDimitry Andric 
35160b57cec5SDimitry Andric   if ((clear_mask & eClearUserVisibleDataItemsDescription) ==
35170b57cec5SDimitry Andric       eClearUserVisibleDataItemsDescription)
35180b57cec5SDimitry Andric     m_object_desc_str.clear();
35190b57cec5SDimitry Andric 
35200b57cec5SDimitry Andric   if ((clear_mask & eClearUserVisibleDataItemsSyntheticChildren) ==
35210b57cec5SDimitry Andric       eClearUserVisibleDataItemsSyntheticChildren) {
35220b57cec5SDimitry Andric     if (m_synthetic_value)
35230b57cec5SDimitry Andric       m_synthetic_value = nullptr;
35240b57cec5SDimitry Andric   }
35250b57cec5SDimitry Andric }
35260b57cec5SDimitry Andric 
35270b57cec5SDimitry Andric SymbolContextScope *ValueObject::GetSymbolContextScope() {
35280b57cec5SDimitry Andric   if (m_parent) {
35290b57cec5SDimitry Andric     if (!m_parent->IsPointerOrReferenceType())
35300b57cec5SDimitry Andric       return m_parent->GetSymbolContextScope();
35310b57cec5SDimitry Andric   }
35320b57cec5SDimitry Andric   return nullptr;
35330b57cec5SDimitry Andric }
35340b57cec5SDimitry Andric 
35350b57cec5SDimitry Andric lldb::ValueObjectSP
35360b57cec5SDimitry Andric ValueObject::CreateValueObjectFromExpression(llvm::StringRef name,
35370b57cec5SDimitry Andric                                              llvm::StringRef expression,
35380b57cec5SDimitry Andric                                              const ExecutionContext &exe_ctx) {
35390b57cec5SDimitry Andric   return CreateValueObjectFromExpression(name, expression, exe_ctx,
35400b57cec5SDimitry Andric                                          EvaluateExpressionOptions());
35410b57cec5SDimitry Andric }
35420b57cec5SDimitry Andric 
35430b57cec5SDimitry Andric lldb::ValueObjectSP ValueObject::CreateValueObjectFromExpression(
35440b57cec5SDimitry Andric     llvm::StringRef name, llvm::StringRef expression,
35450b57cec5SDimitry Andric     const ExecutionContext &exe_ctx, const EvaluateExpressionOptions &options) {
35460b57cec5SDimitry Andric   lldb::ValueObjectSP retval_sp;
35470b57cec5SDimitry Andric   lldb::TargetSP target_sp(exe_ctx.GetTargetSP());
35480b57cec5SDimitry Andric   if (!target_sp)
35490b57cec5SDimitry Andric     return retval_sp;
35500b57cec5SDimitry Andric   if (expression.empty())
35510b57cec5SDimitry Andric     return retval_sp;
35520b57cec5SDimitry Andric   target_sp->EvaluateExpression(expression, exe_ctx.GetFrameSP().get(),
35530b57cec5SDimitry Andric                                 retval_sp, options);
35540b57cec5SDimitry Andric   if (retval_sp && !name.empty())
35550b57cec5SDimitry Andric     retval_sp->SetName(ConstString(name));
35560b57cec5SDimitry Andric   return retval_sp;
35570b57cec5SDimitry Andric }
35580b57cec5SDimitry Andric 
35590b57cec5SDimitry Andric lldb::ValueObjectSP ValueObject::CreateValueObjectFromAddress(
35600b57cec5SDimitry Andric     llvm::StringRef name, uint64_t address, const ExecutionContext &exe_ctx,
3561*0fca6ea1SDimitry Andric     CompilerType type, bool do_deref) {
35620b57cec5SDimitry Andric   if (type) {
35630b57cec5SDimitry Andric     CompilerType pointer_type(type.GetPointerType());
3564*0fca6ea1SDimitry Andric     if (!do_deref)
3565*0fca6ea1SDimitry Andric       pointer_type = type;
35660b57cec5SDimitry Andric     if (pointer_type) {
35670b57cec5SDimitry Andric       lldb::DataBufferSP buffer(
35680b57cec5SDimitry Andric           new lldb_private::DataBufferHeap(&address, sizeof(lldb::addr_t)));
35690b57cec5SDimitry Andric       lldb::ValueObjectSP ptr_result_valobj_sp(ValueObjectConstResult::Create(
35700b57cec5SDimitry Andric           exe_ctx.GetBestExecutionContextScope(), pointer_type,
35710b57cec5SDimitry Andric           ConstString(name), buffer, exe_ctx.GetByteOrder(),
35720b57cec5SDimitry Andric           exe_ctx.GetAddressByteSize()));
35730b57cec5SDimitry Andric       if (ptr_result_valobj_sp) {
3574*0fca6ea1SDimitry Andric         if (do_deref)
35750b57cec5SDimitry Andric           ptr_result_valobj_sp->GetValue().SetValueType(
3576fe6060f1SDimitry Andric               Value::ValueType::LoadAddress);
35770b57cec5SDimitry Andric         Status err;
3578*0fca6ea1SDimitry Andric         if (do_deref)
35790b57cec5SDimitry Andric           ptr_result_valobj_sp = ptr_result_valobj_sp->Dereference(err);
35800b57cec5SDimitry Andric         if (ptr_result_valobj_sp && !name.empty())
35810b57cec5SDimitry Andric           ptr_result_valobj_sp->SetName(ConstString(name));
35820b57cec5SDimitry Andric       }
35830b57cec5SDimitry Andric       return ptr_result_valobj_sp;
35840b57cec5SDimitry Andric     }
35850b57cec5SDimitry Andric   }
35860b57cec5SDimitry Andric   return lldb::ValueObjectSP();
35870b57cec5SDimitry Andric }
35880b57cec5SDimitry Andric 
35890b57cec5SDimitry Andric lldb::ValueObjectSP ValueObject::CreateValueObjectFromData(
35900b57cec5SDimitry Andric     llvm::StringRef name, const DataExtractor &data,
35910b57cec5SDimitry Andric     const ExecutionContext &exe_ctx, CompilerType type) {
35920b57cec5SDimitry Andric   lldb::ValueObjectSP new_value_sp;
35930b57cec5SDimitry Andric   new_value_sp = ValueObjectConstResult::Create(
35940b57cec5SDimitry Andric       exe_ctx.GetBestExecutionContextScope(), type, ConstString(name), data,
35950b57cec5SDimitry Andric       LLDB_INVALID_ADDRESS);
35960b57cec5SDimitry Andric   new_value_sp->SetAddressTypeOfChildren(eAddressTypeLoad);
35970b57cec5SDimitry Andric   if (new_value_sp && !name.empty())
35980b57cec5SDimitry Andric     new_value_sp->SetName(ConstString(name));
35990b57cec5SDimitry Andric   return new_value_sp;
36000b57cec5SDimitry Andric }
36010b57cec5SDimitry Andric 
3602*0fca6ea1SDimitry Andric lldb::ValueObjectSP
3603*0fca6ea1SDimitry Andric ValueObject::CreateValueObjectFromAPInt(lldb::TargetSP target,
3604*0fca6ea1SDimitry Andric                                         const llvm::APInt &v, CompilerType type,
3605*0fca6ea1SDimitry Andric                                         llvm::StringRef name) {
3606*0fca6ea1SDimitry Andric   ExecutionContext exe_ctx(target.get(), false);
3607*0fca6ea1SDimitry Andric   uint64_t byte_size = 0;
3608*0fca6ea1SDimitry Andric   if (auto temp = type.GetByteSize(target.get()))
3609*0fca6ea1SDimitry Andric     byte_size = temp.value();
3610*0fca6ea1SDimitry Andric   lldb::DataExtractorSP data_sp = std::make_shared<DataExtractor>(
3611*0fca6ea1SDimitry Andric       reinterpret_cast<const void *>(v.getRawData()), byte_size,
3612*0fca6ea1SDimitry Andric       exe_ctx.GetByteOrder(), exe_ctx.GetAddressByteSize());
3613*0fca6ea1SDimitry Andric   return ValueObject::CreateValueObjectFromData(name, *data_sp, exe_ctx, type);
3614*0fca6ea1SDimitry Andric }
3615*0fca6ea1SDimitry Andric 
3616*0fca6ea1SDimitry Andric lldb::ValueObjectSP ValueObject::CreateValueObjectFromAPFloat(
3617*0fca6ea1SDimitry Andric     lldb::TargetSP target, const llvm::APFloat &v, CompilerType type,
3618*0fca6ea1SDimitry Andric     llvm::StringRef name) {
3619*0fca6ea1SDimitry Andric   return CreateValueObjectFromAPInt(target, v.bitcastToAPInt(), type, name);
3620*0fca6ea1SDimitry Andric }
3621*0fca6ea1SDimitry Andric 
3622*0fca6ea1SDimitry Andric lldb::ValueObjectSP
3623*0fca6ea1SDimitry Andric ValueObject::CreateValueObjectFromBool(lldb::TargetSP target, bool value,
3624*0fca6ea1SDimitry Andric                                        llvm::StringRef name) {
3625*0fca6ea1SDimitry Andric   CompilerType target_type;
3626*0fca6ea1SDimitry Andric   if (target) {
3627*0fca6ea1SDimitry Andric     for (auto type_system_sp : target->GetScratchTypeSystems())
3628*0fca6ea1SDimitry Andric       if (auto compiler_type =
3629*0fca6ea1SDimitry Andric               type_system_sp->GetBasicTypeFromAST(lldb::eBasicTypeBool)) {
3630*0fca6ea1SDimitry Andric         target_type = compiler_type;
3631*0fca6ea1SDimitry Andric         break;
3632*0fca6ea1SDimitry Andric       }
3633*0fca6ea1SDimitry Andric   }
3634*0fca6ea1SDimitry Andric   ExecutionContext exe_ctx(target.get(), false);
3635*0fca6ea1SDimitry Andric   uint64_t byte_size = 0;
3636*0fca6ea1SDimitry Andric   if (auto temp = target_type.GetByteSize(target.get()))
3637*0fca6ea1SDimitry Andric     byte_size = temp.value();
3638*0fca6ea1SDimitry Andric   lldb::DataExtractorSP data_sp = std::make_shared<DataExtractor>(
3639*0fca6ea1SDimitry Andric       reinterpret_cast<const void *>(&value), byte_size, exe_ctx.GetByteOrder(),
3640*0fca6ea1SDimitry Andric       exe_ctx.GetAddressByteSize());
3641*0fca6ea1SDimitry Andric   return ValueObject::CreateValueObjectFromData(name, *data_sp, exe_ctx,
3642*0fca6ea1SDimitry Andric                                                 target_type);
3643*0fca6ea1SDimitry Andric }
3644*0fca6ea1SDimitry Andric 
3645*0fca6ea1SDimitry Andric lldb::ValueObjectSP ValueObject::CreateValueObjectFromNullptr(
3646*0fca6ea1SDimitry Andric     lldb::TargetSP target, CompilerType type, llvm::StringRef name) {
3647*0fca6ea1SDimitry Andric   if (!type.IsNullPtrType()) {
3648*0fca6ea1SDimitry Andric     lldb::ValueObjectSP ret_val;
3649*0fca6ea1SDimitry Andric     return ret_val;
3650*0fca6ea1SDimitry Andric   }
3651*0fca6ea1SDimitry Andric   uintptr_t zero = 0;
3652*0fca6ea1SDimitry Andric   ExecutionContext exe_ctx(target.get(), false);
3653*0fca6ea1SDimitry Andric   uint64_t byte_size = 0;
3654*0fca6ea1SDimitry Andric   if (auto temp = type.GetByteSize(target.get()))
3655*0fca6ea1SDimitry Andric     byte_size = temp.value();
3656*0fca6ea1SDimitry Andric   lldb::DataExtractorSP data_sp = std::make_shared<DataExtractor>(
3657*0fca6ea1SDimitry Andric       reinterpret_cast<const void *>(zero), byte_size, exe_ctx.GetByteOrder(),
3658*0fca6ea1SDimitry Andric       exe_ctx.GetAddressByteSize());
3659*0fca6ea1SDimitry Andric   return ValueObject::CreateValueObjectFromData(name, *data_sp, exe_ctx, type);
3660*0fca6ea1SDimitry Andric }
3661*0fca6ea1SDimitry Andric 
36620b57cec5SDimitry Andric ModuleSP ValueObject::GetModule() {
36630b57cec5SDimitry Andric   ValueObject *root(GetRoot());
36640b57cec5SDimitry Andric   if (root != this)
36650b57cec5SDimitry Andric     return root->GetModule();
36660b57cec5SDimitry Andric   return lldb::ModuleSP();
36670b57cec5SDimitry Andric }
36680b57cec5SDimitry Andric 
36690b57cec5SDimitry Andric ValueObject *ValueObject::GetRoot() {
36700b57cec5SDimitry Andric   if (m_root)
36710b57cec5SDimitry Andric     return m_root;
36720b57cec5SDimitry Andric   return (m_root = FollowParentChain([](ValueObject *vo) -> bool {
36730b57cec5SDimitry Andric             return (vo->m_parent != nullptr);
36740b57cec5SDimitry Andric           }));
36750b57cec5SDimitry Andric }
36760b57cec5SDimitry Andric 
36770b57cec5SDimitry Andric ValueObject *
36780b57cec5SDimitry Andric ValueObject::FollowParentChain(std::function<bool(ValueObject *)> f) {
36790b57cec5SDimitry Andric   ValueObject *vo = this;
36800b57cec5SDimitry Andric   while (vo) {
36810b57cec5SDimitry Andric     if (!f(vo))
36820b57cec5SDimitry Andric       break;
36830b57cec5SDimitry Andric     vo = vo->m_parent;
36840b57cec5SDimitry Andric   }
36850b57cec5SDimitry Andric   return vo;
36860b57cec5SDimitry Andric }
36870b57cec5SDimitry Andric 
36880b57cec5SDimitry Andric AddressType ValueObject::GetAddressTypeOfChildren() {
36890b57cec5SDimitry Andric   if (m_address_type_of_ptr_or_ref_children == eAddressTypeInvalid) {
36900b57cec5SDimitry Andric     ValueObject *root(GetRoot());
36910b57cec5SDimitry Andric     if (root != this)
36920b57cec5SDimitry Andric       return root->GetAddressTypeOfChildren();
36930b57cec5SDimitry Andric   }
36940b57cec5SDimitry Andric   return m_address_type_of_ptr_or_ref_children;
36950b57cec5SDimitry Andric }
36960b57cec5SDimitry Andric 
36970b57cec5SDimitry Andric lldb::DynamicValueType ValueObject::GetDynamicValueType() {
36980b57cec5SDimitry Andric   ValueObject *with_dv_info = this;
36990b57cec5SDimitry Andric   while (with_dv_info) {
37000b57cec5SDimitry Andric     if (with_dv_info->HasDynamicValueTypeInfo())
37010b57cec5SDimitry Andric       return with_dv_info->GetDynamicValueTypeImpl();
37020b57cec5SDimitry Andric     with_dv_info = with_dv_info->m_parent;
37030b57cec5SDimitry Andric   }
37040b57cec5SDimitry Andric   return lldb::eNoDynamicValues;
37050b57cec5SDimitry Andric }
37060b57cec5SDimitry Andric 
37070b57cec5SDimitry Andric lldb::Format ValueObject::GetFormat() const {
37080b57cec5SDimitry Andric   const ValueObject *with_fmt_info = this;
37090b57cec5SDimitry Andric   while (with_fmt_info) {
37100b57cec5SDimitry Andric     if (with_fmt_info->m_format != lldb::eFormatDefault)
37110b57cec5SDimitry Andric       return with_fmt_info->m_format;
37120b57cec5SDimitry Andric     with_fmt_info = with_fmt_info->m_parent;
37130b57cec5SDimitry Andric   }
37140b57cec5SDimitry Andric   return m_format;
37150b57cec5SDimitry Andric }
37160b57cec5SDimitry Andric 
37170b57cec5SDimitry Andric lldb::LanguageType ValueObject::GetPreferredDisplayLanguage() {
37180b57cec5SDimitry Andric   lldb::LanguageType type = m_preferred_display_language;
37190b57cec5SDimitry Andric   if (m_preferred_display_language == lldb::eLanguageTypeUnknown) {
37200b57cec5SDimitry Andric     if (GetRoot()) {
37210b57cec5SDimitry Andric       if (GetRoot() == this) {
37220b57cec5SDimitry Andric         if (StackFrameSP frame_sp = GetFrameSP()) {
37230b57cec5SDimitry Andric           const SymbolContext &sc(
37240b57cec5SDimitry Andric               frame_sp->GetSymbolContext(eSymbolContextCompUnit));
37250b57cec5SDimitry Andric           if (CompileUnit *cu = sc.comp_unit)
37260b57cec5SDimitry Andric             type = cu->GetLanguage();
37270b57cec5SDimitry Andric         }
37280b57cec5SDimitry Andric       } else {
37290b57cec5SDimitry Andric         type = GetRoot()->GetPreferredDisplayLanguage();
37300b57cec5SDimitry Andric       }
37310b57cec5SDimitry Andric     }
37320b57cec5SDimitry Andric   }
37330b57cec5SDimitry Andric   return (m_preferred_display_language = type); // only compute it once
37340b57cec5SDimitry Andric }
37350b57cec5SDimitry Andric 
37360b57cec5SDimitry Andric void ValueObject::SetPreferredDisplayLanguageIfNeeded(lldb::LanguageType lt) {
37370b57cec5SDimitry Andric   if (m_preferred_display_language == lldb::eLanguageTypeUnknown)
37380b57cec5SDimitry Andric     SetPreferredDisplayLanguage(lt);
37390b57cec5SDimitry Andric }
37400b57cec5SDimitry Andric 
37410b57cec5SDimitry Andric bool ValueObject::CanProvideValue() {
37420b57cec5SDimitry Andric   // we need to support invalid types as providers of values because some bare-
37430b57cec5SDimitry Andric   // board debugging scenarios have no notion of types, but still manage to
37440b57cec5SDimitry Andric   // have raw numeric values for things like registers. sigh.
3745e8d8bef9SDimitry Andric   CompilerType type = GetCompilerType();
37460b57cec5SDimitry Andric   return (!type.IsValid()) || (0 != (type.GetTypeInfo() & eTypeHasValue));
37470b57cec5SDimitry Andric }
37480b57cec5SDimitry Andric 
3749fe6060f1SDimitry Andric 
37500b57cec5SDimitry Andric 
37510b57cec5SDimitry Andric ValueObjectSP ValueObject::Persist() {
37520b57cec5SDimitry Andric   if (!UpdateValueIfNeeded())
37530b57cec5SDimitry Andric     return nullptr;
37540b57cec5SDimitry Andric 
37550b57cec5SDimitry Andric   TargetSP target_sp(GetTargetSP());
37560b57cec5SDimitry Andric   if (!target_sp)
37570b57cec5SDimitry Andric     return nullptr;
37580b57cec5SDimitry Andric 
37590b57cec5SDimitry Andric   PersistentExpressionState *persistent_state =
37600b57cec5SDimitry Andric       target_sp->GetPersistentExpressionStateForLanguage(
37610b57cec5SDimitry Andric           GetPreferredDisplayLanguage());
37620b57cec5SDimitry Andric 
37630b57cec5SDimitry Andric   if (!persistent_state)
37640b57cec5SDimitry Andric     return nullptr;
37650b57cec5SDimitry Andric 
37665ffd83dbSDimitry Andric   ConstString name = persistent_state->GetNextPersistentVariableName();
37670b57cec5SDimitry Andric 
37680b57cec5SDimitry Andric   ValueObjectSP const_result_sp =
37690b57cec5SDimitry Andric       ValueObjectConstResult::Create(target_sp.get(), GetValue(), name);
37700b57cec5SDimitry Andric 
37715ffd83dbSDimitry Andric   ExpressionVariableSP persistent_var_sp =
37720b57cec5SDimitry Andric       persistent_state->CreatePersistentVariable(const_result_sp);
37735ffd83dbSDimitry Andric   persistent_var_sp->m_live_sp = persistent_var_sp->m_frozen_sp;
37745ffd83dbSDimitry Andric   persistent_var_sp->m_flags |= ExpressionVariable::EVIsProgramReference;
37750b57cec5SDimitry Andric 
37765ffd83dbSDimitry Andric   return persistent_var_sp->GetValueObject();
37770b57cec5SDimitry Andric }
37785f757f3fSDimitry Andric 
37795f757f3fSDimitry Andric lldb::ValueObjectSP ValueObject::GetVTable() {
37805f757f3fSDimitry Andric   return ValueObjectVTable::Create(*this);
37815f757f3fSDimitry Andric }
3782