//===-- ValueObject.cpp ---------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "lldb/ValueObject/ValueObject.h"

#include "lldb/Core/Address.h"
#include "lldb/Core/Declaration.h"
#include "lldb/Core/Module.h"
#include "lldb/DataFormatters/DataVisualization.h"
#include "lldb/DataFormatters/DumpValueObjectOptions.h"
#include "lldb/DataFormatters/FormatManager.h"
#include "lldb/DataFormatters/StringPrinter.h"
#include "lldb/DataFormatters/TypeFormat.h"
#include "lldb/DataFormatters/TypeSummary.h"
#include "lldb/DataFormatters/ValueObjectPrinter.h"
#include "lldb/Expression/ExpressionVariable.h"
#include "lldb/Host/Config.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/CompilerType.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Symbol/Type.h"
#include "lldb/Symbol/Variable.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Language.h"
#include "lldb/Target/LanguageRuntime.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/StackFrame.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Target/ThreadList.h"
#include "lldb/Utility/DataBuffer.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/Flags.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/Scalar.h"
#include "lldb/Utility/Stream.h"
#include "lldb/Utility/StreamString.h"
#include "lldb/ValueObject/ValueObjectCast.h"
#include "lldb/ValueObject/ValueObjectChild.h"
#include "lldb/ValueObject/ValueObjectConstResult.h"
#include "lldb/ValueObject/ValueObjectDynamicValue.h"
#include "lldb/ValueObject/ValueObjectMemory.h"
#include "lldb/ValueObject/ValueObjectSynthetic.h"
#include "lldb/ValueObject/ValueObjectVTable.h"
#include "lldb/lldb-enumerations.h"

#include "llvm/Support/Compiler.h"

#include <algorithm>
#include <cstdint>
#include <cstdlib>
#include <memory>
#include <optional>
#include <tuple>

#include <cassert>
#include <cinttypes>
#include <cstdio>
#include <cstring>

namespace lldb_private {
class ExecutionContextScope;
}
namespace lldb_private {
class SymbolContextScope;
}

using namespace lldb;
using namespace lldb_private;

static user_id_t g_value_obj_uid = 0;

// FIXME: this will return true for vector types whose elements
// are floats. Audit all usages of this function and call
// IsFloatingPointType() instead if vectors of floats aren't intended
// to be supported.
static bool HasFloatingRepresentation(CompilerType ct) {
  return ct.GetTypeInfo() & eTypeIsFloat;
}

// ValueObject constructor
ValueObject::ValueObject(ValueObject &parent)
    : m_parent(&parent), m_update_point(parent.GetUpdatePoint()),
      m_manager(parent.GetManager()), m_id(++g_value_obj_uid) {
  m_flags.m_is_synthetic_children_generated =
      parent.m_flags.m_is_synthetic_children_generated;
  m_data.SetByteOrder(parent.GetDataExtractor().GetByteOrder());
  m_data.SetAddressByteSize(parent.GetDataExtractor().GetAddressByteSize());
  m_manager->ManageObject(this);
}

// ValueObject constructor
ValueObject::ValueObject(ExecutionContextScope *exe_scope,
                         ValueObjectManager &manager,
                         AddressType child_ptr_or_ref_addr_type)
    : m_update_point(exe_scope), m_manager(&manager),
      m_address_type_of_ptr_or_ref_children(child_ptr_or_ref_addr_type),
      m_id(++g_value_obj_uid) {
  if (exe_scope) {
    TargetSP target_sp(exe_scope->CalculateTarget());
    if (target_sp) {
      const ArchSpec &arch = target_sp->GetArchitecture();
      m_data.SetByteOrder(arch.GetByteOrder());
      m_data.SetAddressByteSize(arch.GetAddressByteSize());
    }
  }
  m_manager->ManageObject(this);
}

// Destructor
ValueObject::~ValueObject() = default;

bool ValueObject::UpdateValueIfNeeded(bool update_format) {

  bool did_change_formats = false;

  if (update_format)
    did_change_formats = UpdateFormatsIfNeeded();

  // If this is a constant value, then our success is predicated on whether we
  // have an error or not
  if (GetIsConstant()) {
    // if you are constant, things might still have changed behind your back
    // (e.g. you are a frozen object and things have changed deeper than you
    // cared to freeze-dry yourself) in this case, your value has not changed,
    // but "computed" entries might have, so you might now have a different
    // summary, or a different object description. clear these so we will
    // recompute them
    if (update_format && !did_change_formats)
      ClearUserVisibleData(eClearUserVisibleDataItemsSummary |
                           eClearUserVisibleDataItemsDescription);
    return m_error.Success();
  }

  bool first_update = IsChecksumEmpty();

  if (NeedsUpdating()) {
    m_update_point.SetUpdated();

    // Save the old value using swap to avoid a string copy which also will
    // clear our m_value_str
    if (m_value_str.empty()) {
      m_flags.m_old_value_valid = false;
    } else {
      m_flags.m_old_value_valid = true;
      m_old_value_str.swap(m_value_str);
      ClearUserVisibleData(eClearUserVisibleDataItemsValue);
    }

    ClearUserVisibleData();

    if (IsInScope()) {
      const bool value_was_valid = GetValueIsValid();
      SetValueDidChange(false);

      m_error.Clear();

      // Call the pure virtual function to update the value

      bool need_compare_checksums = false;
      llvm::SmallVector<uint8_t, 16> old_checksum;

      if (!first_update && CanProvideValue()) {
        need_compare_checksums = true;
        old_checksum.resize(m_value_checksum.size());
        std::copy(m_value_checksum.begin(), m_value_checksum.end(),
                  old_checksum.begin());
      }

      bool success = UpdateValue();

      SetValueIsValid(success);

      if (success) {
        UpdateChildrenAddressType();
        const uint64_t max_checksum_size = 128;
        m_data.Checksum(m_value_checksum, max_checksum_size);
      } else {
        need_compare_checksums = false;
        m_value_checksum.clear();
      }

      assert(!need_compare_checksums ||
             (!old_checksum.empty() && !m_value_checksum.empty()));

      if (first_update)
        SetValueDidChange(false);
      else if (!m_flags.m_value_did_change && !success) {
        // The value wasn't gotten successfully, so we mark this as changed if
        // the value used to be valid and now isn't
        SetValueDidChange(value_was_valid);
      } else if (need_compare_checksums) {
        SetValueDidChange(memcmp(&old_checksum[0], &m_value_checksum[0],
                                 m_value_checksum.size()));
      }

    } else {
      m_error = Status::FromErrorString("out of scope");
    }
  }
  return m_error.Success();
}

bool ValueObject::UpdateFormatsIfNeeded() {
  Log *log = GetLog(LLDBLog::DataFormatters);
  LLDB_LOGF(log,
            "[%s %p] checking for FormatManager revisions. ValueObject "
            "rev: %d - Global rev: %d",
            GetName().GetCString(), static_cast<void *>(this),
            m_last_format_mgr_revision,
            DataVisualization::GetCurrentRevision());

  bool any_change = false;

  if ((m_last_format_mgr_revision != DataVisualization::GetCurrentRevision())) {
    m_last_format_mgr_revision = DataVisualization::GetCurrentRevision();
    any_change = true;

    SetValueFormat(DataVisualization::GetFormat(*this, GetDynamicValueType()));
    SetSummaryFormat(
        DataVisualization::GetSummaryFormat(*this, GetDynamicValueType()));
    SetSyntheticChildren(
        DataVisualization::GetSyntheticChildren(*this, GetDynamicValueType()));
  }

  return any_change;
}

void ValueObject::SetNeedsUpdate() {
  m_update_point.SetNeedsUpdate();
  // We have to clear the value string here so ConstResult children will notice
  // if their values are changed by hand (i.e. with SetValueAsCString).
  ClearUserVisibleData(eClearUserVisibleDataItemsValue);
}

void ValueObject::ClearDynamicTypeInformation() {
  m_flags.m_children_count_valid = false;
  m_flags.m_did_calculate_complete_objc_class_type = false;
  m_last_format_mgr_revision = 0;
  m_override_type = CompilerType();
  SetValueFormat(lldb::TypeFormatImplSP());
  SetSummaryFormat(lldb::TypeSummaryImplSP());
  SetSyntheticChildren(lldb::SyntheticChildrenSP());
}

CompilerType ValueObject::MaybeCalculateCompleteType() {
  CompilerType compiler_type(GetCompilerTypeImpl());

  if (m_flags.m_did_calculate_complete_objc_class_type) {
    if (m_override_type.IsValid())
      return m_override_type;
    else
      return compiler_type;
  }

  m_flags.m_did_calculate_complete_objc_class_type = true;

  ProcessSP process_sp(
      GetUpdatePoint().GetExecutionContextRef().GetProcessSP());

  if (!process_sp)
    return compiler_type;

  if (auto *runtime =
          process_sp->GetLanguageRuntime(GetObjectRuntimeLanguage())) {
    if (std::optional<CompilerType> complete_type =
            runtime->GetRuntimeType(compiler_type)) {
      m_override_type = *complete_type;
      if (m_override_type.IsValid())
        return m_override_type;
    }
  }
  return compiler_type;
}

DataExtractor &ValueObject::GetDataExtractor() {
  UpdateValueIfNeeded(false);
  return m_data;
}

const Status &ValueObject::GetError() {
  UpdateValueIfNeeded(false);
  return m_error;
}

const char *ValueObject::GetLocationAsCStringImpl(const Value &value,
                                                  const DataExtractor &data) {
  if (UpdateValueIfNeeded(false)) {
    if (m_location_str.empty()) {
      StreamString sstr;

      Value::ValueType value_type = value.GetValueType();

      switch (value_type) {
      case Value::ValueType::Invalid:
        m_location_str = "invalid";
        break;
      case Value::ValueType::Scalar:
        if (value.GetContextType() == Value::ContextType::RegisterInfo) {
          RegisterInfo *reg_info = value.GetRegisterInfo();
          if (reg_info) {
            if (reg_info->name)
              m_location_str = reg_info->name;
            else if (reg_info->alt_name)
              m_location_str = reg_info->alt_name;
            if (m_location_str.empty())
              m_location_str = (reg_info->encoding == lldb::eEncodingVector)
                                   ? "vector"
                                   : "scalar";
          }
        }
        if (m_location_str.empty())
          m_location_str = "scalar";
        break;

      case Value::ValueType::LoadAddress:
      case Value::ValueType::FileAddress:
      case Value::ValueType::HostAddress: {
        uint32_t addr_nibble_size = data.GetAddressByteSize() * 2;
        sstr.Printf("0x%*.*llx", addr_nibble_size, addr_nibble_size,
                    value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS));
        m_location_str = std::string(sstr.GetString());
      } break;
      }
    }
  }
  return m_location_str.c_str();
}

bool ValueObject::ResolveValue(Scalar &scalar) {
  if (UpdateValueIfNeeded(
          false)) // make sure that you are up to date before returning anything
  {
    ExecutionContext exe_ctx(GetExecutionContextRef());
    Value tmp_value(m_value);
    scalar = tmp_value.ResolveValue(&exe_ctx, GetModule().get());
    if (scalar.IsValid()) {
      const uint32_t bitfield_bit_size = GetBitfieldBitSize();
      if (bitfield_bit_size)
        return scalar.ExtractBitfield(bitfield_bit_size,
                                      GetBitfieldBitOffset());
      return true;
    }
  }
  return false;
}

bool ValueObject::IsLogicalTrue(Status &error) {
  if (Language *language = Language::FindPlugin(GetObjectRuntimeLanguage())) {
    LazyBool is_logical_true = language->IsLogicalTrue(*this, error);
    switch (is_logical_true) {
    case eLazyBoolYes:
    case eLazyBoolNo:
      return (is_logical_true == true);
    case eLazyBoolCalculate:
      break;
    }
  }

  Scalar scalar_value;

  if (!ResolveValue(scalar_value)) {
    error = Status::FromErrorString("failed to get a scalar result");
    return false;
  }

  bool ret;
  ret = scalar_value.ULongLong(1) != 0;
  error.Clear();
  return ret;
}

ValueObjectSP ValueObject::GetChildAtIndex(uint32_t idx, bool can_create) {
  ValueObjectSP child_sp;
  // We may need to update our value if we are dynamic
  if (IsPossibleDynamicType())
    UpdateValueIfNeeded(false);
  if (idx < GetNumChildrenIgnoringErrors()) {
    // Check if we have already made the child value object?
    if (can_create && !m_children.HasChildAtIndex(idx)) {
      // No we haven't created the child at this index, so lets have our
      // subclass do it and cache the result for quick future access.
      m_children.SetChildAtIndex(idx, CreateChildAtIndex(idx));
    }

    ValueObject *child = m_children.GetChildAtIndex(idx);
    if (child != nullptr)
      return child->GetSP();
  }
  return child_sp;
}

lldb::ValueObjectSP
ValueObject::GetChildAtNamePath(llvm::ArrayRef<llvm::StringRef> names) {
  if (names.size() == 0)
    return GetSP();
  ValueObjectSP root(GetSP());
  for (llvm::StringRef name : names) {
    root = root->GetChildMemberWithName(name);
    if (!root) {
      return root;
    }
  }
  return root;
}

llvm::Expected<size_t>
ValueObject::GetIndexOfChildWithName(llvm::StringRef name) {
  bool omit_empty_base_classes = true;
  return GetCompilerType().GetIndexOfChildWithName(name,
                                                   omit_empty_base_classes);
}

ValueObjectSP ValueObject::GetChildMemberWithName(llvm::StringRef name,
                                                  bool can_create) {
  // We may need to update our value if we are dynamic.
  if (IsPossibleDynamicType())
    UpdateValueIfNeeded(false);

  // When getting a child by name, it could be buried inside some base classes
  // (which really aren't part of the expression path), so we need a vector of
  // indexes that can get us down to the correct child.
  std::vector<uint32_t> child_indexes;
  bool omit_empty_base_classes = true;

  if (!GetCompilerType().IsValid())
    return ValueObjectSP();

  const size_t num_child_indexes =
      GetCompilerType().GetIndexOfChildMemberWithName(
          name, omit_empty_base_classes, child_indexes);
  if (num_child_indexes == 0)
    return nullptr;

  ValueObjectSP child_sp = GetSP();
  for (uint32_t idx : child_indexes)
    if (child_sp)
      child_sp = child_sp->GetChildAtIndex(idx, can_create);
  return child_sp;
}

llvm::Expected<uint32_t> ValueObject::GetNumChildren(uint32_t max) {
  UpdateValueIfNeeded();

  if (max < UINT32_MAX) {
    if (m_flags.m_children_count_valid) {
      size_t children_count = m_children.GetChildrenCount();
      return children_count <= max ? children_count : max;
    } else
      return CalculateNumChildren(max);
  }

  if (!m_flags.m_children_count_valid) {
    auto num_children_or_err = CalculateNumChildren();
    if (num_children_or_err)
      SetNumChildren(*num_children_or_err);
    else
      return num_children_or_err;
  }
  return m_children.GetChildrenCount();
}

uint32_t ValueObject::GetNumChildrenIgnoringErrors(uint32_t max) {
  auto value_or_err = GetNumChildren(max);
  if (value_or_err)
    return *value_or_err;
  LLDB_LOG_ERRORV(GetLog(LLDBLog::DataFormatters), value_or_err.takeError(),
                  "{0}");
  return 0;
}

bool ValueObject::MightHaveChildren() {
  bool has_children = false;
  const uint32_t type_info = GetTypeInfo();
  if (type_info) {
    if (type_info & (eTypeHasChildren | eTypeIsPointer | eTypeIsReference))
      has_children = true;
  } else {
    has_children = GetNumChildrenIgnoringErrors() > 0;
  }
  return has_children;
}

// Should only be called by ValueObject::GetNumChildren()
void ValueObject::SetNumChildren(uint32_t num_children) {
  m_flags.m_children_count_valid = true;
  m_children.SetChildrenCount(num_children);
}

ValueObject *ValueObject::CreateChildAtIndex(size_t idx) {
  bool omit_empty_base_classes = true;
  bool ignore_array_bounds = false;
  std::string child_name;
  uint32_t child_byte_size = 0;
  int32_t child_byte_offset = 0;
  uint32_t child_bitfield_bit_size = 0;
  uint32_t child_bitfield_bit_offset = 0;
  bool child_is_base_class = false;
  bool child_is_deref_of_parent = false;
  uint64_t language_flags = 0;
  const bool transparent_pointers = true;

  ExecutionContext exe_ctx(GetExecutionContextRef());

  auto child_compiler_type_or_err =
      GetCompilerType().GetChildCompilerTypeAtIndex(
          &exe_ctx, idx, transparent_pointers, omit_empty_base_classes,
          ignore_array_bounds, child_name, child_byte_size, child_byte_offset,
          child_bitfield_bit_size, child_bitfield_bit_offset,
          child_is_base_class, child_is_deref_of_parent, this, language_flags);
  if (!child_compiler_type_or_err || !child_compiler_type_or_err->IsValid()) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::Types),
                   child_compiler_type_or_err.takeError(),
                   "could not find child: {0}");
    return nullptr;
  }

  return new ValueObjectChild(
      *this, *child_compiler_type_or_err, ConstString(child_name),
      child_byte_size, child_byte_offset, child_bitfield_bit_size,
      child_bitfield_bit_offset, child_is_base_class, child_is_deref_of_parent,
      eAddressTypeInvalid, language_flags);
}

ValueObject *ValueObject::CreateSyntheticArrayMember(size_t idx) {
  bool omit_empty_base_classes = true;
  bool ignore_array_bounds = true;
  std::string child_name;
  uint32_t child_byte_size = 0;
  int32_t child_byte_offset = 0;
  uint32_t child_bitfield_bit_size = 0;
  uint32_t child_bitfield_bit_offset = 0;
  bool child_is_base_class = false;
  bool child_is_deref_of_parent = false;
  uint64_t language_flags = 0;
  const bool transparent_pointers = false;

  ExecutionContext exe_ctx(GetExecutionContextRef());

  auto child_compiler_type_or_err =
      GetCompilerType().GetChildCompilerTypeAtIndex(
          &exe_ctx, 0, transparent_pointers, omit_empty_base_classes,
          ignore_array_bounds, child_name, child_byte_size, child_byte_offset,
          child_bitfield_bit_size, child_bitfield_bit_offset,
          child_is_base_class, child_is_deref_of_parent, this, language_flags);
  if (!child_compiler_type_or_err) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::Types),
                   child_compiler_type_or_err.takeError(),
                   "could not find child: {0}");
    return nullptr;
  }

  if (child_compiler_type_or_err->IsValid()) {
    child_byte_offset += child_byte_size * idx;

    return new ValueObjectChild(
        *this, *child_compiler_type_or_err, ConstString(child_name),
        child_byte_size, child_byte_offset, child_bitfield_bit_size,
        child_bitfield_bit_offset, child_is_base_class,
        child_is_deref_of_parent, eAddressTypeInvalid, language_flags);
  }

  // In case of an incomplete type, try to use the ValueObject's
  // synthetic value to create the child ValueObject.
  if (ValueObjectSP synth_valobj_sp = GetSyntheticValue())
    return synth_valobj_sp->GetChildAtIndex(idx, /*can_create=*/true).get();

  return nullptr;
}

bool ValueObject::GetSummaryAsCString(TypeSummaryImpl *summary_ptr,
                                      std::string &destination,
                                      lldb::LanguageType lang) {
  return GetSummaryAsCString(summary_ptr, destination,
                             TypeSummaryOptions().SetLanguage(lang));
}

bool ValueObject::GetSummaryAsCString(TypeSummaryImpl *summary_ptr,
                                      std::string &destination,
                                      const TypeSummaryOptions &options) {
  destination.clear();

  // If we have a forcefully completed type, don't try and show a summary from
  // a valid summary string or function because the type is not complete and
  // no member variables or member functions will be available.
  if (GetCompilerType().IsForcefullyCompleted()) {
    destination = "<incomplete type>";
    return true;
  }

  // ideally we would like to bail out if passing NULL, but if we do so we end
  // up not providing the summary for function pointers anymore
  if (/*summary_ptr == NULL ||*/ m_flags.m_is_getting_summary)
    return false;

  m_flags.m_is_getting_summary = true;

  TypeSummaryOptions actual_options(options);

  if (actual_options.GetLanguage() == lldb::eLanguageTypeUnknown)
    actual_options.SetLanguage(GetPreferredDisplayLanguage());

  // this is a hot path in code and we prefer to avoid setting this string all
  // too often also clearing out other information that we might care to see in
  // a crash log. might be useful in very specific situations though.
  /*Host::SetCrashDescriptionWithFormat("Trying to fetch a summary for %s %s.
   Summary provider's description is %s",
   GetTypeName().GetCString(),
   GetName().GetCString(),
   summary_ptr->GetDescription().c_str());*/

  if (UpdateValueIfNeeded(false) && summary_ptr) {
    if (HasSyntheticValue())
      m_synthetic_value->UpdateValueIfNeeded(); // the summary might depend on
                                                // the synthetic children being
                                                // up-to-date (e.g. ${svar%#})

    if (TargetSP target_sp = GetExecutionContextRef().GetTargetSP()) {
      SummaryStatisticsSP stats_sp =
          target_sp->GetSummaryStatisticsCache()
              .GetSummaryStatisticsForProvider(*summary_ptr);

      // Construct RAII types to time and collect data on summary creation.
      SummaryStatistics::SummaryInvocation invocation(stats_sp);
      summary_ptr->FormatObject(this, destination, actual_options);
    } else
      summary_ptr->FormatObject(this, destination, actual_options);
  }
  m_flags.m_is_getting_summary = false;
  return !destination.empty();
}

const char *ValueObject::GetSummaryAsCString(lldb::LanguageType lang) {
  if (UpdateValueIfNeeded(true) && m_summary_str.empty()) {
    TypeSummaryOptions summary_options;
    summary_options.SetLanguage(lang);
    GetSummaryAsCString(GetSummaryFormat().get(), m_summary_str,
                        summary_options);
  }
  if (m_summary_str.empty())
    return nullptr;
  return m_summary_str.c_str();
}

bool ValueObject::GetSummaryAsCString(std::string &destination,
                                      const TypeSummaryOptions &options) {
  return GetSummaryAsCString(GetSummaryFormat().get(), destination, options);
}

bool ValueObject::IsCStringContainer(bool check_pointer) {
  CompilerType pointee_or_element_compiler_type;
  const Flags type_flags(GetTypeInfo(&pointee_or_element_compiler_type));
  bool is_char_arr_ptr(type_flags.AnySet(eTypeIsArray | eTypeIsPointer) &&
                       pointee_or_element_compiler_type.IsCharType());
  if (!is_char_arr_ptr)
    return false;
  if (!check_pointer)
    return true;
  if (type_flags.Test(eTypeIsArray))
    return true;
  addr_t cstr_address = GetPointerValue().address;
  return (cstr_address != LLDB_INVALID_ADDRESS);
}

size_t ValueObject::GetPointeeData(DataExtractor &data, uint32_t item_idx,
                                   uint32_t item_count) {
  CompilerType pointee_or_element_compiler_type;
  const uint32_t type_info = GetTypeInfo(&pointee_or_element_compiler_type);
  const bool is_pointer_type = type_info & eTypeIsPointer;
  const bool is_array_type = type_info & eTypeIsArray;
  if (!(is_pointer_type || is_array_type))
    return 0;

  if (item_count == 0)
    return 0;

  ExecutionContext exe_ctx(GetExecutionContextRef());

  std::optional<uint64_t> item_type_size =
      llvm::expectedToOptional(pointee_or_element_compiler_type.GetByteSize(
          exe_ctx.GetBestExecutionContextScope()));
  if (!item_type_size)
    return 0;
  const uint64_t bytes = item_count * *item_type_size;
  const uint64_t offset = item_idx * *item_type_size;

  if (item_idx == 0 && item_count == 1) // simply a deref
  {
    if (is_pointer_type) {
      Status error;
      ValueObjectSP pointee_sp = Dereference(error);
      if (error.Fail() || pointee_sp.get() == nullptr)
        return 0;
      return pointee_sp->GetData(data, error);
    } else {
      ValueObjectSP child_sp = GetChildAtIndex(0);
      if (child_sp.get() == nullptr)
        return 0;
      Status error;
      return child_sp->GetData(data, error);
    }
    return true;
  } else /* (items > 1) */
  {
    Status error;
    lldb_private::DataBufferHeap *heap_buf_ptr = nullptr;
    lldb::DataBufferSP data_sp(heap_buf_ptr =
                                   new lldb_private::DataBufferHeap());

    auto [addr, addr_type] =
        is_pointer_type ? GetPointerValue() : GetAddressOf(true);

    switch (addr_type) {
    case eAddressTypeFile: {
      ModuleSP module_sp(GetModule());
      if (module_sp) {
        addr = addr + offset;
        Address so_addr;
        module_sp->ResolveFileAddress(addr, so_addr);
        ExecutionContext exe_ctx(GetExecutionContextRef());
        Target *target = exe_ctx.GetTargetPtr();
        if (target) {
          heap_buf_ptr->SetByteSize(bytes);
          size_t bytes_read = target->ReadMemory(
              so_addr, heap_buf_ptr->GetBytes(), bytes, error, true);
          if (error.Success()) {
            data.SetData(data_sp);
            return bytes_read;
          }
        }
      }
    } break;
    case eAddressTypeLoad: {
      ExecutionContext exe_ctx(GetExecutionContextRef());
      if (Target *target = exe_ctx.GetTargetPtr()) {
        heap_buf_ptr->SetByteSize(bytes);
        Address target_addr;
        target_addr.SetLoadAddress(addr + offset, target);
        size_t bytes_read =
            target->ReadMemory(target_addr, heap_buf_ptr->GetBytes(), bytes,
                               error, /*force_live_memory=*/true);
        if (error.Success() || bytes_read > 0) {
          data.SetData(data_sp);
          return bytes_read;
        }
      }
    } break;
    case eAddressTypeHost: {
      auto max_bytes = llvm::expectedToOptional(GetCompilerType().GetByteSize(
          exe_ctx.GetBestExecutionContextScope()));
      if (max_bytes && *max_bytes > offset) {
        size_t bytes_read = std::min<uint64_t>(*max_bytes - offset, bytes);
        addr = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
        if (addr == 0 || addr == LLDB_INVALID_ADDRESS)
          break;
        heap_buf_ptr->CopyData((uint8_t *)(addr + offset), bytes_read);
        data.SetData(data_sp);
        return bytes_read;
      }
    } break;
    case eAddressTypeInvalid:
      break;
    }
  }
  return 0;
}

uint64_t ValueObject::GetData(DataExtractor &data, Status &error) {
  UpdateValueIfNeeded(false);
  ExecutionContext exe_ctx(GetExecutionContextRef());
  error = m_value.GetValueAsData(&exe_ctx, data, GetModule().get());
  if (error.Fail()) {
    if (m_data.GetByteSize()) {
      data = m_data;
      error.Clear();
      return data.GetByteSize();
    } else {
      return 0;
    }
  }
  data.SetAddressByteSize(m_data.GetAddressByteSize());
  data.SetByteOrder(m_data.GetByteOrder());
  return data.GetByteSize();
}

bool ValueObject::SetData(DataExtractor &data, Status &error) {
  error.Clear();
  // Make sure our value is up to date first so that our location and location
  // type is valid.
  if (!UpdateValueIfNeeded(false)) {
    error = Status::FromErrorString("unable to read value");
    return false;
  }

  const Encoding encoding = GetCompilerType().GetEncoding();

  const size_t byte_size = llvm::expectedToOptional(GetByteSize()).value_or(0);

  Value::ValueType value_type = m_value.GetValueType();

  switch (value_type) {
  case Value::ValueType::Invalid:
    error = Status::FromErrorString("invalid location");
    return false;
  case Value::ValueType::Scalar: {
    Status set_error =
        m_value.GetScalar().SetValueFromData(data, encoding, byte_size);

    if (!set_error.Success()) {
      error = Status::FromErrorStringWithFormat(
          "unable to set scalar value: %s", set_error.AsCString());
      return false;
    }
  } break;
  case Value::ValueType::LoadAddress: {
    // If it is a load address, then the scalar value is the storage location
    // of the data, and we have to shove this value down to that load location.
    ExecutionContext exe_ctx(GetExecutionContextRef());
    Process *process = exe_ctx.GetProcessPtr();
    if (process) {
      addr_t target_addr = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
      size_t bytes_written = process->WriteMemory(
          target_addr, data.GetDataStart(), byte_size, error);
      if (!error.Success())
        return false;
      if (bytes_written != byte_size) {
        error = Status::FromErrorString("unable to write value to memory");
        return false;
      }
    }
  } break;
  case Value::ValueType::HostAddress: {
    // If it is a host address, then we stuff the scalar as a DataBuffer into
    // the Value's data.
    DataBufferSP buffer_sp(new DataBufferHeap(byte_size, 0));
    m_data.SetData(buffer_sp, 0);
    data.CopyByteOrderedData(0, byte_size,
                             const_cast<uint8_t *>(m_data.GetDataStart()),
                             byte_size, m_data.GetByteOrder());
    m_value.GetScalar() = (uintptr_t)m_data.GetDataStart();
  } break;
  case Value::ValueType::FileAddress:
    break;
  }

  // If we have reached this point, then we have successfully changed the
  // value.
  SetNeedsUpdate();
  return true;
}

llvm::ArrayRef<uint8_t> ValueObject::GetLocalBuffer() const {
  if (m_value.GetValueType() != Value::ValueType::HostAddress)
    return {};
  auto start = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
  if (start == LLDB_INVALID_ADDRESS)
    return {};
  // Does our pointer point to this value object's m_data buffer?
  if ((uint64_t)m_data.GetDataStart() == start)
    return m_data.GetData();
  // Does our pointer point to the value's buffer?
  if ((uint64_t)m_value.GetBuffer().GetBytes() == start)
    return m_value.GetBuffer().GetData();
  // Our pointer points to something else. We can't know what the size is.
  return {};
}

static bool CopyStringDataToBufferSP(const StreamString &source,
                                     lldb::WritableDataBufferSP &destination) {
  llvm::StringRef src = source.GetString();
  src = src.rtrim('\0');
  destination = std::make_shared<DataBufferHeap>(src.size(), 0);
  memcpy(destination->GetBytes(), src.data(), src.size());
  return true;
}

std::pair<size_t, bool>
ValueObject::ReadPointedString(lldb::WritableDataBufferSP &buffer_sp,
                               Status &error, bool honor_array) {
  bool was_capped = false;
  StreamString s;
  ExecutionContext exe_ctx(GetExecutionContextRef());
  Target *target = exe_ctx.GetTargetPtr();

  if (!target) {
    s << "<no target to read from>";
    error = Status::FromErrorString("no target to read from");
    CopyStringDataToBufferSP(s, buffer_sp);
    return {0, was_capped};
  }

  const auto max_length = target->GetMaximumSizeOfStringSummary();

  size_t bytes_read = 0;
  size_t total_bytes_read = 0;

  CompilerType compiler_type = GetCompilerType();
  CompilerType elem_or_pointee_compiler_type;
  const Flags type_flags(GetTypeInfo(&elem_or_pointee_compiler_type));
  if (type_flags.AnySet(eTypeIsArray | eTypeIsPointer) &&
      elem_or_pointee_compiler_type.IsCharType()) {
    AddrAndType cstr_address;

    size_t cstr_len = 0;
    bool capped_data = false;
    const bool is_array = type_flags.Test(eTypeIsArray);
    if (is_array) {
      // We have an array
      uint64_t array_size = 0;
      if (compiler_type.IsArrayType(nullptr, &array_size)) {
        cstr_len = array_size;
        if (cstr_len > max_length) {
          capped_data = true;
          cstr_len = max_length;
        }
      }
      cstr_address = GetAddressOf(true);
    } else {
      // We have a pointer
      cstr_address = GetPointerValue();
    }

    if (cstr_address.address == 0 ||
        cstr_address.address == LLDB_INVALID_ADDRESS) {
      if (cstr_address.type == eAddressTypeHost && is_array) {
        const char *cstr = GetDataExtractor().PeekCStr(0);
        if (cstr == nullptr) {
          s << "<invalid address>";
          error = Status::FromErrorString("invalid address");
          CopyStringDataToBufferSP(s, buffer_sp);
          return {0, was_capped};
        }
        s << llvm::StringRef(cstr, cstr_len);
        CopyStringDataToBufferSP(s, buffer_sp);
        return {cstr_len, was_capped};
      } else {
        s << "<invalid address>";
        error = Status::FromErrorString("invalid address");
        CopyStringDataToBufferSP(s, buffer_sp);
        return {0, was_capped};
      }
    }

    Address cstr_so_addr(cstr_address.address);
    DataExtractor data;
    if (cstr_len > 0 && honor_array) {
      // I am using GetPointeeData() here to abstract the fact that some
      // ValueObjects are actually frozen pointers in the host but the pointed-
      // to data lives in the debuggee, and GetPointeeData() automatically
      // takes care of this
      GetPointeeData(data, 0, cstr_len);

      if ((bytes_read = data.GetByteSize()) > 0) {
        total_bytes_read = bytes_read;
        for (size_t offset = 0; offset < bytes_read; offset++)
          s.Printf("%c", *data.PeekData(offset, 1));
        if (capped_data)
          was_capped = true;
      }
    } else {
      cstr_len = max_length;
      const size_t k_max_buf_size = 64;

      size_t offset = 0;

      int cstr_len_displayed = -1;
      bool capped_cstr = false;
      // I am using GetPointeeData() here to abstract the fact that some
      // ValueObjects are actually frozen pointers in the host but the pointed-
      // to data lives in the debuggee, and GetPointeeData() automatically
      // takes care of this
      while ((bytes_read = GetPointeeData(data, offset, k_max_buf_size)) > 0) {
        total_bytes_read += bytes_read;
        const char *cstr = data.PeekCStr(0);
        size_t len = strnlen(cstr, k_max_buf_size);
        if (cstr_len_displayed < 0)
          cstr_len_displayed = len;

        if (len == 0)
          break;
        cstr_len_displayed += len;
        if (len > bytes_read)
          len = bytes_read;
        if (len > cstr_len)
          len = cstr_len;

        for (size_t offset = 0; offset < bytes_read; offset++)
          s.Printf("%c", *data.PeekData(offset, 1));

        if (len < k_max_buf_size)
          break;

        if (len >= cstr_len) {
          capped_cstr = true;
          break;
        }

        cstr_len -= len;
        offset += len;
      }

      if (cstr_len_displayed >= 0) {
        if (capped_cstr)
          was_capped = true;
      }
    }
  } else {
    error = Status::FromErrorString("not a string object");
    s << "<not a string object>";
  }
  CopyStringDataToBufferSP(s, buffer_sp);
  return {total_bytes_read, was_capped};
}

llvm::Expected<std::string> ValueObject::GetObjectDescription() {
  if (!UpdateValueIfNeeded(true))
    return llvm::createStringError("could not update value");

  // Return cached value.
  if (!m_object_desc_str.empty())
    return m_object_desc_str;

  ExecutionContext exe_ctx(GetExecutionContextRef());
  Process *process = exe_ctx.GetProcessPtr();
  if (!process)
    return llvm::createStringError("no process");

  // Returns the object description produced by one language runtime.
  auto get_object_description =
      [&](LanguageType language) -> llvm::Expected<std::string> {
    if (LanguageRuntime *runtime = process->GetLanguageRuntime(language)) {
      StreamString s;
      if (llvm::Error error = runtime->GetObjectDescription(s, *this))
        return error;
      m_object_desc_str = s.GetString();
      return m_object_desc_str;
    }
    return llvm::createStringError("no native language runtime");
  };

  // Try the native language runtime first.
  LanguageType native_language = GetObjectRuntimeLanguage();
  llvm::Expected<std::string> desc = get_object_description(native_language);
  if (desc)
    return desc;

  // Try the Objective-C language runtime. This fallback is necessary
  // for Objective-C++ and mixed Objective-C / C++ programs.
  if (Language::LanguageIsCFamily(native_language)) {
    // We're going to try again, so let's drop the first error.
    llvm::consumeError(desc.takeError());
    return get_object_description(eLanguageTypeObjC);
  }
  return desc;
}

bool ValueObject::GetValueAsCString(const lldb_private::TypeFormatImpl &format,
                                    std::string &destination) {
  if (UpdateValueIfNeeded(false))
    return format.FormatObject(this, destination);
  else
    return false;
}

bool ValueObject::GetValueAsCString(lldb::Format format,
                                    std::string &destination) {
  return GetValueAsCString(TypeFormatImpl_Format(format), destination);
}

const char *ValueObject::GetValueAsCString() {
  if (UpdateValueIfNeeded(true)) {
    lldb::TypeFormatImplSP format_sp;
    lldb::Format my_format = GetFormat();
    if (my_format == lldb::eFormatDefault) {
      if (m_type_format_sp)
        format_sp = m_type_format_sp;
      else {
        if (m_flags.m_is_bitfield_for_scalar)
          my_format = eFormatUnsigned;
        else {
          if (m_value.GetContextType() == Value::ContextType::RegisterInfo) {
            const RegisterInfo *reg_info = m_value.GetRegisterInfo();
            if (reg_info)
              my_format = reg_info->format;
          } else {
            my_format = GetValue().GetCompilerType().GetFormat();
          }
        }
      }
    }
    if (my_format != m_last_format || m_value_str.empty()) {
      m_last_format = my_format;
      if (!format_sp)
        format_sp = std::make_shared<TypeFormatImpl_Format>(my_format);
      if (GetValueAsCString(*format_sp.get(), m_value_str)) {
        if (!m_flags.m_value_did_change && m_flags.m_old_value_valid) {
          // The value was gotten successfully, so we consider the value as
          // changed if the value string differs
          SetValueDidChange(m_old_value_str != m_value_str);
        }
      }
    }
  }
  if (m_value_str.empty())
    return nullptr;
  return m_value_str.c_str();
}

// if > 8bytes, 0 is returned. this method should mostly be used to read
// address values out of pointers
uint64_t ValueObject::GetValueAsUnsigned(uint64_t fail_value, bool *success) {
  // If our byte size is zero this is an aggregate type that has children
  if (CanProvideValue()) {
    Scalar scalar;
    if (ResolveValue(scalar)) {
      if (success)
        *success = true;
      scalar.MakeUnsigned();
      return scalar.ULongLong(fail_value);
    }
    // fallthrough, otherwise...
  }

  if (success)
    *success = false;
  return fail_value;
}

int64_t ValueObject::GetValueAsSigned(int64_t fail_value, bool *success) {
  // If our byte size is zero this is an aggregate type that has children
  if (CanProvideValue()) {
    Scalar scalar;
    if (ResolveValue(scalar)) {
      if (success)
        *success = true;
      scalar.MakeSigned();
      return scalar.SLongLong(fail_value);
    }
    // fallthrough, otherwise...
  }

  if (success)
    *success = false;
  return fail_value;
}

llvm::Expected<llvm::APSInt> ValueObject::GetValueAsAPSInt() {
  // Make sure the type can be converted to an APSInt.
  if (!GetCompilerType().IsInteger() &&
      !GetCompilerType().IsScopedEnumerationType() &&
      !GetCompilerType().IsEnumerationType() &&
      !GetCompilerType().IsPointerType() &&
      !GetCompilerType().IsNullPtrType() &&
      !GetCompilerType().IsReferenceType() && !GetCompilerType().IsBoolean())
    return llvm::make_error<llvm::StringError>(
        "type cannot be converted to APSInt", llvm::inconvertibleErrorCode());

  if (CanProvideValue()) {
    Scalar scalar;
    if (ResolveValue(scalar))
      return scalar.GetAPSInt();
  }

  return llvm::make_error<llvm::StringError>(
      "error occurred; unable to convert to APSInt",
      llvm::inconvertibleErrorCode());
}

llvm::Expected<llvm::APFloat> ValueObject::GetValueAsAPFloat() {
  if (!HasFloatingRepresentation(GetCompilerType()))
    return llvm::make_error<llvm::StringError>(
        "type cannot be converted to APFloat", llvm::inconvertibleErrorCode());

  if (CanProvideValue()) {
    Scalar scalar;
    if (ResolveValue(scalar))
      return scalar.GetAPFloat();
  }

  return llvm::make_error<llvm::StringError>(
      "error occurred; unable to convert to APFloat",
      llvm::inconvertibleErrorCode());
}

llvm::Expected<bool> ValueObject::GetValueAsBool() {
  CompilerType val_type = GetCompilerType();
  if (val_type.IsInteger() || val_type.IsUnscopedEnumerationType() ||
      val_type.IsPointerType()) {
    auto value_or_err = GetValueAsAPSInt();
    if (value_or_err)
      return value_or_err->getBoolValue();
  }
  if (HasFloatingRepresentation(val_type)) {
    auto value_or_err = GetValueAsAPFloat();
    if (value_or_err)
      return value_or_err->isNonZero();
  }
  if (val_type.IsArrayType())
    return GetAddressOf().address != 0;

  return llvm::make_error<llvm::StringError>("type cannot be converted to bool",
                                             llvm::inconvertibleErrorCode());
}

void ValueObject::SetValueFromInteger(const llvm::APInt &value, Status &error) {
  // Verify the current object is an integer object
  CompilerType val_type = GetCompilerType();
  if (!val_type.IsInteger() && !val_type.IsUnscopedEnumerationType() &&
      !HasFloatingRepresentation(val_type) && !val_type.IsPointerType() &&
      !val_type.IsScalarType()) {
    error =
        Status::FromErrorString("current value object is not an integer objet");
    return;
  }

  // Verify the current object is not actually associated with any program
  // variable.
  if (GetVariable()) {
    error = Status::FromErrorString(
        "current value object is not a temporary object");
    return;
  }

  // Verify the proposed new value is the right size.
  lldb::TargetSP target = GetTargetSP();
  uint64_t byte_size = 0;
  if (auto temp =
          llvm::expectedToOptional(GetCompilerType().GetByteSize(target.get())))
    byte_size = temp.value();
  if (value.getBitWidth() != byte_size * CHAR_BIT) {
    error = Status::FromErrorString(
        "illegal argument: new value should be of the same size");
    return;
  }

  lldb::DataExtractorSP data_sp;
  data_sp->SetData(value.getRawData(), byte_size,
                   target->GetArchitecture().GetByteOrder());
  data_sp->SetAddressByteSize(
      static_cast<uint8_t>(target->GetArchitecture().GetAddressByteSize()));
  SetData(*data_sp, error);
}

void ValueObject::SetValueFromInteger(lldb::ValueObjectSP new_val_sp,
                                      Status &error) {
  // Verify the current object is an integer object
  CompilerType val_type = GetCompilerType();
  if (!val_type.IsInteger() && !val_type.IsUnscopedEnumerationType() &&
      !HasFloatingRepresentation(val_type) && !val_type.IsPointerType() &&
      !val_type.IsScalarType()) {
    error =
        Status::FromErrorString("current value object is not an integer objet");
    return;
  }

  // Verify the current object is not actually associated with any program
  // variable.
  if (GetVariable()) {
    error = Status::FromErrorString(
        "current value object is not a temporary object");
    return;
  }

  // Verify the proposed new value is the right type.
  CompilerType new_val_type = new_val_sp->GetCompilerType();
  if (!new_val_type.IsInteger() && !HasFloatingRepresentation(new_val_type) &&
      !new_val_type.IsPointerType()) {
    error = Status::FromErrorString(
        "illegal argument: new value should be of the same size");
    return;
  }

  if (new_val_type.IsInteger()) {
    auto value_or_err = new_val_sp->GetValueAsAPSInt();
    if (value_or_err)
      SetValueFromInteger(*value_or_err, error);
    else
      error = Status::FromErrorString("error getting APSInt from new_val_sp");
  } else if (HasFloatingRepresentation(new_val_type)) {
    auto value_or_err = new_val_sp->GetValueAsAPFloat();
    if (value_or_err)
      SetValueFromInteger(value_or_err->bitcastToAPInt(), error);
    else
      error = Status::FromErrorString("error getting APFloat from new_val_sp");
  } else if (new_val_type.IsPointerType()) {
    bool success = true;
    uint64_t int_val = new_val_sp->GetValueAsUnsigned(0, &success);
    if (success) {
      lldb::TargetSP target = GetTargetSP();
      uint64_t num_bits = 0;
      if (auto temp = llvm::expectedToOptional(
              new_val_sp->GetCompilerType().GetBitSize(target.get())))
        num_bits = temp.value();
      SetValueFromInteger(llvm::APInt(num_bits, int_val), error);
    } else
      error = Status::FromErrorString("error converting new_val_sp to integer");
  }
}

// if any more "special cases" are added to
// ValueObject::DumpPrintableRepresentation() please keep this call up to date
// by returning true for your new special cases. We will eventually move to
// checking this call result before trying to display special cases
bool ValueObject::HasSpecialPrintableRepresentation(
    ValueObjectRepresentationStyle val_obj_display, Format custom_format) {
  Flags flags(GetTypeInfo());
  if (flags.AnySet(eTypeIsArray | eTypeIsPointer) &&
      val_obj_display == ValueObject::eValueObjectRepresentationStyleValue) {
    if (IsCStringContainer(true) &&
        (custom_format == eFormatCString || custom_format == eFormatCharArray ||
         custom_format == eFormatChar || custom_format == eFormatVectorOfChar))
      return true;

    if (flags.Test(eTypeIsArray)) {
      if ((custom_format == eFormatBytes) ||
          (custom_format == eFormatBytesWithASCII))
        return true;

      if ((custom_format == eFormatVectorOfChar) ||
          (custom_format == eFormatVectorOfFloat32) ||
          (custom_format == eFormatVectorOfFloat64) ||
          (custom_format == eFormatVectorOfSInt16) ||
          (custom_format == eFormatVectorOfSInt32) ||
          (custom_format == eFormatVectorOfSInt64) ||
          (custom_format == eFormatVectorOfSInt8) ||
          (custom_format == eFormatVectorOfUInt128) ||
          (custom_format == eFormatVectorOfUInt16) ||
          (custom_format == eFormatVectorOfUInt32) ||
          (custom_format == eFormatVectorOfUInt64) ||
          (custom_format == eFormatVectorOfUInt8))
        return true;
    }
  }
  return false;
}

bool ValueObject::DumpPrintableRepresentation(
    Stream &s, ValueObjectRepresentationStyle val_obj_display,
    Format custom_format, PrintableRepresentationSpecialCases special,
    bool do_dump_error) {

  // If the ValueObject has an error, we might end up dumping the type, which
  // is useful, but if we don't even have a type, then don't examine the object
  // further as that's not meaningful, only the error is.
  if (m_error.Fail() && !GetCompilerType().IsValid()) {
    if (do_dump_error)
      s.Printf("<%s>", m_error.AsCString());
    return false;
  }

  Flags flags(GetTypeInfo());

  bool allow_special =
      (special == ValueObject::PrintableRepresentationSpecialCases::eAllow);
  const bool only_special = false;

  if (allow_special) {
    if (flags.AnySet(eTypeIsArray | eTypeIsPointer) &&
        val_obj_display == ValueObject::eValueObjectRepresentationStyleValue) {
      // when being asked to get a printable display an array or pointer type
      // directly, try to "do the right thing"

      if (IsCStringContainer(true) &&
          (custom_format == eFormatCString ||
           custom_format == eFormatCharArray || custom_format == eFormatChar ||
           custom_format ==
               eFormatVectorOfChar)) // print char[] & char* directly
      {
        Status error;
        lldb::WritableDataBufferSP buffer_sp;
        std::pair<size_t, bool> read_string =
            ReadPointedString(buffer_sp, error,
                              (custom_format == eFormatVectorOfChar) ||
                                  (custom_format == eFormatCharArray));
        lldb_private::formatters::StringPrinter::
            ReadBufferAndDumpToStreamOptions options(*this);
        options.SetData(DataExtractor(
            buffer_sp, lldb::eByteOrderInvalid,
            8)); // none of this matters for a string - pass some defaults
        options.SetStream(&s);
        options.SetPrefixToken(nullptr);
        options.SetQuote('"');
        options.SetSourceSize(buffer_sp->GetByteSize());
        options.SetIsTruncated(read_string.second);
        options.SetBinaryZeroIsTerminator(custom_format != eFormatVectorOfChar);
        formatters::StringPrinter::ReadBufferAndDumpToStream<
            lldb_private::formatters::StringPrinter::StringElementType::ASCII>(
            options);
        return !error.Fail();
      }

      if (custom_format == eFormatEnum)
        return false;

      // this only works for arrays, because I have no way to know when the
      // pointed memory ends, and no special \0 end of data marker
      if (flags.Test(eTypeIsArray)) {
        if ((custom_format == eFormatBytes) ||
            (custom_format == eFormatBytesWithASCII)) {
          const size_t count = GetNumChildrenIgnoringErrors();

          s << '[';
          for (size_t low = 0; low < count; low++) {

            if (low)
              s << ',';

            ValueObjectSP child = GetChildAtIndex(low);
            if (!child.get()) {
              s << "<invalid child>";
              continue;
            }
            child->DumpPrintableRepresentation(
                s, ValueObject::eValueObjectRepresentationStyleValue,
                custom_format);
          }

          s << ']';

          return true;
        }

        if ((custom_format == eFormatVectorOfChar) ||
            (custom_format == eFormatVectorOfFloat32) ||
            (custom_format == eFormatVectorOfFloat64) ||
            (custom_format == eFormatVectorOfSInt16) ||
            (custom_format == eFormatVectorOfSInt32) ||
            (custom_format == eFormatVectorOfSInt64) ||
            (custom_format == eFormatVectorOfSInt8) ||
            (custom_format == eFormatVectorOfUInt128) ||
            (custom_format == eFormatVectorOfUInt16) ||
            (custom_format == eFormatVectorOfUInt32) ||
            (custom_format == eFormatVectorOfUInt64) ||
            (custom_format == eFormatVectorOfUInt8)) // arrays of bytes, bytes
                                                     // with ASCII or any vector
                                                     // format should be printed
                                                     // directly
        {
          const size_t count = GetNumChildrenIgnoringErrors();

          Format format = FormatManager::GetSingleItemFormat(custom_format);

          s << '[';
          for (size_t low = 0; low < count; low++) {

            if (low)
              s << ',';

            ValueObjectSP child = GetChildAtIndex(low);
            if (!child.get()) {
              s << "<invalid child>";
              continue;
            }
            child->DumpPrintableRepresentation(
                s, ValueObject::eValueObjectRepresentationStyleValue, format);
          }

          s << ']';

          return true;
        }
      }

      if ((custom_format == eFormatBoolean) ||
          (custom_format == eFormatBinary) || (custom_format == eFormatChar) ||
          (custom_format == eFormatCharPrintable) ||
          (custom_format == eFormatComplexFloat) ||
          (custom_format == eFormatDecimal) || (custom_format == eFormatHex) ||
          (custom_format == eFormatHexUppercase) ||
          (custom_format == eFormatFloat) ||
          (custom_format == eFormatFloat128) ||
          (custom_format == eFormatOctal) || (custom_format == eFormatOSType) ||
          (custom_format == eFormatUnicode16) ||
          (custom_format == eFormatUnicode32) ||
          (custom_format == eFormatUnsigned) ||
          (custom_format == eFormatPointer) ||
          (custom_format == eFormatComplexInteger) ||
          (custom_format == eFormatComplex) ||
          (custom_format == eFormatDefault)) // use the [] operator
        return false;
    }
  }

  if (only_special)
    return false;

  bool var_success = false;

  {
    llvm::StringRef str;

    // this is a local stream that we are using to ensure that the data pointed
    // to by cstr survives long enough for us to copy it to its destination -
    // it is necessary to have this temporary storage area for cases where our
    // desired output is not backed by some other longer-term storage
    StreamString strm;

    if (custom_format != eFormatInvalid)
      SetFormat(custom_format);

    switch (val_obj_display) {
    case eValueObjectRepresentationStyleValue:
      str = GetValueAsCString();
      break;

    case eValueObjectRepresentationStyleSummary:
      str = GetSummaryAsCString();
      break;

    case eValueObjectRepresentationStyleLanguageSpecific: {
      llvm::Expected<std::string> desc = GetObjectDescription();
      if (!desc) {
        strm << "error: " << toString(desc.takeError());
        str = strm.GetString();
      } else {
        strm << *desc;
        str = strm.GetString();
      }
    } break;

    case eValueObjectRepresentationStyleLocation:
      str = GetLocationAsCString();
      break;

    case eValueObjectRepresentationStyleChildrenCount: {
      if (auto err = GetNumChildren()) {
        strm.Printf("%" PRIu32, *err);
        str = strm.GetString();
      } else {
        strm << "error: " << toString(err.takeError());
        str = strm.GetString();
      }
      break;
    }

    case eValueObjectRepresentationStyleType:
      str = GetTypeName().GetStringRef();
      break;

    case eValueObjectRepresentationStyleName:
      str = GetName().GetStringRef();
      break;

    case eValueObjectRepresentationStyleExpressionPath:
      GetExpressionPath(strm);
      str = strm.GetString();
      break;
    }

    // If the requested display style produced no output, try falling back to
    // alternative presentations.
    if (str.empty()) {
      if (val_obj_display == eValueObjectRepresentationStyleValue)
        str = GetSummaryAsCString();
      else if (val_obj_display == eValueObjectRepresentationStyleSummary) {
        if (!CanProvideValue()) {
          strm.Printf("%s @ %s", GetTypeName().AsCString(),
                      GetLocationAsCString());
          str = strm.GetString();
        } else
          str = GetValueAsCString();
      }
    }

    if (!str.empty())
      s << str;
    else {
      // We checked for errors at the start, but do it again here in case
      // realizing the value for dumping produced an error.
      if (m_error.Fail()) {
        if (do_dump_error)
          s.Printf("<%s>", m_error.AsCString());
        else
          return false;
      } else if (val_obj_display == eValueObjectRepresentationStyleSummary)
        s.PutCString("<no summary available>");
      else if (val_obj_display == eValueObjectRepresentationStyleValue)
        s.PutCString("<no value available>");
      else if (val_obj_display ==
               eValueObjectRepresentationStyleLanguageSpecific)
        s.PutCString("<not a valid Objective-C object>"); // edit this if we
                                                          // have other runtimes
                                                          // that support a
                                                          // description
      else
        s.PutCString("<no printable representation>");
    }

    // we should only return false here if we could not do *anything* even if
    // we have an error message as output, that's a success from our callers'
    // perspective, so return true
    var_success = true;

    if (custom_format != eFormatInvalid)
      SetFormat(eFormatDefault);
  }

  return var_success;
}

ValueObject::AddrAndType
ValueObject::GetAddressOf(bool scalar_is_load_address) {
  // Can't take address of a bitfield
  if (IsBitfield())
    return {};

  if (!UpdateValueIfNeeded(false))
    return {};

  switch (m_value.GetValueType()) {
  case Value::ValueType::Invalid:
    return {};
  case Value::ValueType::Scalar:
    if (scalar_is_load_address) {
      return {m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS),
              eAddressTypeLoad};
    }
    return {};

  case Value::ValueType::LoadAddress:
  case Value::ValueType::FileAddress:
    return {m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS),
            m_value.GetValueAddressType()};
  case Value::ValueType::HostAddress:
    return {LLDB_INVALID_ADDRESS, m_value.GetValueAddressType()};
  }
  llvm_unreachable("Unhandled value type!");
}

ValueObject::AddrAndType ValueObject::GetPointerValue() {
  if (!UpdateValueIfNeeded(false))
    return {};

  switch (m_value.GetValueType()) {
  case Value::ValueType::Invalid:
    return {};
  case Value::ValueType::Scalar:
    return {m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS),
            GetAddressTypeOfChildren()};

  case Value::ValueType::HostAddress:
  case Value::ValueType::LoadAddress:
  case Value::ValueType::FileAddress: {
    lldb::offset_t data_offset = 0;
    return {m_data.GetAddress(&data_offset), GetAddressTypeOfChildren()};
  }
  }

  llvm_unreachable("Unhandled value type!");
}

static const char *ConvertBoolean(lldb::LanguageType language_type,
                                  const char *value_str) {
  if (Language *language = Language::FindPlugin(language_type))
    if (auto boolean = language->GetBooleanFromString(value_str))
      return *boolean ? "1" : "0";

  return llvm::StringSwitch<const char *>(value_str)
      .Case("true", "1")
      .Case("false", "0")
      .Default(value_str);
}

bool ValueObject::SetValueFromCString(const char *value_str, Status &error) {
  error.Clear();
  // Make sure our value is up to date first so that our location and location
  // type is valid.
  if (!UpdateValueIfNeeded(false)) {
    error = Status::FromErrorString("unable to read value");
    return false;
  }

  const Encoding encoding = GetCompilerType().GetEncoding();

  const size_t byte_size = llvm::expectedToOptional(GetByteSize()).value_or(0);

  Value::ValueType value_type = m_value.GetValueType();

  if (value_type == Value::ValueType::Scalar) {
    // If the value is already a scalar, then let the scalar change itself:
    m_value.GetScalar().SetValueFromCString(value_str, encoding, byte_size);
  } else if (byte_size <= 16) {
    if (GetCompilerType().IsBoolean())
      value_str = ConvertBoolean(GetObjectRuntimeLanguage(), value_str);

    // If the value fits in a scalar, then make a new scalar and again let the
    // scalar code do the conversion, then figure out where to put the new
    // value.
    Scalar new_scalar;
    error = new_scalar.SetValueFromCString(value_str, encoding, byte_size);
    if (error.Success()) {
      switch (value_type) {
      case Value::ValueType::LoadAddress: {
        // If it is a load address, then the scalar value is the storage
        // location of the data, and we have to shove this value down to that
        // load location.
        ExecutionContext exe_ctx(GetExecutionContextRef());
        Process *process = exe_ctx.GetProcessPtr();
        if (process) {
          addr_t target_addr =
              m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
          size_t bytes_written = process->WriteScalarToMemory(
              target_addr, new_scalar, byte_size, error);
          if (!error.Success())
            return false;
          if (bytes_written != byte_size) {
            error = Status::FromErrorString("unable to write value to memory");
            return false;
          }
        }
      } break;
      case Value::ValueType::HostAddress: {
        // If it is a host address, then we stuff the scalar as a DataBuffer
        // into the Value's data.
        DataExtractor new_data;
        new_data.SetByteOrder(m_data.GetByteOrder());

        DataBufferSP buffer_sp(new DataBufferHeap(byte_size, 0));
        m_data.SetData(buffer_sp, 0);
        bool success = new_scalar.GetData(new_data);
        if (success) {
          new_data.CopyByteOrderedData(
              0, byte_size, const_cast<uint8_t *>(m_data.GetDataStart()),
              byte_size, m_data.GetByteOrder());
        }
        m_value.GetScalar() = (uintptr_t)m_data.GetDataStart();

      } break;
      case Value::ValueType::Invalid:
        error = Status::FromErrorString("invalid location");
        return false;
      case Value::ValueType::FileAddress:
      case Value::ValueType::Scalar:
        break;
      }
    } else {
      return false;
    }
  } else {
    // We don't support setting things bigger than a scalar at present.
    error = Status::FromErrorString("unable to write aggregate data type");
    return false;
  }

  // If we have reached this point, then we have successfully changed the
  // value.
  SetNeedsUpdate();
  return true;
}

bool ValueObject::GetDeclaration(Declaration &decl) {
  decl.Clear();
  return false;
}

void ValueObject::AddSyntheticChild(ConstString key, ValueObject *valobj) {
  m_synthetic_children[key] = valobj;
}

ValueObjectSP ValueObject::GetSyntheticChild(ConstString key) const {
  ValueObjectSP synthetic_child_sp;
  std::map<ConstString, ValueObject *>::const_iterator pos =
      m_synthetic_children.find(key);
  if (pos != m_synthetic_children.end())
    synthetic_child_sp = pos->second->GetSP();
  return synthetic_child_sp;
}

bool ValueObject::IsPossibleDynamicType() {
  ExecutionContext exe_ctx(GetExecutionContextRef());
  Process *process = exe_ctx.GetProcessPtr();
  if (process)
    return process->IsPossibleDynamicValue(*this);
  else
    return GetCompilerType().IsPossibleDynamicType(nullptr, true, true);
}

bool ValueObject::IsRuntimeSupportValue() {
  Process *process(GetProcessSP().get());
  if (!process)
    return false;

  // We trust that the compiler did the right thing and marked runtime support
  // values as artificial.
  if (!GetVariable() || !GetVariable()->IsArtificial())
    return false;

  if (auto *runtime = process->GetLanguageRuntime(GetVariable()->GetLanguage()))
    if (runtime->IsAllowedRuntimeValue(GetName()))
      return false;

  return true;
}

bool ValueObject::IsNilReference() {
  if (Language *language = Language::FindPlugin(GetObjectRuntimeLanguage())) {
    return language->IsNilReference(*this);
  }
  return false;
}

bool ValueObject::IsUninitializedReference() {
  if (Language *language = Language::FindPlugin(GetObjectRuntimeLanguage())) {
    return language->IsUninitializedReference(*this);
  }
  return false;
}

// This allows you to create an array member using and index that doesn't not
// fall in the normal bounds of the array. Many times structure can be defined
// as: struct Collection {
//     uint32_t item_count;
//     Item item_array[0];
// };
// The size of the "item_array" is 1, but many times in practice there are more
// items in "item_array".

ValueObjectSP ValueObject::GetSyntheticArrayMember(size_t index,
                                                   bool can_create) {
  ValueObjectSP synthetic_child_sp;
  if (IsPointerType() || IsArrayType()) {
    std::string index_str = llvm::formatv("[{0}]", index);
    ConstString index_const_str(index_str);
    // Check if we have already created a synthetic array member in this valid
    // object. If we have we will re-use it.
    synthetic_child_sp = GetSyntheticChild(index_const_str);
    if (!synthetic_child_sp) {
      ValueObject *synthetic_child;
      // We haven't made a synthetic array member for INDEX yet, so lets make
      // one and cache it for any future reference.
      synthetic_child = CreateSyntheticArrayMember(index);

      // Cache the value if we got one back...
      if (synthetic_child) {
        AddSyntheticChild(index_const_str, synthetic_child);
        synthetic_child_sp = synthetic_child->GetSP();
        synthetic_child_sp->SetName(ConstString(index_str));
        synthetic_child_sp->m_flags.m_is_array_item_for_pointer = true;
      }
    }
  }
  return synthetic_child_sp;
}

ValueObjectSP ValueObject::GetSyntheticBitFieldChild(uint32_t from, uint32_t to,
                                                     bool can_create) {
  ValueObjectSP synthetic_child_sp;
  if (IsScalarType()) {
    std::string index_str = llvm::formatv("[{0}-{1}]", from, to);
    ConstString index_const_str(index_str);
    // Check if we have already created a synthetic array member in this valid
    // object. If we have we will re-use it.
    synthetic_child_sp = GetSyntheticChild(index_const_str);
    if (!synthetic_child_sp) {
      uint32_t bit_field_size = to - from + 1;
      uint32_t bit_field_offset = from;
      if (GetDataExtractor().GetByteOrder() == eByteOrderBig)
        bit_field_offset =
            llvm::expectedToOptional(GetByteSize()).value_or(0) * 8 -
            bit_field_size - bit_field_offset;
      // We haven't made a synthetic array member for INDEX yet, so lets make
      // one and cache it for any future reference.
      ValueObjectChild *synthetic_child = new ValueObjectChild(
          *this, GetCompilerType(), index_const_str,
          llvm::expectedToOptional(GetByteSize()).value_or(0), 0,
          bit_field_size, bit_field_offset, false, false, eAddressTypeInvalid,
          0);

      // Cache the value if we got one back...
      if (synthetic_child) {
        AddSyntheticChild(index_const_str, synthetic_child);
        synthetic_child_sp = synthetic_child->GetSP();
        synthetic_child_sp->SetName(ConstString(index_str));
        synthetic_child_sp->m_flags.m_is_bitfield_for_scalar = true;
      }
    }
  }
  return synthetic_child_sp;
}

ValueObjectSP ValueObject::GetSyntheticChildAtOffset(
    uint32_t offset, const CompilerType &type, bool can_create,
    ConstString name_const_str) {

  ValueObjectSP synthetic_child_sp;

  if (name_const_str.IsEmpty()) {
    name_const_str.SetString("@" + std::to_string(offset));
  }

  // Check if we have already created a synthetic array member in this valid
  // object. If we have we will re-use it.
  synthetic_child_sp = GetSyntheticChild(name_const_str);

  if (synthetic_child_sp.get())
    return synthetic_child_sp;

  if (!can_create)
    return {};

  ExecutionContext exe_ctx(GetExecutionContextRef());
  std::optional<uint64_t> size = llvm::expectedToOptional(
      type.GetByteSize(exe_ctx.GetBestExecutionContextScope()));
  if (!size)
    return {};
  ValueObjectChild *synthetic_child =
      new ValueObjectChild(*this, type, name_const_str, *size, offset, 0, 0,
                           false, false, eAddressTypeInvalid, 0);
  if (synthetic_child) {
    AddSyntheticChild(name_const_str, synthetic_child);
    synthetic_child_sp = synthetic_child->GetSP();
    synthetic_child_sp->SetName(name_const_str);
    synthetic_child_sp->m_flags.m_is_child_at_offset = true;
  }
  return synthetic_child_sp;
}

ValueObjectSP ValueObject::GetSyntheticBase(uint32_t offset,
                                            const CompilerType &type,
                                            bool can_create,
                                            ConstString name_const_str) {
  ValueObjectSP synthetic_child_sp;

  if (name_const_str.IsEmpty()) {
    char name_str[128];
    snprintf(name_str, sizeof(name_str), "base%s@%i",
             type.GetTypeName().AsCString("<unknown>"), offset);
    name_const_str.SetCString(name_str);
  }

  // Check if we have already created a synthetic array member in this valid
  // object. If we have we will re-use it.
  synthetic_child_sp = GetSyntheticChild(name_const_str);

  if (synthetic_child_sp.get())
    return synthetic_child_sp;

  if (!can_create)
    return {};

  const bool is_base_class = true;

  ExecutionContext exe_ctx(GetExecutionContextRef());
  std::optional<uint64_t> size = llvm::expectedToOptional(
      type.GetByteSize(exe_ctx.GetBestExecutionContextScope()));
  if (!size)
    return {};
  ValueObjectChild *synthetic_child =
      new ValueObjectChild(*this, type, name_const_str, *size, offset, 0, 0,
                           is_base_class, false, eAddressTypeInvalid, 0);
  if (synthetic_child) {
    AddSyntheticChild(name_const_str, synthetic_child);
    synthetic_child_sp = synthetic_child->GetSP();
    synthetic_child_sp->SetName(name_const_str);
  }
  return synthetic_child_sp;
}

// your expression path needs to have a leading . or -> (unless it somehow
// "looks like" an array, in which case it has a leading [ symbol). while the [
// is meaningful and should be shown to the user, . and -> are just parser
// design, but by no means added information for the user.. strip them off
static const char *SkipLeadingExpressionPathSeparators(const char *expression) {
  if (!expression || !expression[0])
    return expression;
  if (expression[0] == '.')
    return expression + 1;
  if (expression[0] == '-' && expression[1] == '>')
    return expression + 2;
  return expression;
}

ValueObjectSP
ValueObject::GetSyntheticExpressionPathChild(const char *expression,
                                             bool can_create) {
  ValueObjectSP synthetic_child_sp;
  ConstString name_const_string(expression);
  // Check if we have already created a synthetic array member in this valid
  // object. If we have we will re-use it.
  synthetic_child_sp = GetSyntheticChild(name_const_string);
  if (!synthetic_child_sp) {
    // We haven't made a synthetic array member for expression yet, so lets
    // make one and cache it for any future reference.
    synthetic_child_sp = GetValueForExpressionPath(
        expression, nullptr, nullptr,
        GetValueForExpressionPathOptions().SetSyntheticChildrenTraversal(
            GetValueForExpressionPathOptions::SyntheticChildrenTraversal::
                None));

    // Cache the value if we got one back...
    if (synthetic_child_sp.get()) {
      // FIXME: this causes a "real" child to end up with its name changed to
      // the contents of expression
      AddSyntheticChild(name_const_string, synthetic_child_sp.get());
      synthetic_child_sp->SetName(
          ConstString(SkipLeadingExpressionPathSeparators(expression)));
    }
  }
  return synthetic_child_sp;
}

void ValueObject::CalculateSyntheticValue() {
  TargetSP target_sp(GetTargetSP());
  if (target_sp && !target_sp->GetEnableSyntheticValue()) {
    m_synthetic_value = nullptr;
    return;
  }

  lldb::SyntheticChildrenSP current_synth_sp(m_synthetic_children_sp);

  if (!UpdateFormatsIfNeeded() && m_synthetic_value)
    return;

  if (m_synthetic_children_sp.get() == nullptr)
    return;

  if (current_synth_sp == m_synthetic_children_sp && m_synthetic_value)
    return;

  m_synthetic_value = new ValueObjectSynthetic(*this, m_synthetic_children_sp);
}

void ValueObject::CalculateDynamicValue(DynamicValueType use_dynamic) {
  if (use_dynamic == eNoDynamicValues)
    return;

  if (!m_dynamic_value && !IsDynamic()) {
    ExecutionContext exe_ctx(GetExecutionContextRef());
    Process *process = exe_ctx.GetProcessPtr();
    if (process && process->IsPossibleDynamicValue(*this)) {
      ClearDynamicTypeInformation();
      m_dynamic_value = new ValueObjectDynamicValue(*this, use_dynamic);
    }
  }
}

ValueObjectSP ValueObject::GetDynamicValue(DynamicValueType use_dynamic) {
  if (use_dynamic == eNoDynamicValues)
    return ValueObjectSP();

  if (!IsDynamic() && m_dynamic_value == nullptr) {
    CalculateDynamicValue(use_dynamic);
  }
  if (m_dynamic_value && m_dynamic_value->GetError().Success())
    return m_dynamic_value->GetSP();
  else
    return ValueObjectSP();
}

ValueObjectSP ValueObject::GetSyntheticValue() {
  CalculateSyntheticValue();

  if (m_synthetic_value)
    return m_synthetic_value->GetSP();
  else
    return ValueObjectSP();
}

bool ValueObject::HasSyntheticValue() {
  UpdateFormatsIfNeeded();

  if (m_synthetic_children_sp.get() == nullptr)
    return false;

  CalculateSyntheticValue();

  return m_synthetic_value != nullptr;
}

ValueObject *ValueObject::GetNonBaseClassParent() {
  if (GetParent()) {
    if (GetParent()->IsBaseClass())
      return GetParent()->GetNonBaseClassParent();
    else
      return GetParent();
  }
  return nullptr;
}

bool ValueObject::IsBaseClass(uint32_t &depth) {
  if (!IsBaseClass()) {
    depth = 0;
    return false;
  }
  if (GetParent()) {
    GetParent()->IsBaseClass(depth);
    depth = depth + 1;
    return true;
  }
  // TODO: a base of no parent? weird..
  depth = 1;
  return true;
}

void ValueObject::GetExpressionPath(Stream &s,
                                    GetExpressionPathFormat epformat) {
  // synthetic children do not actually "exist" as part of the hierarchy, and
  // sometimes they are consed up in ways that don't make sense from an
  // underlying language/API standpoint. So, use a special code path here to
  // return something that can hopefully be used in expression
  if (m_flags.m_is_synthetic_children_generated) {
    UpdateValueIfNeeded();

    if (m_value.GetValueType() == Value::ValueType::LoadAddress) {
      if (IsPointerOrReferenceType()) {
        s.Printf("((%s)0x%" PRIx64 ")", GetTypeName().AsCString("void"),
                 GetValueAsUnsigned(0));
        return;
      } else {
        uint64_t load_addr =
            m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
        if (load_addr != LLDB_INVALID_ADDRESS) {
          s.Printf("(*( (%s *)0x%" PRIx64 "))", GetTypeName().AsCString("void"),
                   load_addr);
          return;
        }
      }
    }

    if (CanProvideValue()) {
      s.Printf("((%s)%s)", GetTypeName().AsCString("void"),
               GetValueAsCString());
      return;
    }

    return;
  }

  const bool is_deref_of_parent = IsDereferenceOfParent();

  if (is_deref_of_parent &&
      epformat == eGetExpressionPathFormatDereferencePointers) {
    // this is the original format of GetExpressionPath() producing code like
    // *(a_ptr).memberName, which is entirely fine, until you put this into
    // StackFrame::GetValueForVariableExpressionPath() which prefers to see
    // a_ptr->memberName. the eHonorPointers mode is meant to produce strings
    // in this latter format
    s.PutCString("*(");
  }

  ValueObject *parent = GetParent();

  if (parent) {
    parent->GetExpressionPath(s, epformat);
    const CompilerType parentType = parent->GetCompilerType();
    if (parentType.IsPointerType() &&
        parentType.GetPointeeType().IsArrayType(nullptr, nullptr, nullptr)) {
      // When the parent is a pointer to an array, then we have to:
      // - follow the expression path of the parent with "[0]"
      //   (that will indicate dereferencing the pointer to the array)
      // - and then follow that with this ValueObject's name
      //   (which will be something like "[i]" to indicate
      //    the i-th element of the array)
      s.PutCString("[0]");
      s.PutCString(GetName().GetCString());
      return;
    }
  }

  // if we are a deref_of_parent just because we are synthetic array members
  // made up to allow ptr[%d] syntax to work in variable printing, then add our
  // name ([%d]) to the expression path
  if (m_flags.m_is_array_item_for_pointer &&
      epformat == eGetExpressionPathFormatHonorPointers)
    s.PutCString(m_name.GetStringRef());

  if (!IsBaseClass()) {
    if (!is_deref_of_parent) {
      ValueObject *non_base_class_parent = GetNonBaseClassParent();
      if (non_base_class_parent &&
          !non_base_class_parent->GetName().IsEmpty()) {
        CompilerType non_base_class_parent_compiler_type =
            non_base_class_parent->GetCompilerType();
        if (non_base_class_parent_compiler_type) {
          if (parent && parent->IsDereferenceOfParent() &&
              epformat == eGetExpressionPathFormatHonorPointers) {
            s.PutCString("->");
          } else {
            const uint32_t non_base_class_parent_type_info =
                non_base_class_parent_compiler_type.GetTypeInfo();

            if (non_base_class_parent_type_info & eTypeIsPointer) {
              s.PutCString("->");
            } else if ((non_base_class_parent_type_info & eTypeHasChildren) &&
                       !(non_base_class_parent_type_info & eTypeIsArray)) {
              s.PutChar('.');
            }
          }
        }
      }

      const char *name = GetName().GetCString();
      if (name)
        s.PutCString(name);
    }
  }

  if (is_deref_of_parent &&
      epformat == eGetExpressionPathFormatDereferencePointers) {
    s.PutChar(')');
  }
}

// Return the alternate value (synthetic if the input object is non-synthetic
// and otherwise) this is permitted by the expression path options.
static ValueObjectSP GetAlternateValue(
    ValueObject &valobj,
    ValueObject::GetValueForExpressionPathOptions::SyntheticChildrenTraversal
        synth_traversal) {
  using SynthTraversal =
      ValueObject::GetValueForExpressionPathOptions::SyntheticChildrenTraversal;

  if (valobj.IsSynthetic()) {
    if (synth_traversal == SynthTraversal::FromSynthetic ||
        synth_traversal == SynthTraversal::Both)
      return valobj.GetNonSyntheticValue();
  } else {
    if (synth_traversal == SynthTraversal::ToSynthetic ||
        synth_traversal == SynthTraversal::Both)
      return valobj.GetSyntheticValue();
  }
  return nullptr;
}

// Dereference the provided object or the alternate value, if permitted by the
// expression path options.
static ValueObjectSP DereferenceValueOrAlternate(
    ValueObject &valobj,
    ValueObject::GetValueForExpressionPathOptions::SyntheticChildrenTraversal
        synth_traversal,
    Status &error) {
  error.Clear();
  ValueObjectSP result = valobj.Dereference(error);
  if (!result || error.Fail()) {
    if (ValueObjectSP alt_obj = GetAlternateValue(valobj, synth_traversal)) {
      error.Clear();
      result = alt_obj->Dereference(error);
    }
  }
  return result;
}

ValueObjectSP ValueObject::GetValueForExpressionPath(
    llvm::StringRef expression, ExpressionPathScanEndReason *reason_to_stop,
    ExpressionPathEndResultType *final_value_type,
    const GetValueForExpressionPathOptions &options,
    ExpressionPathAftermath *final_task_on_target) {

  ExpressionPathScanEndReason dummy_reason_to_stop =
      ValueObject::eExpressionPathScanEndReasonUnknown;
  ExpressionPathEndResultType dummy_final_value_type =
      ValueObject::eExpressionPathEndResultTypeInvalid;
  ExpressionPathAftermath dummy_final_task_on_target =
      ValueObject::eExpressionPathAftermathNothing;

  ValueObjectSP ret_val = GetValueForExpressionPath_Impl(
      expression, reason_to_stop ? reason_to_stop : &dummy_reason_to_stop,
      final_value_type ? final_value_type : &dummy_final_value_type, options,
      final_task_on_target ? final_task_on_target
                           : &dummy_final_task_on_target);

  if (!final_task_on_target ||
      *final_task_on_target == ValueObject::eExpressionPathAftermathNothing)
    return ret_val;

  if (ret_val.get() &&
      ((final_value_type ? *final_value_type : dummy_final_value_type) ==
       eExpressionPathEndResultTypePlain)) // I can only deref and takeaddress
                                           // of plain objects
  {
    if ((final_task_on_target ? *final_task_on_target
                              : dummy_final_task_on_target) ==
        ValueObject::eExpressionPathAftermathDereference) {
      Status error;
      ValueObjectSP final_value = DereferenceValueOrAlternate(
          *ret_val, options.m_synthetic_children_traversal, error);
      if (error.Fail() || !final_value.get()) {
        if (reason_to_stop)
          *reason_to_stop =
              ValueObject::eExpressionPathScanEndReasonDereferencingFailed;
        if (final_value_type)
          *final_value_type = ValueObject::eExpressionPathEndResultTypeInvalid;
        return ValueObjectSP();
      } else {
        if (final_task_on_target)
          *final_task_on_target = ValueObject::eExpressionPathAftermathNothing;
        return final_value;
      }
    }
    if (*final_task_on_target ==
        ValueObject::eExpressionPathAftermathTakeAddress) {
      Status error;
      ValueObjectSP final_value = ret_val->AddressOf(error);
      if (error.Fail() || !final_value.get()) {
        if (reason_to_stop)
          *reason_to_stop =
              ValueObject::eExpressionPathScanEndReasonTakingAddressFailed;
        if (final_value_type)
          *final_value_type = ValueObject::eExpressionPathEndResultTypeInvalid;
        return ValueObjectSP();
      } else {
        if (final_task_on_target)
          *final_task_on_target = ValueObject::eExpressionPathAftermathNothing;
        return final_value;
      }
    }
  }
  return ret_val; // final_task_on_target will still have its original value, so
                  // you know I did not do it
}

ValueObjectSP ValueObject::GetValueForExpressionPath_Impl(
    llvm::StringRef expression, ExpressionPathScanEndReason *reason_to_stop,
    ExpressionPathEndResultType *final_result,
    const GetValueForExpressionPathOptions &options,
    ExpressionPathAftermath *what_next) {
  ValueObjectSP root = GetSP();

  if (!root)
    return nullptr;

  llvm::StringRef remainder = expression;

  while (true) {
    llvm::StringRef temp_expression = remainder;

    CompilerType root_compiler_type = root->GetCompilerType();
    CompilerType pointee_compiler_type;
    Flags pointee_compiler_type_info;

    Flags root_compiler_type_info(
        root_compiler_type.GetTypeInfo(&pointee_compiler_type));
    if (pointee_compiler_type)
      pointee_compiler_type_info.Reset(pointee_compiler_type.GetTypeInfo());

    if (temp_expression.empty()) {
      *reason_to_stop = ValueObject::eExpressionPathScanEndReasonEndOfString;
      return root;
    }

    switch (temp_expression.front()) {
    case '-': {
      temp_expression = temp_expression.drop_front();
      if (options.m_check_dot_vs_arrow_syntax &&
          root_compiler_type_info.Test(eTypeIsPointer)) // if you are trying to
                                                        // use -> on a
                                                        // non-pointer and I
                                                        // must catch the error
      {
        *reason_to_stop =
            ValueObject::eExpressionPathScanEndReasonArrowInsteadOfDot;
        *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
        return ValueObjectSP();
      }
      if (root_compiler_type_info.Test(eTypeIsObjC) && // if yo are trying to
                                                       // extract an ObjC IVar
                                                       // when this is forbidden
          root_compiler_type_info.Test(eTypeIsPointer) &&
          options.m_no_fragile_ivar) {
        *reason_to_stop =
            ValueObject::eExpressionPathScanEndReasonFragileIVarNotAllowed;
        *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
        return ValueObjectSP();
      }
      if (!temp_expression.starts_with(">")) {
        *reason_to_stop =
            ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol;
        *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
        return ValueObjectSP();
      }
    }
      [[fallthrough]];
    case '.': // or fallthrough from ->
    {
      if (options.m_check_dot_vs_arrow_syntax &&
          temp_expression.front() == '.' &&
          root_compiler_type_info.Test(eTypeIsPointer)) // if you are trying to
                                                        // use . on a pointer
                                                        // and I must catch the
                                                        // error
      {
        *reason_to_stop =
            ValueObject::eExpressionPathScanEndReasonDotInsteadOfArrow;
        *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
        return nullptr;
      }
      temp_expression = temp_expression.drop_front(); // skip . or >

      size_t next_sep_pos = temp_expression.find_first_of("-.[", 1);
      if (next_sep_pos == llvm::StringRef::npos) {
        // if no other separator just expand this last layer
        llvm::StringRef child_name = temp_expression;
        ValueObjectSP child_valobj_sp =
            root->GetChildMemberWithName(child_name);
        if (!child_valobj_sp) {
          if (ValueObjectSP altroot = GetAlternateValue(
                  *root, options.m_synthetic_children_traversal))
            child_valobj_sp = altroot->GetChildMemberWithName(child_name);
        }
        if (child_valobj_sp) {
          *reason_to_stop =
              ValueObject::eExpressionPathScanEndReasonEndOfString;
          *final_result = ValueObject::eExpressionPathEndResultTypePlain;
          return child_valobj_sp;
        }
        *reason_to_stop = ValueObject::eExpressionPathScanEndReasonNoSuchChild;
        *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
        return nullptr;
      }

      llvm::StringRef next_separator = temp_expression.substr(next_sep_pos);
      llvm::StringRef child_name = temp_expression.slice(0, next_sep_pos);

      ValueObjectSP child_valobj_sp = root->GetChildMemberWithName(child_name);
      if (!child_valobj_sp) {
        if (ValueObjectSP altroot = GetAlternateValue(
                *root, options.m_synthetic_children_traversal))
          child_valobj_sp = altroot->GetChildMemberWithName(child_name);
      }
      if (child_valobj_sp) {
        root = child_valobj_sp;
        remainder = next_separator;
        *final_result = ValueObject::eExpressionPathEndResultTypePlain;
        continue;
      }
      *reason_to_stop = ValueObject::eExpressionPathScanEndReasonNoSuchChild;
      *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
      return nullptr;
    }
    case '[': {
      if (!root_compiler_type_info.Test(eTypeIsArray) &&
          !root_compiler_type_info.Test(eTypeIsPointer) &&
          !root_compiler_type_info.Test(
              eTypeIsVector)) // if this is not a T[] nor a T*
      {
        if (!root_compiler_type_info.Test(
                eTypeIsScalar)) // if this is not even a scalar...
        {
          if (options.m_synthetic_children_traversal ==
              GetValueForExpressionPathOptions::SyntheticChildrenTraversal::
                  None) // ...only chance left is synthetic
          {
            *reason_to_stop =
                ValueObject::eExpressionPathScanEndReasonRangeOperatorInvalid;
            *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
            return ValueObjectSP();
          }
        } else if (!options.m_allow_bitfields_syntax) // if this is a scalar,
                                                      // check that we can
                                                      // expand bitfields
        {
          *reason_to_stop =
              ValueObject::eExpressionPathScanEndReasonRangeOperatorNotAllowed;
          *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
          return ValueObjectSP();
        }
      }
      if (temp_expression[1] ==
          ']') // if this is an unbounded range it only works for arrays
      {
        if (!root_compiler_type_info.Test(eTypeIsArray)) {
          *reason_to_stop =
              ValueObject::eExpressionPathScanEndReasonEmptyRangeNotAllowed;
          *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
          return nullptr;
        } else // even if something follows, we cannot expand unbounded ranges,
               // just let the caller do it
        {
          *reason_to_stop =
              ValueObject::eExpressionPathScanEndReasonArrayRangeOperatorMet;
          *final_result =
              ValueObject::eExpressionPathEndResultTypeUnboundedRange;
          return root;
        }
      }

      size_t close_bracket_position = temp_expression.find(']', 1);
      if (close_bracket_position ==
          llvm::StringRef::npos) // if there is no ], this is a syntax error
      {
        *reason_to_stop =
            ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol;
        *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
        return nullptr;
      }

      llvm::StringRef bracket_expr =
          temp_expression.slice(1, close_bracket_position);

      // If this was an empty expression it would have been caught by the if
      // above.
      assert(!bracket_expr.empty());

      if (!bracket_expr.contains('-')) {
        // if no separator, this is of the form [N].  Note that this cannot be
        // an unbounded range of the form [], because that case was handled
        // above with an unconditional return.
        unsigned long index = 0;
        if (bracket_expr.getAsInteger(0, index)) {
          *reason_to_stop =
              ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol;
          *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
          return nullptr;
        }

        // from here on we do have a valid index
        if (root_compiler_type_info.Test(eTypeIsArray)) {
          ValueObjectSP child_valobj_sp = root->GetChildAtIndex(index);
          if (!child_valobj_sp)
            child_valobj_sp = root->GetSyntheticArrayMember(index, true);
          if (!child_valobj_sp)
            if (root->HasSyntheticValue() &&
                llvm::expectedToStdOptional(
                    root->GetSyntheticValue()->GetNumChildren())
                        .value_or(0) > index)
              child_valobj_sp =
                  root->GetSyntheticValue()->GetChildAtIndex(index);
          if (child_valobj_sp) {
            root = child_valobj_sp;
            remainder =
                temp_expression.substr(close_bracket_position + 1); // skip ]
            *final_result = ValueObject::eExpressionPathEndResultTypePlain;
            continue;
          } else {
            *reason_to_stop =
                ValueObject::eExpressionPathScanEndReasonNoSuchChild;
            *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
            return nullptr;
          }
        } else if (root_compiler_type_info.Test(eTypeIsPointer)) {
          if (*what_next ==
                  ValueObject::
                      eExpressionPathAftermathDereference && // if this is a
                                                             // ptr-to-scalar, I
                                                             // am accessing it
                                                             // by index and I
                                                             // would have
                                                             // deref'ed anyway,
                                                             // then do it now
                                                             // and use this as
                                                             // a bitfield
              pointee_compiler_type_info.Test(eTypeIsScalar)) {
            Status error;
            root = DereferenceValueOrAlternate(
                *root, options.m_synthetic_children_traversal, error);
            if (error.Fail() || !root) {
              *reason_to_stop =
                  ValueObject::eExpressionPathScanEndReasonDereferencingFailed;
              *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
              return nullptr;
            } else {
              *what_next = eExpressionPathAftermathNothing;
              continue;
            }
          } else {
            if (root->GetCompilerType().GetMinimumLanguage() ==
                    eLanguageTypeObjC &&
                pointee_compiler_type_info.AllClear(eTypeIsPointer) &&
                root->HasSyntheticValue() &&
                (options.m_synthetic_children_traversal ==
                     GetValueForExpressionPathOptions::
                         SyntheticChildrenTraversal::ToSynthetic ||
                 options.m_synthetic_children_traversal ==
                     GetValueForExpressionPathOptions::
                         SyntheticChildrenTraversal::Both)) {
              root = root->GetSyntheticValue()->GetChildAtIndex(index);
            } else
              root = root->GetSyntheticArrayMember(index, true);
            if (!root) {
              *reason_to_stop =
                  ValueObject::eExpressionPathScanEndReasonNoSuchChild;
              *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
              return nullptr;
            } else {
              remainder =
                  temp_expression.substr(close_bracket_position + 1); // skip ]
              *final_result = ValueObject::eExpressionPathEndResultTypePlain;
              continue;
            }
          }
        } else if (root_compiler_type_info.Test(eTypeIsScalar)) {
          root = root->GetSyntheticBitFieldChild(index, index, true);
          if (!root) {
            *reason_to_stop =
                ValueObject::eExpressionPathScanEndReasonNoSuchChild;
            *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
            return nullptr;
          } else // we do not know how to expand members of bitfields, so we
                 // just return and let the caller do any further processing
          {
            *reason_to_stop = ValueObject::
                eExpressionPathScanEndReasonBitfieldRangeOperatorMet;
            *final_result = ValueObject::eExpressionPathEndResultTypeBitfield;
            return root;
          }
        } else if (root_compiler_type_info.Test(eTypeIsVector)) {
          root = root->GetChildAtIndex(index);
          if (!root) {
            *reason_to_stop =
                ValueObject::eExpressionPathScanEndReasonNoSuchChild;
            *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
            return ValueObjectSP();
          } else {
            remainder =
                temp_expression.substr(close_bracket_position + 1); // skip ]
            *final_result = ValueObject::eExpressionPathEndResultTypePlain;
            continue;
          }
        } else if (options.m_synthetic_children_traversal ==
                       GetValueForExpressionPathOptions::
                           SyntheticChildrenTraversal::ToSynthetic ||
                   options.m_synthetic_children_traversal ==
                       GetValueForExpressionPathOptions::
                           SyntheticChildrenTraversal::Both) {
          if (root->HasSyntheticValue())
            root = root->GetSyntheticValue();
          else if (!root->IsSynthetic()) {
            *reason_to_stop =
                ValueObject::eExpressionPathScanEndReasonSyntheticValueMissing;
            *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
            return nullptr;
          }
          // if we are here, then root itself is a synthetic VO.. should be
          // good to go

          if (!root) {
            *reason_to_stop =
                ValueObject::eExpressionPathScanEndReasonSyntheticValueMissing;
            *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
            return nullptr;
          }
          root = root->GetChildAtIndex(index);
          if (!root) {
            *reason_to_stop =
                ValueObject::eExpressionPathScanEndReasonNoSuchChild;
            *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
            return nullptr;
          } else {
            remainder =
                temp_expression.substr(close_bracket_position + 1); // skip ]
            *final_result = ValueObject::eExpressionPathEndResultTypePlain;
            continue;
          }
        } else {
          *reason_to_stop =
              ValueObject::eExpressionPathScanEndReasonNoSuchChild;
          *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
          return nullptr;
        }
      } else {
        // we have a low and a high index
        llvm::StringRef sleft, sright;
        unsigned long low_index, high_index;
        std::tie(sleft, sright) = bracket_expr.split('-');
        if (sleft.getAsInteger(0, low_index) ||
            sright.getAsInteger(0, high_index)) {
          *reason_to_stop =
              ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol;
          *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
          return nullptr;
        }

        if (low_index > high_index) // swap indices if required
          std::swap(low_index, high_index);

        if (root_compiler_type_info.Test(
                eTypeIsScalar)) // expansion only works for scalars
        {
          root = root->GetSyntheticBitFieldChild(low_index, high_index, true);
          if (!root) {
            *reason_to_stop =
                ValueObject::eExpressionPathScanEndReasonNoSuchChild;
            *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
            return nullptr;
          } else {
            *reason_to_stop = ValueObject::
                eExpressionPathScanEndReasonBitfieldRangeOperatorMet;
            *final_result = ValueObject::eExpressionPathEndResultTypeBitfield;
            return root;
          }
        } else if (root_compiler_type_info.Test(
                       eTypeIsPointer) && // if this is a ptr-to-scalar, I am
                                          // accessing it by index and I would
                                          // have deref'ed anyway, then do it
                                          // now and use this as a bitfield
                   *what_next ==
                       ValueObject::eExpressionPathAftermathDereference &&
                   pointee_compiler_type_info.Test(eTypeIsScalar)) {
          Status error;
          root = DereferenceValueOrAlternate(
              *root, options.m_synthetic_children_traversal, error);
          if (error.Fail() || !root) {
            *reason_to_stop =
                ValueObject::eExpressionPathScanEndReasonDereferencingFailed;
            *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
            return nullptr;
          } else {
            *what_next = ValueObject::eExpressionPathAftermathNothing;
            continue;
          }
        } else {
          *reason_to_stop =
              ValueObject::eExpressionPathScanEndReasonArrayRangeOperatorMet;
          *final_result = ValueObject::eExpressionPathEndResultTypeBoundedRange;
          return root;
        }
      }
      break;
    }
    default: // some non-separator is in the way
    {
      *reason_to_stop =
          ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol;
      *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
      return nullptr;
    }
    }
  }
}

llvm::Error ValueObject::Dump(Stream &s) {
  return Dump(s, DumpValueObjectOptions(*this));
}

llvm::Error ValueObject::Dump(Stream &s,
                              const DumpValueObjectOptions &options) {
  ValueObjectPrinter printer(*this, &s, options);
  return printer.PrintValueObject();
}

ValueObjectSP ValueObject::CreateConstantValue(ConstString name) {
  ValueObjectSP valobj_sp;

  if (UpdateValueIfNeeded(false) && m_error.Success()) {
    ExecutionContext exe_ctx(GetExecutionContextRef());

    DataExtractor data;
    data.SetByteOrder(m_data.GetByteOrder());
    data.SetAddressByteSize(m_data.GetAddressByteSize());

    if (IsBitfield()) {
      Value v(Scalar(GetValueAsUnsigned(UINT64_MAX)));
      m_error = v.GetValueAsData(&exe_ctx, data, GetModule().get());
    } else
      m_error = m_value.GetValueAsData(&exe_ctx, data, GetModule().get());

    valobj_sp = ValueObjectConstResult::Create(
        exe_ctx.GetBestExecutionContextScope(), GetCompilerType(), name, data,
        GetAddressOf().address);
  }

  if (!valobj_sp) {
    ExecutionContext exe_ctx(GetExecutionContextRef());
    valobj_sp = ValueObjectConstResult::Create(
        exe_ctx.GetBestExecutionContextScope(), m_error.Clone());
  }
  return valobj_sp;
}

ValueObjectSP ValueObject::GetQualifiedRepresentationIfAvailable(
    lldb::DynamicValueType dynValue, bool synthValue) {
  ValueObjectSP result_sp;
  switch (dynValue) {
  case lldb::eDynamicCanRunTarget:
  case lldb::eDynamicDontRunTarget: {
    if (!IsDynamic())
      result_sp = GetDynamicValue(dynValue);
  } break;
  case lldb::eNoDynamicValues: {
    if (IsDynamic())
      result_sp = GetStaticValue();
  } break;
  }
  if (!result_sp)
    result_sp = GetSP();
  assert(result_sp);

  bool is_synthetic = result_sp->IsSynthetic();
  if (synthValue && !is_synthetic) {
    if (auto synth_sp = result_sp->GetSyntheticValue())
      return synth_sp;
  }
  if (!synthValue && is_synthetic) {
    if (auto non_synth_sp = result_sp->GetNonSyntheticValue())
      return non_synth_sp;
  }

  return result_sp;
}

ValueObjectSP ValueObject::Dereference(Status &error) {
  if (m_deref_valobj)
    return m_deref_valobj->GetSP();

  std::string deref_name_str;
  uint32_t deref_byte_size = 0;
  int32_t deref_byte_offset = 0;
  CompilerType compiler_type = GetCompilerType();
  uint64_t language_flags = 0;

  ExecutionContext exe_ctx(GetExecutionContextRef());

  CompilerType deref_compiler_type;
  auto deref_compiler_type_or_err = compiler_type.GetDereferencedType(
      &exe_ctx, deref_name_str, deref_byte_size, deref_byte_offset, this,
      language_flags);

  std::string deref_error;
  if (deref_compiler_type_or_err) {
    deref_compiler_type = *deref_compiler_type_or_err;
  } else {
    deref_error = llvm::toString(deref_compiler_type_or_err.takeError());
    LLDB_LOG(GetLog(LLDBLog::Types), "could not find child: {0}", deref_error);
  }

  if (deref_compiler_type && deref_byte_size) {
    ConstString deref_name;
    if (!deref_name_str.empty())
      deref_name.SetCString(deref_name_str.c_str());

    m_deref_valobj =
        new ValueObjectChild(*this, deref_compiler_type, deref_name,
                             deref_byte_size, deref_byte_offset, 0, 0, false,
                             true, eAddressTypeInvalid, language_flags);
  }

  // In case of incomplete deref compiler type, use the pointee type and try
  // to recreate a new ValueObjectChild using it.
  if (!m_deref_valobj) {
    // FIXME(#59012): C++ stdlib formatters break with incomplete types (e.g.
    // `std::vector<int> &`). Remove ObjC restriction once that's resolved.
    if (Language::LanguageIsObjC(GetPreferredDisplayLanguage()) &&
        HasSyntheticValue()) {
      deref_compiler_type = compiler_type.GetPointeeType();

      if (deref_compiler_type) {
        ConstString deref_name;
        if (!deref_name_str.empty())
          deref_name.SetCString(deref_name_str.c_str());

        m_deref_valobj = new ValueObjectChild(
            *this, deref_compiler_type, deref_name, deref_byte_size,
            deref_byte_offset, 0, 0, false, true, eAddressTypeInvalid,
            language_flags);
      }
    }
  }

  if (!m_deref_valobj && IsSynthetic())
    m_deref_valobj = GetChildMemberWithName("$$dereference$$").get();

  if (m_deref_valobj) {
    error.Clear();
    return m_deref_valobj->GetSP();
  } else {
    StreamString strm;
    GetExpressionPath(strm);

    if (deref_error.empty())
      error = Status::FromErrorStringWithFormat(
          "dereference failed: (%s) %s",
          GetTypeName().AsCString("<invalid type>"), strm.GetData());
    else
      error = Status::FromErrorStringWithFormat(
          "dereference failed: %s: (%s) %s", deref_error.c_str(),
          GetTypeName().AsCString("<invalid type>"), strm.GetData());
    return ValueObjectSP();
  }
}

ValueObjectSP ValueObject::AddressOf(Status &error) {
  if (m_addr_of_valobj_sp)
    return m_addr_of_valobj_sp;

  auto [addr, address_type] = GetAddressOf(/*scalar_is_load_address=*/false);
  error.Clear();
  if (addr != LLDB_INVALID_ADDRESS && address_type != eAddressTypeHost) {
    switch (address_type) {
    case eAddressTypeInvalid: {
      StreamString expr_path_strm;
      GetExpressionPath(expr_path_strm);
      error = Status::FromErrorStringWithFormat("'%s' is not in memory",
                                                expr_path_strm.GetData());
    } break;

    case eAddressTypeFile:
    case eAddressTypeLoad: {
      CompilerType compiler_type = GetCompilerType();
      if (compiler_type) {
        std::string name(1, '&');
        name.append(m_name.AsCString(""));
        ExecutionContext exe_ctx(GetExecutionContextRef());

        lldb::DataBufferSP buffer(
            new lldb_private::DataBufferHeap(&addr, sizeof(lldb::addr_t)));
        m_addr_of_valobj_sp = ValueObjectConstResult::Create(
            exe_ctx.GetBestExecutionContextScope(),
            compiler_type.GetPointerType(), ConstString(name.c_str()), buffer,
            endian::InlHostByteOrder(), exe_ctx.GetAddressByteSize());
      }
    } break;
    default:
      break;
    }
  } else {
    StreamString expr_path_strm;
    GetExpressionPath(expr_path_strm);
    error = Status::FromErrorStringWithFormat(
        "'%s' doesn't have a valid address", expr_path_strm.GetData());
  }

  return m_addr_of_valobj_sp;
}

ValueObjectSP ValueObject::DoCast(const CompilerType &compiler_type) {
  return ValueObjectCast::Create(*this, GetName(), compiler_type);
}

ValueObjectSP ValueObject::Cast(const CompilerType &compiler_type) {
  // Only allow casts if the original type is equal or larger than the cast
  // type, unless we know this is a load address.  Getting the size wrong for
  // a host side storage could leak lldb memory, so we absolutely want to
  // prevent that.  We may not always get the right value, for instance if we
  // have an expression result value that's copied into a storage location in
  // the target may not have copied enough memory.  I'm not trying to fix that
  // here, I'm just making Cast from a smaller to a larger possible in all the
  // cases where that doesn't risk making a Value out of random lldb memory.
  // You have to check the ValueObject's Value for the address types, since
  // ValueObjects that use live addresses will tell you they fetch data from the
  // live address, but once they are made, they actually don't.
  // FIXME: Can we make ValueObject's with a live address fetch "more data" from
  // the live address if it is still valid?

  Status error;
  CompilerType my_type = GetCompilerType();

  ExecutionContextScope *exe_scope =
      ExecutionContext(GetExecutionContextRef()).GetBestExecutionContextScope();
  if (llvm::expectedToOptional(compiler_type.GetByteSize(exe_scope))
              .value_or(0) <=
          llvm::expectedToOptional(GetCompilerType().GetByteSize(exe_scope))
              .value_or(0) ||
      m_value.GetValueType() == Value::ValueType::LoadAddress)
    return DoCast(compiler_type);

  error = Status::FromErrorString(
      "Can only cast to a type that is equal to or smaller "
      "than the orignal type.");

  return ValueObjectConstResult::Create(
      ExecutionContext(GetExecutionContextRef()).GetBestExecutionContextScope(),
      std::move(error));
}

lldb::ValueObjectSP ValueObject::Clone(ConstString new_name) {
  return ValueObjectCast::Create(*this, new_name, GetCompilerType());
}

ValueObjectSP ValueObject::CastPointerType(const char *name,
                                           CompilerType &compiler_type) {
  ValueObjectSP valobj_sp;
  addr_t ptr_value = GetPointerValue().address;

  if (ptr_value != LLDB_INVALID_ADDRESS) {
    Address ptr_addr(ptr_value);
    ExecutionContext exe_ctx(GetExecutionContextRef());
    valobj_sp = ValueObjectMemory::Create(
        exe_ctx.GetBestExecutionContextScope(), name, ptr_addr, compiler_type);
  }
  return valobj_sp;
}

ValueObjectSP ValueObject::CastPointerType(const char *name, TypeSP &type_sp) {
  ValueObjectSP valobj_sp;
  addr_t ptr_value = GetPointerValue().address;

  if (ptr_value != LLDB_INVALID_ADDRESS) {
    Address ptr_addr(ptr_value);
    ExecutionContext exe_ctx(GetExecutionContextRef());
    valobj_sp = ValueObjectMemory::Create(
        exe_ctx.GetBestExecutionContextScope(), name, ptr_addr, type_sp);
  }
  return valobj_sp;
}

lldb::addr_t ValueObject::GetLoadAddress() {
  if (auto target_sp = GetTargetSP()) {
    const bool scalar_is_load_address = true;
    auto [addr_value, addr_type] = GetAddressOf(scalar_is_load_address);
    if (addr_type == eAddressTypeFile) {
      lldb::ModuleSP module_sp(GetModule());
      if (!module_sp)
        addr_value = LLDB_INVALID_ADDRESS;
      else {
        Address tmp_addr;
        module_sp->ResolveFileAddress(addr_value, tmp_addr);
        addr_value = tmp_addr.GetLoadAddress(target_sp.get());
      }
    } else if (addr_type == eAddressTypeHost ||
               addr_type == eAddressTypeInvalid)
      addr_value = LLDB_INVALID_ADDRESS;
    return addr_value;
  }
  return LLDB_INVALID_ADDRESS;
}

llvm::Expected<lldb::ValueObjectSP> ValueObject::CastDerivedToBaseType(
    CompilerType type, const llvm::ArrayRef<uint32_t> &base_type_indices) {
  // Make sure the starting type and the target type are both valid for this
  // type of cast; otherwise return the shared pointer to the original
  // (unchanged) ValueObject.
  if (!type.IsPointerType() && !type.IsReferenceType())
    return llvm::make_error<llvm::StringError>(
        "Invalid target type: should be a pointer or a reference",
        llvm::inconvertibleErrorCode());

  CompilerType start_type = GetCompilerType();
  if (start_type.IsReferenceType())
    start_type = start_type.GetNonReferenceType();

  auto target_record_type =
      type.IsPointerType() ? type.GetPointeeType() : type.GetNonReferenceType();
  auto start_record_type =
      start_type.IsPointerType() ? start_type.GetPointeeType() : start_type;

  if (!target_record_type.IsRecordType() || !start_record_type.IsRecordType())
    return llvm::make_error<llvm::StringError>(
        "Underlying start & target types should be record types",
        llvm::inconvertibleErrorCode());

  if (target_record_type.CompareTypes(start_record_type))
    return llvm::make_error<llvm::StringError>(
        "Underlying start & target types should be different",
        llvm::inconvertibleErrorCode());

  if (base_type_indices.empty())
    return llvm::make_error<llvm::StringError>(
        "Children sequence must be non-empty", llvm::inconvertibleErrorCode());

  // Both the starting & target types are valid for the cast, and the list of
  // base class indices is non-empty, so we can proceed with the cast.

  lldb::TargetSP target = GetTargetSP();
  // The `value` can be a pointer, but GetChildAtIndex works for pointers too.
  lldb::ValueObjectSP inner_value = GetSP();

  for (const uint32_t i : base_type_indices)
    // Create synthetic value if needed.
    inner_value =
        inner_value->GetChildAtIndex(i, /*can_create_synthetic*/ true);

  // At this point type of `inner_value` should be the dereferenced target
  // type.
  CompilerType inner_value_type = inner_value->GetCompilerType();
  if (type.IsPointerType()) {
    if (!inner_value_type.CompareTypes(type.GetPointeeType()))
      return llvm::make_error<llvm::StringError>(
          "casted value doesn't match the desired type",
          llvm::inconvertibleErrorCode());

    uintptr_t addr = inner_value->GetLoadAddress();
    llvm::StringRef name = "";
    ExecutionContext exe_ctx(target.get(), false);
    return ValueObject::CreateValueObjectFromAddress(name, addr, exe_ctx, type,
                                                     /* do deref */ false);
  }

  // At this point the target type should be a reference.
  if (!inner_value_type.CompareTypes(type.GetNonReferenceType()))
    return llvm::make_error<llvm::StringError>(
        "casted value doesn't match the desired type",
        llvm::inconvertibleErrorCode());

  return lldb::ValueObjectSP(inner_value->Cast(type.GetNonReferenceType()));
}

llvm::Expected<lldb::ValueObjectSP>
ValueObject::CastBaseToDerivedType(CompilerType type, uint64_t offset) {
  // Make sure the starting type and the target type are both valid for this
  // type of cast; otherwise return the shared pointer to the original
  // (unchanged) ValueObject.
  if (!type.IsPointerType() && !type.IsReferenceType())
    return llvm::make_error<llvm::StringError>(
        "Invalid target type: should be a pointer or a reference",
        llvm::inconvertibleErrorCode());

  CompilerType start_type = GetCompilerType();
  if (start_type.IsReferenceType())
    start_type = start_type.GetNonReferenceType();

  auto target_record_type =
      type.IsPointerType() ? type.GetPointeeType() : type.GetNonReferenceType();
  auto start_record_type =
      start_type.IsPointerType() ? start_type.GetPointeeType() : start_type;

  if (!target_record_type.IsRecordType() || !start_record_type.IsRecordType())
    return llvm::make_error<llvm::StringError>(
        "Underlying start & target types should be record types",
        llvm::inconvertibleErrorCode());

  if (target_record_type.CompareTypes(start_record_type))
    return llvm::make_error<llvm::StringError>(
        "Underlying start & target types should be different",
        llvm::inconvertibleErrorCode());

  CompilerType virtual_base;
  if (target_record_type.IsVirtualBase(start_record_type, &virtual_base)) {
    if (!virtual_base.IsValid())
      return llvm::make_error<llvm::StringError>(
          "virtual base should be valid", llvm::inconvertibleErrorCode());
    return llvm::make_error<llvm::StringError>(
        llvm::Twine("cannot cast " + start_type.TypeDescription() + " to " +
                    type.TypeDescription() + " via virtual base " +
                    virtual_base.TypeDescription()),
        llvm::inconvertibleErrorCode());
  }

  // Both the starting & target types are valid for the cast,  so we can
  // proceed with the cast.

  lldb::TargetSP target = GetTargetSP();
  auto pointer_type =
      type.IsPointerType() ? type : type.GetNonReferenceType().GetPointerType();

  uintptr_t addr =
      type.IsPointerType() ? GetValueAsUnsigned(0) : GetLoadAddress();

  llvm::StringRef name = "";
  ExecutionContext exe_ctx(target.get(), false);
  lldb::ValueObjectSP value = ValueObject::CreateValueObjectFromAddress(
      name, addr - offset, exe_ctx, pointer_type, /* do_deref */ false);

  if (type.IsPointerType())
    return value;

  // At this point the target type is a reference. Since `value` is a pointer,
  // it has to be dereferenced.
  Status error;
  return value->Dereference(error);
}

lldb::ValueObjectSP ValueObject::CastToBasicType(CompilerType type) {
  bool is_scalar = GetCompilerType().IsScalarType();
  bool is_enum = GetCompilerType().IsEnumerationType();
  bool is_pointer =
      GetCompilerType().IsPointerType() || GetCompilerType().IsNullPtrType();
  bool is_float = HasFloatingRepresentation(GetCompilerType());
  bool is_integer = GetCompilerType().IsInteger();
  ExecutionContext exe_ctx(GetExecutionContextRef());

  if (!type.IsScalarType())
    return ValueObjectConstResult::Create(
        exe_ctx.GetBestExecutionContextScope(),
        Status::FromErrorString("target type must be a scalar"));

  if (!is_scalar && !is_enum && !is_pointer)
    return ValueObjectConstResult::Create(
        exe_ctx.GetBestExecutionContextScope(),
        Status::FromErrorString("argument must be a scalar, enum, or pointer"));

  lldb::TargetSP target = GetTargetSP();
  uint64_t type_byte_size = 0;
  uint64_t val_byte_size = 0;
  if (auto temp = llvm::expectedToOptional(type.GetByteSize(target.get())))
    type_byte_size = temp.value();
  if (auto temp =
          llvm::expectedToOptional(GetCompilerType().GetByteSize(target.get())))
    val_byte_size = temp.value();

  if (is_pointer) {
    if (!type.IsInteger() && !type.IsBoolean())
      return ValueObjectConstResult::Create(
          exe_ctx.GetBestExecutionContextScope(),
          Status::FromErrorString("target type must be an integer or boolean"));
    if (!type.IsBoolean() && type_byte_size < val_byte_size)
      return ValueObjectConstResult::Create(
          exe_ctx.GetBestExecutionContextScope(),
          Status::FromErrorString(
              "target type cannot be smaller than the pointer type"));
  }

  if (type.IsBoolean()) {
    if (!is_scalar || is_integer)
      return ValueObject::CreateValueObjectFromBool(
          target, GetValueAsUnsigned(0) != 0, "result");
    else if (is_scalar && is_float) {
      auto float_value_or_err = GetValueAsAPFloat();
      if (float_value_or_err)
        return ValueObject::CreateValueObjectFromBool(
            target, !float_value_or_err->isZero(), "result");
      else
        return ValueObjectConstResult::Create(
            exe_ctx.GetBestExecutionContextScope(),
            Status::FromErrorStringWithFormat(
                "cannot get value as APFloat: %s",
                llvm::toString(float_value_or_err.takeError()).c_str()));
    }
  }

  if (type.IsInteger()) {
    if (!is_scalar || is_integer) {
      auto int_value_or_err = GetValueAsAPSInt();
      if (int_value_or_err) {
        // Get the value as APSInt and extend or truncate it to the requested
        // size.
        llvm::APSInt ext =
            int_value_or_err->extOrTrunc(type_byte_size * CHAR_BIT);
        return ValueObject::CreateValueObjectFromAPInt(target, ext, type,
                                                       "result");
      } else
        return ValueObjectConstResult::Create(
            exe_ctx.GetBestExecutionContextScope(),
            Status::FromErrorStringWithFormat(
                "cannot get value as APSInt: %s",
                llvm::toString(int_value_or_err.takeError()).c_str()));
    } else if (is_scalar && is_float) {
      llvm::APSInt integer(type_byte_size * CHAR_BIT, !type.IsSigned());
      bool is_exact;
      auto float_value_or_err = GetValueAsAPFloat();
      if (float_value_or_err) {
        llvm::APFloatBase::opStatus status =
            float_value_or_err->convertToInteger(
                integer, llvm::APFloat::rmTowardZero, &is_exact);

        // Casting floating point values that are out of bounds of the target
        // type is undefined behaviour.
        if (status & llvm::APFloatBase::opInvalidOp)
          return ValueObjectConstResult::Create(
              exe_ctx.GetBestExecutionContextScope(),
              Status::FromErrorStringWithFormat(
                  "invalid type cast detected: %s",
                  llvm::toString(float_value_or_err.takeError()).c_str()));
        return ValueObject::CreateValueObjectFromAPInt(target, integer, type,
                                                       "result");
      }
    }
  }

  if (HasFloatingRepresentation(type)) {
    if (!is_scalar) {
      auto int_value_or_err = GetValueAsAPSInt();
      if (int_value_or_err) {
        llvm::APSInt ext =
            int_value_or_err->extOrTrunc(type_byte_size * CHAR_BIT);
        Scalar scalar_int(ext);
        llvm::APFloat f =
            scalar_int.CreateAPFloatFromAPSInt(type.GetBasicTypeEnumeration());
        return ValueObject::CreateValueObjectFromAPFloat(target, f, type,
                                                         "result");
      } else {
        return ValueObjectConstResult::Create(
            exe_ctx.GetBestExecutionContextScope(),
            Status::FromErrorStringWithFormat(
                "cannot get value as APSInt: %s",
                llvm::toString(int_value_or_err.takeError()).c_str()));
      }
    } else {
      if (is_integer) {
        auto int_value_or_err = GetValueAsAPSInt();
        if (int_value_or_err) {
          Scalar scalar_int(*int_value_or_err);
          llvm::APFloat f = scalar_int.CreateAPFloatFromAPSInt(
              type.GetBasicTypeEnumeration());
          return ValueObject::CreateValueObjectFromAPFloat(target, f, type,
                                                           "result");
        } else {
          return ValueObjectConstResult::Create(
              exe_ctx.GetBestExecutionContextScope(),
              Status::FromErrorStringWithFormat(
                  "cannot get value as APSInt: %s",
                  llvm::toString(int_value_or_err.takeError()).c_str()));
        }
      }
      if (is_float) {
        auto float_value_or_err = GetValueAsAPFloat();
        if (float_value_or_err) {
          Scalar scalar_float(*float_value_or_err);
          llvm::APFloat f = scalar_float.CreateAPFloatFromAPFloat(
              type.GetBasicTypeEnumeration());
          return ValueObject::CreateValueObjectFromAPFloat(target, f, type,
                                                           "result");
        } else {
          return ValueObjectConstResult::Create(
              exe_ctx.GetBestExecutionContextScope(),
              Status::FromErrorStringWithFormat(
                  "cannot get value as APFloat: %s",
                  llvm::toString(float_value_or_err.takeError()).c_str()));
        }
      }
    }
  }

  return ValueObjectConstResult::Create(
      exe_ctx.GetBestExecutionContextScope(),
      Status::FromErrorString("Unable to perform requested cast"));
}

lldb::ValueObjectSP ValueObject::CastToEnumType(CompilerType type) {
  bool is_enum = GetCompilerType().IsEnumerationType();
  bool is_integer = GetCompilerType().IsInteger();
  bool is_float = HasFloatingRepresentation(GetCompilerType());
  ExecutionContext exe_ctx(GetExecutionContextRef());

  if (!is_enum && !is_integer && !is_float)
    return ValueObjectConstResult::Create(
        exe_ctx.GetBestExecutionContextScope(),
        Status::FromErrorString(
            "argument must be an integer, a float, or an enum"));

  if (!type.IsEnumerationType())
    return ValueObjectConstResult::Create(
        exe_ctx.GetBestExecutionContextScope(),
        Status::FromErrorString("target type must be an enum"));

  lldb::TargetSP target = GetTargetSP();
  uint64_t byte_size = 0;
  if (auto temp = llvm::expectedToOptional(type.GetByteSize(target.get())))
    byte_size = temp.value();

  if (is_float) {
    llvm::APSInt integer(byte_size * CHAR_BIT, !type.IsSigned());
    bool is_exact;
    auto value_or_err = GetValueAsAPFloat();
    if (value_or_err) {
      llvm::APFloatBase::opStatus status = value_or_err->convertToInteger(
          integer, llvm::APFloat::rmTowardZero, &is_exact);

      // Casting floating point values that are out of bounds of the target
      // type is undefined behaviour.
      if (status & llvm::APFloatBase::opInvalidOp)
        return ValueObjectConstResult::Create(
            exe_ctx.GetBestExecutionContextScope(),
            Status::FromErrorStringWithFormat(
                "invalid type cast detected: %s",
                llvm::toString(value_or_err.takeError()).c_str()));
      return ValueObject::CreateValueObjectFromAPInt(target, integer, type,
                                                     "result");
    } else
      return ValueObjectConstResult::Create(
          exe_ctx.GetBestExecutionContextScope(),
          Status::FromErrorString("cannot get value as APFloat"));
  } else {
    // Get the value as APSInt and extend or truncate it to the requested size.
    auto value_or_err = GetValueAsAPSInt();
    if (value_or_err) {
      llvm::APSInt ext = value_or_err->extOrTrunc(byte_size * CHAR_BIT);
      return ValueObject::CreateValueObjectFromAPInt(target, ext, type,
                                                     "result");
    } else
      return ValueObjectConstResult::Create(
          exe_ctx.GetBestExecutionContextScope(),
          Status::FromErrorStringWithFormat(
              "cannot get value as APSInt: %s",
              llvm::toString(value_or_err.takeError()).c_str()));
  }
  return ValueObjectConstResult::Create(
      exe_ctx.GetBestExecutionContextScope(),
      Status::FromErrorString("Cannot perform requested cast"));
}

ValueObject::EvaluationPoint::EvaluationPoint() : m_mod_id(), m_exe_ctx_ref() {}

ValueObject::EvaluationPoint::EvaluationPoint(ExecutionContextScope *exe_scope,
                                              bool use_selected)
    : m_mod_id(), m_exe_ctx_ref() {
  ExecutionContext exe_ctx(exe_scope);
  TargetSP target_sp(exe_ctx.GetTargetSP());
  if (target_sp) {
    m_exe_ctx_ref.SetTargetSP(target_sp);
    ProcessSP process_sp(exe_ctx.GetProcessSP());
    if (!process_sp)
      process_sp = target_sp->GetProcessSP();

    if (process_sp) {
      m_mod_id = process_sp->GetModID();
      m_exe_ctx_ref.SetProcessSP(process_sp);

      ThreadSP thread_sp(exe_ctx.GetThreadSP());

      if (!thread_sp) {
        if (use_selected)
          thread_sp = process_sp->GetThreadList().GetSelectedThread();
      }

      if (thread_sp) {
        m_exe_ctx_ref.SetThreadSP(thread_sp);

        StackFrameSP frame_sp(exe_ctx.GetFrameSP());
        if (!frame_sp) {
          if (use_selected)
            frame_sp = thread_sp->GetSelectedFrame(DoNoSelectMostRelevantFrame);
        }
        if (frame_sp)
          m_exe_ctx_ref.SetFrameSP(frame_sp);
      }
    }
  }
}

ValueObject::EvaluationPoint::EvaluationPoint(
    const ValueObject::EvaluationPoint &rhs)
    : m_mod_id(), m_exe_ctx_ref(rhs.m_exe_ctx_ref) {}

ValueObject::EvaluationPoint::~EvaluationPoint() = default;

// This function checks the EvaluationPoint against the current process state.
// If the current state matches the evaluation point, or the evaluation point
// is already invalid, then we return false, meaning "no change".  If the
// current state is different, we update our state, and return true meaning
// "yes, change".  If we did see a change, we also set m_needs_update to true,
// so future calls to NeedsUpdate will return true. exe_scope will be set to
// the current execution context scope.

bool ValueObject::EvaluationPoint::SyncWithProcessState(
    bool accept_invalid_exe_ctx) {
  // Start with the target, if it is NULL, then we're obviously not going to
  // get any further:
  const bool thread_and_frame_only_if_stopped = true;
  ExecutionContext exe_ctx(
      m_exe_ctx_ref.Lock(thread_and_frame_only_if_stopped));

  if (exe_ctx.GetTargetPtr() == nullptr)
    return false;

  // If we don't have a process nothing can change.
  Process *process = exe_ctx.GetProcessPtr();
  if (process == nullptr)
    return false;

  // If our stop id is the current stop ID, nothing has changed:
  ProcessModID current_mod_id = process->GetModID();

  // If the current stop id is 0, either we haven't run yet, or the process
  // state has been cleared. In either case, we aren't going to be able to sync
  // with the process state.
  if (current_mod_id.GetStopID() == 0)
    return false;

  bool changed = false;
  const bool was_valid = m_mod_id.IsValid();
  if (was_valid) {
    if (m_mod_id == current_mod_id) {
      // Everything is already up to date in this object, no need to update the
      // execution context scope.
      changed = false;
    } else {
      m_mod_id = current_mod_id;
      m_needs_update = true;
      changed = true;
    }
  }

  // Now re-look up the thread and frame in case the underlying objects have
  // gone away & been recreated. That way we'll be sure to return a valid
  // exe_scope. If we used to have a thread or a frame but can't find it
  // anymore, then mark ourselves as invalid.

  if (!accept_invalid_exe_ctx) {
    if (m_exe_ctx_ref.HasThreadRef()) {
      ThreadSP thread_sp(m_exe_ctx_ref.GetThreadSP());
      if (thread_sp) {
        if (m_exe_ctx_ref.HasFrameRef()) {
          StackFrameSP frame_sp(m_exe_ctx_ref.GetFrameSP());
          if (!frame_sp) {
            // We used to have a frame, but now it is gone
            SetInvalid();
            changed = was_valid;
          }
        }
      } else {
        // We used to have a thread, but now it is gone
        SetInvalid();
        changed = was_valid;
      }
    }
  }

  return changed;
}

void ValueObject::EvaluationPoint::SetUpdated() {
  ProcessSP process_sp(m_exe_ctx_ref.GetProcessSP());
  if (process_sp)
    m_mod_id = process_sp->GetModID();
  m_needs_update = false;
}

void ValueObject::ClearUserVisibleData(uint32_t clear_mask) {
  if ((clear_mask & eClearUserVisibleDataItemsValue) ==
      eClearUserVisibleDataItemsValue)
    m_value_str.clear();

  if ((clear_mask & eClearUserVisibleDataItemsLocation) ==
      eClearUserVisibleDataItemsLocation)
    m_location_str.clear();

  if ((clear_mask & eClearUserVisibleDataItemsSummary) ==
      eClearUserVisibleDataItemsSummary)
    m_summary_str.clear();

  if ((clear_mask & eClearUserVisibleDataItemsDescription) ==
      eClearUserVisibleDataItemsDescription)
    m_object_desc_str.clear();

  if ((clear_mask & eClearUserVisibleDataItemsSyntheticChildren) ==
      eClearUserVisibleDataItemsSyntheticChildren) {
    if (m_synthetic_value)
      m_synthetic_value = nullptr;
  }
}

SymbolContextScope *ValueObject::GetSymbolContextScope() {
  if (m_parent) {
    if (!m_parent->IsPointerOrReferenceType())
      return m_parent->GetSymbolContextScope();
  }
  return nullptr;
}

lldb::ValueObjectSP
ValueObject::CreateValueObjectFromExpression(llvm::StringRef name,
                                             llvm::StringRef expression,
                                             const ExecutionContext &exe_ctx) {
  return CreateValueObjectFromExpression(name, expression, exe_ctx,
                                         EvaluateExpressionOptions());
}

lldb::ValueObjectSP ValueObject::CreateValueObjectFromExpression(
    llvm::StringRef name, llvm::StringRef expression,
    const ExecutionContext &exe_ctx, const EvaluateExpressionOptions &options) {
  lldb::ValueObjectSP retval_sp;
  lldb::TargetSP target_sp(exe_ctx.GetTargetSP());
  if (!target_sp)
    return retval_sp;
  if (expression.empty())
    return retval_sp;
  target_sp->EvaluateExpression(expression, exe_ctx.GetFrameSP().get(),
                                retval_sp, options);
  if (retval_sp && !name.empty())
    retval_sp->SetName(ConstString(name));
  return retval_sp;
}

lldb::ValueObjectSP ValueObject::CreateValueObjectFromAddress(
    llvm::StringRef name, uint64_t address, const ExecutionContext &exe_ctx,
    CompilerType type, bool do_deref) {
  if (type) {
    CompilerType pointer_type(type.GetPointerType());
    if (!do_deref)
      pointer_type = type;
    if (pointer_type) {
      lldb::DataBufferSP buffer(
          new lldb_private::DataBufferHeap(&address, sizeof(lldb::addr_t)));
      lldb::ValueObjectSP ptr_result_valobj_sp(ValueObjectConstResult::Create(
          exe_ctx.GetBestExecutionContextScope(), pointer_type,
          ConstString(name), buffer, exe_ctx.GetByteOrder(),
          exe_ctx.GetAddressByteSize()));
      if (ptr_result_valobj_sp) {
        if (do_deref)
          ptr_result_valobj_sp->GetValue().SetValueType(
              Value::ValueType::LoadAddress);
        Status err;
        if (do_deref)
          ptr_result_valobj_sp = ptr_result_valobj_sp->Dereference(err);
        if (ptr_result_valobj_sp && !name.empty())
          ptr_result_valobj_sp->SetName(ConstString(name));
      }
      return ptr_result_valobj_sp;
    }
  }
  return lldb::ValueObjectSP();
}

lldb::ValueObjectSP ValueObject::CreateValueObjectFromData(
    llvm::StringRef name, const DataExtractor &data,
    const ExecutionContext &exe_ctx, CompilerType type) {
  lldb::ValueObjectSP new_value_sp;
  new_value_sp = ValueObjectConstResult::Create(
      exe_ctx.GetBestExecutionContextScope(), type, ConstString(name), data,
      LLDB_INVALID_ADDRESS);
  new_value_sp->SetAddressTypeOfChildren(eAddressTypeLoad);
  if (new_value_sp && !name.empty())
    new_value_sp->SetName(ConstString(name));
  return new_value_sp;
}

lldb::ValueObjectSP
ValueObject::CreateValueObjectFromAPInt(lldb::TargetSP target,
                                        const llvm::APInt &v, CompilerType type,
                                        llvm::StringRef name) {
  ExecutionContext exe_ctx(target.get(), false);
  uint64_t byte_size = 0;
  if (auto temp = llvm::expectedToOptional(type.GetByteSize(target.get())))
    byte_size = temp.value();
  lldb::DataExtractorSP data_sp = std::make_shared<DataExtractor>(
      reinterpret_cast<const void *>(v.getRawData()), byte_size,
      exe_ctx.GetByteOrder(), exe_ctx.GetAddressByteSize());
  return ValueObject::CreateValueObjectFromData(name, *data_sp, exe_ctx, type);
}

lldb::ValueObjectSP ValueObject::CreateValueObjectFromAPFloat(
    lldb::TargetSP target, const llvm::APFloat &v, CompilerType type,
    llvm::StringRef name) {
  return CreateValueObjectFromAPInt(target, v.bitcastToAPInt(), type, name);
}

lldb::ValueObjectSP ValueObject::CreateValueObjectFromScalar(
    lldb::TargetSP target, Scalar &s, CompilerType type, llvm::StringRef name) {
  ExecutionContext exe_ctx(target.get(), false);
  return ValueObjectConstResult::Create(exe_ctx.GetBestExecutionContextScope(),
                                        type, s, ConstString(name));
}

lldb::ValueObjectSP
ValueObject::CreateValueObjectFromBool(lldb::TargetSP target, bool value,
                                       llvm::StringRef name) {
  CompilerType target_type;
  if (target) {
    for (auto type_system_sp : target->GetScratchTypeSystems())
      if (auto compiler_type =
              type_system_sp->GetBasicTypeFromAST(lldb::eBasicTypeBool)) {
        target_type = compiler_type;
        break;
      }
  }
  ExecutionContext exe_ctx(target.get(), false);
  uint64_t byte_size = 0;
  if (auto temp =
          llvm::expectedToOptional(target_type.GetByteSize(target.get())))
    byte_size = temp.value();
  lldb::DataExtractorSP data_sp = std::make_shared<DataExtractor>(
      reinterpret_cast<const void *>(&value), byte_size, exe_ctx.GetByteOrder(),
      exe_ctx.GetAddressByteSize());
  return ValueObject::CreateValueObjectFromData(name, *data_sp, exe_ctx,
                                                target_type);
}

lldb::ValueObjectSP ValueObject::CreateValueObjectFromNullptr(
    lldb::TargetSP target, CompilerType type, llvm::StringRef name) {
  if (!type.IsNullPtrType()) {
    lldb::ValueObjectSP ret_val;
    return ret_val;
  }
  uintptr_t zero = 0;
  ExecutionContext exe_ctx(target.get(), false);
  uint64_t byte_size = 0;
  if (auto temp = llvm::expectedToOptional(type.GetByteSize(target.get())))
    byte_size = temp.value();
  lldb::DataExtractorSP data_sp = std::make_shared<DataExtractor>(
      reinterpret_cast<const void *>(zero), byte_size, exe_ctx.GetByteOrder(),
      exe_ctx.GetAddressByteSize());
  return ValueObject::CreateValueObjectFromData(name, *data_sp, exe_ctx, type);
}

ModuleSP ValueObject::GetModule() {
  ValueObject *root(GetRoot());
  if (root != this)
    return root->GetModule();
  return lldb::ModuleSP();
}

ValueObject *ValueObject::GetRoot() {
  if (m_root)
    return m_root;
  return (m_root = FollowParentChain([](ValueObject *vo) -> bool {
            return (vo->m_parent != nullptr);
          }));
}

ValueObject *
ValueObject::FollowParentChain(std::function<bool(ValueObject *)> f) {
  ValueObject *vo = this;
  while (vo) {
    if (!f(vo))
      break;
    vo = vo->m_parent;
  }
  return vo;
}

AddressType ValueObject::GetAddressTypeOfChildren() {
  if (m_address_type_of_ptr_or_ref_children == eAddressTypeInvalid) {
    ValueObject *root(GetRoot());
    if (root != this)
      return root->GetAddressTypeOfChildren();
  }
  return m_address_type_of_ptr_or_ref_children;
}

lldb::DynamicValueType ValueObject::GetDynamicValueType() {
  ValueObject *with_dv_info = this;
  while (with_dv_info) {
    if (with_dv_info->HasDynamicValueTypeInfo())
      return with_dv_info->GetDynamicValueTypeImpl();
    with_dv_info = with_dv_info->m_parent;
  }
  return lldb::eNoDynamicValues;
}

lldb::Format ValueObject::GetFormat() const {
  const ValueObject *with_fmt_info = this;
  while (with_fmt_info) {
    if (with_fmt_info->m_format != lldb::eFormatDefault)
      return with_fmt_info->m_format;
    with_fmt_info = with_fmt_info->m_parent;
  }
  return m_format;
}

lldb::LanguageType ValueObject::GetPreferredDisplayLanguage() {
  lldb::LanguageType type = m_preferred_display_language;
  if (m_preferred_display_language == lldb::eLanguageTypeUnknown) {
    if (GetRoot()) {
      if (GetRoot() == this) {
        if (StackFrameSP frame_sp = GetFrameSP()) {
          const SymbolContext &sc(
              frame_sp->GetSymbolContext(eSymbolContextCompUnit));
          if (CompileUnit *cu = sc.comp_unit)
            type = cu->GetLanguage();
        }
      } else {
        type = GetRoot()->GetPreferredDisplayLanguage();
      }
    }
  }
  return (m_preferred_display_language = type); // only compute it once
}

void ValueObject::SetPreferredDisplayLanguageIfNeeded(lldb::LanguageType lt) {
  if (m_preferred_display_language == lldb::eLanguageTypeUnknown)
    SetPreferredDisplayLanguage(lt);
}

bool ValueObject::CanProvideValue() {
  // we need to support invalid types as providers of values because some bare-
  // board debugging scenarios have no notion of types, but still manage to
  // have raw numeric values for things like registers. sigh.
  CompilerType type = GetCompilerType();
  return (!type.IsValid()) || (0 != (type.GetTypeInfo() & eTypeHasValue));
}

ValueObjectSP ValueObject::Persist() {
  if (!UpdateValueIfNeeded())
    return nullptr;

  TargetSP target_sp(GetTargetSP());
  if (!target_sp)
    return nullptr;

  PersistentExpressionState *persistent_state =
      target_sp->GetPersistentExpressionStateForLanguage(
          GetPreferredDisplayLanguage());

  if (!persistent_state)
    return nullptr;

  ConstString name = persistent_state->GetNextPersistentVariableName();

  ValueObjectSP const_result_sp =
      ValueObjectConstResult::Create(target_sp.get(), GetValue(), name);

  ExpressionVariableSP persistent_var_sp =
      persistent_state->CreatePersistentVariable(const_result_sp);
  persistent_var_sp->m_live_sp = persistent_var_sp->m_frozen_sp;
  persistent_var_sp->m_flags |= ExpressionVariable::EVIsProgramReference;

  return persistent_var_sp->GetValueObject();
}

lldb::ValueObjectSP ValueObject::GetVTable() {
  return ValueObjectVTable::Create(*this);
}

ValueImpl::ValueImpl(lldb::ValueObjectSP in_valobj_sp,
                     lldb::DynamicValueType use_dynamic, bool use_synthetic,
                     const char *name)
    : m_use_dynamic(use_dynamic), m_use_synthetic(use_synthetic), m_name(name) {
  if (in_valobj_sp) {
    if ((m_valobj_sp = in_valobj_sp->GetQualifiedRepresentationIfAvailable(
             lldb::eNoDynamicValues, false))) {
      if (!m_name.IsEmpty())
        m_valobj_sp->SetName(m_name);
    }
  }
}

ValueImpl &ValueImpl::operator=(const ValueImpl &rhs) {
  if (this != &rhs) {
    m_valobj_sp = rhs.m_valobj_sp;
    m_use_dynamic = rhs.m_use_dynamic;
    m_use_synthetic = rhs.m_use_synthetic;
    m_name = rhs.m_name;
  }
  return *this;
}

bool ValueImpl::IsValid() {
  if (m_valobj_sp.get() == nullptr)
    return false;

  // FIXME: This check is necessary but not sufficient.  We for sure don't
  // want to touch SBValues whose owning
  // targets have gone away.  This check is a little weak in that it
  // enforces that restriction when you call IsValid, but since IsValid
  // doesn't lock the target, you have no guarantee that the SBValue won't
  // go invalid after you call this... Also, an SBValue could depend on
  // data from one of the modules in the target, and those could go away
  // independently of the target, for instance if a module is unloaded.
  // But right now, neither SBValues nor ValueObjects know which modules
  // they depend on.  So I have no good way to make that check without
  // tracking that in all the ValueObject subclasses.
  TargetSP target_sp = m_valobj_sp->GetTargetSP();
  return target_sp && target_sp->IsValid();
}

lldb::ValueObjectSP
ValueImpl::GetSP(Process::StopLocker &stop_locker,
                 std::unique_lock<std::recursive_mutex> &lock, Status &error) {
  if (!m_valobj_sp) {
    error = Status::FromErrorString("invalid value object");
    return m_valobj_sp;
  }

  lldb::ValueObjectSP value_sp = m_valobj_sp;

  Target *target = value_sp->GetTargetSP().get();
  // If this ValueObject holds an error, then it is valuable for that.
  if (value_sp->GetError().Fail())
    return value_sp;

  if (!target)
    return ValueObjectSP();

  lock = std::unique_lock<std::recursive_mutex>(target->GetAPIMutex());

  ProcessSP process_sp(value_sp->GetProcessSP());
  if (process_sp && !stop_locker.TryLock(&process_sp->GetRunLock())) {
    // We don't allow people to play around with ValueObject if the process
    // is running. If you want to look at values, pause the process, then
    // look.
    error = Status::FromErrorString("process must be stopped.");
    return ValueObjectSP();
  }

  if (m_use_dynamic != eNoDynamicValues) {
    ValueObjectSP dynamic_sp = value_sp->GetDynamicValue(m_use_dynamic);
    if (dynamic_sp)
      value_sp = dynamic_sp;
  }

  if (m_use_synthetic) {
    ValueObjectSP synthetic_sp = value_sp->GetSyntheticValue();
    if (synthetic_sp)
      value_sp = synthetic_sp;
  }

  if (!value_sp)
    error = Status::FromErrorString("invalid value object");
  if (!m_name.IsEmpty())
    value_sp->SetName(m_name);

  return value_sp;
}
