//===-- DILEval.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/DILEval.h"
#include "lldb/Core/Module.h"
#include "lldb/Expression/ExpressionVariable.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/TypeSystem.h"
#include "lldb/Symbol/VariableList.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/Target.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/ValueObject/DILAST.h"
#include "lldb/ValueObject/DILParser.h"
#include "lldb/ValueObject/ValueObject.h"
#include "lldb/ValueObject/ValueObjectRegister.h"
#include "lldb/ValueObject/ValueObjectVariable.h"
#include "llvm/Support/ErrorExtras.h"
#include "llvm/Support/FormatAdapters.h"
#include <memory>
#include <optional>

namespace lldb_private::dil {

static CompilerType GetBasicType(lldb::TypeSystemSP type_system,
                                 lldb::BasicType basic_type) {
  if (type_system)
    return type_system.get()->GetBasicTypeFromAST(basic_type);

  return CompilerType();
}

static lldb::ValueObjectSP ArrayToPointerConversion(ValueObject &valobj,
                                                    ExecutionContext &exe_ctx,
                                                    llvm::StringRef name) {
  uint64_t addr = valobj.GetLoadAddress();
  return ValueObject::CreateValueObjectFromAddress(
      name, addr, exe_ctx,
      valobj.GetCompilerType()
          .GetArrayElementType(exe_ctx.GetBestExecutionContextScope())
          .GetPointerType(),
      /* do_deref */ false);
}

static llvm::Expected<SymbolContext>
GetSymbolContexFromFrame(ExecutionContext &exe_ctx) {
  auto frame_sp = exe_ctx.GetFrameSP();
  if (!frame_sp)
    return llvm::createStringError("no stack frame in execution context");

  SymbolContext symbol_context = frame_sp->GetSymbolContext(
      lldb::eSymbolContextCompUnit | lldb::eSymbolContextModule);
  if (!symbol_context.comp_unit)
    return llvm::createStringErrorV("no compile unit for frame: {0}",
                                    frame_sp->GetFunctionName());
  if (!symbol_context.module_sp)
    return llvm::createStringErrorV("no module for frame: {0}",
                                    frame_sp->GetFunctionName());
  return symbol_context;
}

llvm::Expected<lldb::LanguageType> Interpreter::GetSourceLanguageFromCU() {
  llvm::Expected<SymbolContext> symbol_context =
      GetSymbolContexFromFrame(m_exe_ctx);
  if (!symbol_context)
    return symbol_context.takeError();

  return symbol_context->comp_unit->GetLanguage();
}

llvm::Expected<lldb::TypeSystemSP> Interpreter::GetTypeSystemFromCU() {
  lldb::LanguageType language = lldb::eLanguageTypeUnknown;
  if (auto frame_sp = m_exe_ctx.GetFrameSP()) {
    SymbolContext symbol_context =
        frame_sp->GetSymbolContext(lldb::eSymbolContextCompUnit);
    if (symbol_context.comp_unit) {
      language = symbol_context.comp_unit->GetLanguage();
      symbol_context = frame_sp->GetSymbolContext(lldb::eSymbolContextModule);
      if (symbol_context.module_sp)
        return symbol_context.module_sp->GetTypeSystemForLanguage(language);
    }
  }

  lldb::TargetSP target_sp = m_exe_ctx.GetTargetSP();
  if (!target_sp)
    return llvm::createStringError("no target for frame");
  if (language == lldb::eLanguageTypeUnknown)
    language = target_sp->GetLanguage().AsLanguageType();
  return target_sp->GetScratchTypeSystemForLanguage(language);
}

// DIL normally treats '.' as member access, but register names may contain
// periods. Reconstruct the candidate so an exact register name takes
// precedence.
static std::optional<std::string> GetRegisterPathName(const ASTNode &node) {
  if (node.GetKind() == NodeKind::eIdentifierNode) {
    std::string name_storage =
        static_cast<const IdentifierNode &>(node).GetName();
    llvm::StringRef name = name_storage;
    if (name.consume_front("$"))
      return name.str();
    return std::nullopt;
  }

  if (node.GetKind() != NodeKind::eMemberOfNode)
    return std::nullopt;
  const auto &member = static_cast<const MemberOfNode &>(node);
  if (member.GetIsArrow())
    return std::nullopt;
  std::optional<std::string> base_name = GetRegisterPathName(member.GetBase());
  if (!base_name)
    return std::nullopt;
  return *base_name + "." + member.GetFieldName().str();
}

llvm::Expected<lldb::ValueObjectSP>
Interpreter::UnaryConversion(lldb::ValueObjectSP valobj, uint32_t location) {
  if (!valobj)
    return llvm::make_error<DILDiagnosticError>(m_expr, "invalid value object",
                                                location);
  llvm::Expected<lldb::TypeSystemSP> type_system = GetTypeSystemFromCU();
  if (!type_system)
    return type_system.takeError();

  CompilerType in_type = valobj->GetCompilerType();
  if (valobj->IsBitfield()) {
    // Promote bitfields. If `int` can represent the bitfield value, it is
    // converted to `int`. Otherwise, if `unsigned int` can represent it, it
    // is converted to `unsigned int`. Otherwise, it is treated as its
    // underlying type.
    uint32_t bitfield_size = valobj->GetBitfieldBitSize();
    // Some bitfields have undefined size (e.g. result of ternary operation).
    // The AST's `bitfield_size` of those is 0, and no promotion takes place.
    if (bitfield_size > 0 && in_type.IsInteger()) {
      CompilerType int_type = GetBasicType(*type_system, lldb::eBasicTypeInt);
      CompilerType uint_type =
          GetBasicType(*type_system, lldb::eBasicTypeUnsignedInt);
      llvm::Expected<uint64_t> int_bit_size =
          int_type.GetBitSize(m_exe_ctx.GetBestExecutionContextScope());
      if (!int_bit_size)
        return int_bit_size.takeError();
      llvm::Expected<uint64_t> uint_bit_size =
          uint_type.GetBitSize(m_exe_ctx.GetBestExecutionContextScope());
      if (!uint_bit_size)
        return uint_bit_size.takeError();
      if (bitfield_size < *int_bit_size ||
          (in_type.IsSigned() && bitfield_size == *int_bit_size)) {
        auto result = valobj->CastToBasicType(int_type);
        if (result->GetError().Fail())
          return llvm::make_error<DILDiagnosticError>(
              m_expr, result->GetError().AsCString(), location);
        return result;
      }
      if (bitfield_size <= *uint_bit_size) {
        auto result = valobj->CastToBasicType(uint_type);
        if (result->GetError().Fail())
          return llvm::make_error<DILDiagnosticError>(
              m_expr, result->GetError().AsCString(), location);
        return result;
      }
      // Re-create as a const value with the same underlying type
      Scalar scalar;
      bool resolved = valobj->ResolveValue(scalar);
      if (!resolved)
        return llvm::createStringError("invalid scalar value");
      return ValueObject::CreateValueObjectFromScalar(m_exe_ctx, scalar,
                                                      in_type, "result");
    }
  }

  if (in_type.IsArrayType())
    valobj = ArrayToPointerConversion(*valobj, m_exe_ctx, "result");

  CompilerType promoted_type =
      valobj->GetCompilerType().GetPromotedIntegerType();
  if (promoted_type) {
    auto result = valobj->CastToBasicType(promoted_type);
    if (result->GetError().Fail())
      return llvm::make_error<DILDiagnosticError>(
          m_expr, result->GetError().AsCString(), location);
    return result;
  }

  return valobj;
}

/// Basic types with a lower rank are converted to the basic type
/// with a higher rank.
static size_t ConversionRank(CompilerType type) {
  switch (type.GetCanonicalType().GetBasicTypeEnumeration()) {
  case lldb::eBasicTypeBool:
    return 1;
  case lldb::eBasicTypeChar:
  case lldb::eBasicTypeSignedChar:
  case lldb::eBasicTypeUnsignedChar:
    return 2;
  case lldb::eBasicTypeShort:
  case lldb::eBasicTypeUnsignedShort:
    return 3;
  case lldb::eBasicTypeInt:
  case lldb::eBasicTypeUnsignedInt:
    return 4;
  case lldb::eBasicTypeLong:
  case lldb::eBasicTypeUnsignedLong:
    return 5;
  case lldb::eBasicTypeLongLong:
  case lldb::eBasicTypeUnsignedLongLong:
    return 6;
  case lldb::eBasicTypeInt128:
  case lldb::eBasicTypeUnsignedInt128:
    return 7;
  case lldb::eBasicTypeHalf:
    return 8;
  case lldb::eBasicTypeFloat:
    return 9;
  case lldb::eBasicTypeDouble:
    return 10;
  case lldb::eBasicTypeLongDouble:
    return 11;
  default:
    break;
  }
  return 0;
}

static lldb::BasicType BasicTypeToUnsigned(lldb::BasicType basic_type) {
  switch (basic_type) {
  case lldb::eBasicTypeChar:
  case lldb::eBasicTypeSignedChar:
    return lldb::eBasicTypeUnsignedChar;
  case lldb::eBasicTypeShort:
    return lldb::eBasicTypeUnsignedShort;
  case lldb::eBasicTypeInt:
    return lldb::eBasicTypeUnsignedInt;
  case lldb::eBasicTypeLong:
    return lldb::eBasicTypeUnsignedLong;
  case lldb::eBasicTypeLongLong:
    return lldb::eBasicTypeUnsignedLongLong;
  case lldb::eBasicTypeInt128:
    return lldb::eBasicTypeUnsignedInt128;
  default:
    return basic_type;
  }
}

llvm::Expected<CompilerType>
Interpreter::PromoteSignedInteger(CompilerType &lhs_type,
                                  CompilerType &rhs_type) {
  assert(lhs_type.IsInteger() && rhs_type.IsInteger());
  if (!lhs_type.IsSigned() && rhs_type.IsSigned()) {
    llvm::Expected<uint64_t> lhs_size =
        lhs_type.GetBitSize(m_exe_ctx.GetBestExecutionContextScope());
    if (!lhs_size)
      return lhs_size.takeError();
    llvm::Expected<uint64_t> rhs_size =
        rhs_type.GetBitSize(m_exe_ctx.GetBestExecutionContextScope());
    if (!rhs_size)
      return rhs_size.takeError();

    if (*rhs_size == *lhs_size) {
      llvm::Expected<lldb::TypeSystemSP> type_system = GetTypeSystemFromCU();
      if (!type_system)
        return type_system.takeError();
      CompilerType r_type_unsigned = GetBasicType(
          *type_system,
          BasicTypeToUnsigned(
              rhs_type.GetCanonicalType().GetBasicTypeEnumeration()));
      return r_type_unsigned;
    }
  }
  return rhs_type;
}

llvm::Expected<CompilerType>
Interpreter::ArithmeticConversion(lldb::ValueObjectSP &lhs,
                                  lldb::ValueObjectSP &rhs, uint32_t location) {
  // Apply unary conversion for both operands.
  auto lhs_or_err = UnaryConversion(lhs, location);
  if (!lhs_or_err)
    return lhs_or_err.takeError();
  lhs = *lhs_or_err;
  auto rhs_or_err = UnaryConversion(rhs, location);
  if (!rhs_or_err)
    return rhs_or_err.takeError();
  rhs = *rhs_or_err;

  CompilerType lhs_type = lhs->GetCompilerType();
  CompilerType rhs_type = rhs->GetCompilerType();

  // If types already match, no need for further conversions.
  if (lhs_type.CompareTypes(rhs_type))
    return lhs_type;

  // If either of the operands is not arithmetic (e.g. pointer), we're done.
  if (!lhs_type.IsScalarType() || !rhs_type.IsScalarType())
    return CompilerType();

  size_t l_rank = ConversionRank(lhs_type);
  size_t r_rank = ConversionRank(rhs_type);
  if (l_rank == 0 || r_rank == 0)
    return llvm::make_error<DILDiagnosticError>(
        m_expr, "unexpected basic type in arithmetic operation", location);

  // If both operands are integer, check if we need to promote
  // the higher ranked signed type.
  if (lhs_type.IsInteger() && rhs_type.IsInteger()) {
    using Rank = std::tuple<size_t, bool>;
    Rank int_l_rank = {l_rank, !lhs_type.IsSigned()};
    Rank int_r_rank = {r_rank, !rhs_type.IsSigned()};
    if (int_l_rank < int_r_rank) {
      auto type_or_err = PromoteSignedInteger(lhs_type, rhs_type);
      if (!type_or_err)
        return type_or_err.takeError();
      return *type_or_err;
    }
    if (int_l_rank > int_r_rank) {
      auto type_or_err = PromoteSignedInteger(rhs_type, lhs_type);
      if (!type_or_err)
        return type_or_err.takeError();
      return *type_or_err;
    }
    return lhs_type;
  }

  // Handle other combinations of integer and floating point operands.
  if (l_rank < r_rank)
    return rhs_type;
  return lhs_type;
}

static lldb::VariableSP DILFindVariable(ConstString name,
                                        VariableList &variable_list) {
  lldb::VariableSP exact_match;
  std::vector<lldb::VariableSP> possible_matches;

  for (lldb::VariableSP var_sp : variable_list) {
    llvm::StringRef str_ref_name = var_sp->GetName().GetStringRef();

    str_ref_name.consume_front("::");
    // Check for the exact same match
    if (str_ref_name == name.GetStringRef())
      return var_sp;

    // Check for possible matches by base name
    if (var_sp->NameMatches(name))
      possible_matches.push_back(var_sp);
  }

  // If there's a non-exact match, take it.
  if (possible_matches.size() > 0)
    return possible_matches[0];

  return nullptr;
}

lldb::ValueObjectSP LookupGlobalIdentifier(llvm::StringRef name_ref,
                                           ExecutionContext &exe_ctx,
                                           lldb::DynamicValueType use_dynamic) {
  // Get a global variables list without the locals from the current frame
  auto frame_sp = exe_ctx.GetFrameSP();
  if (!frame_sp)
    return nullptr;
  SymbolContext symbol_context =
      frame_sp->GetSymbolContext(lldb::eSymbolContextCompUnit);
  lldb::VariableListSP variable_list;
  if (symbol_context.comp_unit)
    variable_list = symbol_context.comp_unit->GetVariableList(true);

  name_ref.consume_front("::");
  lldb::ValueObjectSP value_sp;
  if (variable_list) {
    lldb::VariableSP var_sp =
        DILFindVariable(ConstString(name_ref), *variable_list);
    if (var_sp)
      value_sp = frame_sp->GetValueObjectForFrameVariable(var_sp, use_dynamic);
  }

  if (value_sp)
    return value_sp;

  // Check for match in modules global variables.
  auto target_sp = exe_ctx.GetTargetSP();
  if (!target_sp)
    return nullptr;
  VariableList modules_var_list;
  target_sp->GetImages().FindGlobalVariables(
      ConstString(name_ref), std::numeric_limits<uint32_t>::max(),
      modules_var_list);

  if (!modules_var_list.Empty()) {
    lldb::VariableSP var_sp =
        DILFindVariable(ConstString(name_ref), modules_var_list);
    if (var_sp)
      value_sp = ValueObjectVariable::Create(
          exe_ctx.GetBestExecutionContextScope(), var_sp);

    if (value_sp)
      return value_sp;
  }
  return nullptr;
}

lldb::ValueObjectSP LookupPersistentIdentifier(llvm::StringRef name_ref,
                                               ExecutionContext &exe_ctx,
                                               lldb::LanguageType language) {
  auto target_sp = exe_ctx.GetTargetSP();
  if (!target_sp)
    return nullptr;

  if (name_ref.starts_with("$")) {
    if (auto *state =
            target_sp->GetPersistentExpressionStateForLanguage(language))
      if (auto var_sp = state->GetVariable(name_ref))
        if (auto valobj_sp = var_sp->GetValueObject())
          return valobj_sp;
  }
  return nullptr;
}

lldb::ValueObjectSP LookupIdentifier(llvm::StringRef name_ref,
                                     ExecutionContext &exe_ctx,
                                     lldb::DynamicValueType use_dynamic) {
  // Support $rax as a special syntax for accessing registers.
  // Will return an invalid value in case the requested register doesn't exist.
  auto frame_sp = exe_ctx.GetFrameSP();
  if (!frame_sp)
    return nullptr;
  if (name_ref.consume_front("$")) {
    lldb::RegisterContextSP reg_ctx(frame_sp->GetRegisterContext());
    if (!reg_ctx)
      return nullptr;

    if (const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(name_ref))
      return ValueObjectRegister::Create(exe_ctx.GetBestExecutionContextScope(),
                                         reg_ctx, reg_info);

    return nullptr;
  }

  if (!name_ref.contains("::")) {
    // Lookup in the current frame.
    // Try looking for a local variable in current scope.
    lldb::VariableListSP variable_list(frame_sp->GetInScopeVariableList(false));

    lldb::ValueObjectSP value_sp;
    if (variable_list) {
      lldb::VariableSP var_sp =
          variable_list->FindVariable(ConstString(name_ref));
      if (var_sp)
        value_sp =
            frame_sp->GetValueObjectForFrameVariable(var_sp, use_dynamic);
    }

    if (value_sp)
      return value_sp;

    // Try looking for an instance variable (class member).
    SymbolContext sc = frame_sp->GetSymbolContext(lldb::eSymbolContextFunction |
                                                  lldb::eSymbolContextBlock);
    llvm::StringRef instance_name = sc.GetInstanceName();
    value_sp = frame_sp->FindVariable(ConstString(instance_name));
    if (value_sp)
      value_sp = value_sp->GetChildMemberWithName(name_ref);

    if (value_sp)
      return value_sp;
  }
  return nullptr;
}

lldb::ValueObjectSP LookupEnumValue(llvm::StringRef name_ref,
                                    ExecutionContext &exe_ctx) {
  if (name_ref.contains("::")) {
    llvm::StringRef enum_typename, enumerator_name;
    // FIXME: Change this to a structured binding for lambda capturing
    // once we have C++20.
    std::tie(enum_typename, enumerator_name) = name_ref.rsplit("::");
    CompilerType enum_type = ResolveTypeByName(enum_typename.str(), exe_ctx);
    lldb::ValueObjectSP result;
    enum_type.ForEachEnumerator([&](const CompilerType &integer_type,
                                    ConstString name,
                                    const llvm::APSInt &value) -> bool {
      if (name == enumerator_name) {
        Scalar scalar(value);
        result = ValueObject::CreateValueObjectFromScalar(exe_ctx, scalar,
                                                          enum_type, "result");
        return false; // Stop iterating
      }
      return true;
    });
    return result;
  }
  return nullptr;
}

Interpreter::Interpreter(ExecutionContext &exe_ctx, llvm::StringRef expr,
                         lldb::DynamicValueType use_dynamic, uint32_t options)
    : m_exe_ctx(exe_ctx), m_expr(expr), m_use_dynamic(use_dynamic) {

  const bool check_ptr_vs_member =
      (options & StackFrame::eExpressionPathOptionCheckPtrVsMember) != 0;
  const bool no_synth_child =
      (options & StackFrame::eExpressionPathOptionsNoSyntheticChildren) != 0;
  const bool allow_var_updates =
      (options & StackFrame::eExpressionPathOptionsAllowVarUpdates) != 0;
  const bool disallow_globals =
      (options & StackFrame::eExpressionPathOptionsDisallowGlobals) != 0;

  m_use_synthetic = !no_synth_child;
  m_check_ptr_vs_member = check_ptr_vs_member;
  m_allow_var_updates = allow_var_updates;
  m_allow_globals = !disallow_globals;
}

llvm::Expected<lldb::ValueObjectSP>
Interpreter::EvaluateTree(const ASTNodeUP &tree) {
  assert(tree && "ASTNodeUP must not contain a nullptr");

  auto value_or_error = Interpreter::Evaluate(*tree);
  if (!value_or_error) {
    auto error = value_or_error.takeError();
    LLDB_LOG(GetLog(LLDBLog::Expressions),
             "[Interpreter::Evaluate] DIL interpreter failed:\n{0}",
             llvm::toStringWithoutConsuming(error));
    return error;
  }

  return value_or_error;
}

llvm::Expected<lldb::ValueObjectSP> Interpreter::Evaluate(const ASTNode &node) {
  // Evaluate an AST.
  auto value_or_error = node.Accept(this);
  // Convert SP with a nullptr to an error.
  if (value_or_error && !*value_or_error)
    return llvm::make_error<DILDiagnosticError>(m_expr, "invalid value object",
                                                node.GetLocation());
  // Return the computed value-or-error. The caller is responsible for
  // checking if an error occurred during the evaluation.
  return value_or_error;
}

llvm::Expected<lldb::ValueObjectSP>
Interpreter::EvaluateAndDereference(const ASTNode &node) {
  auto valobj_or_err = Evaluate(node);
  if (!valobj_or_err)
    return valobj_or_err;
  lldb::ValueObjectSP valobj = *valobj_or_err;

  Status error;
  if (valobj->GetCompilerType().IsReferenceType()) {
    valobj = valobj->Dereference(error);
    if (error.Fail())
      return error.ToError();
  }
  return valobj;
}

llvm::Expected<lldb::ValueObjectSP>
Interpreter::Visit(const IdentifierNode &node) {
  lldb::DynamicValueType use_dynamic = m_use_dynamic;

  lldb::ValueObjectSP identifier =
      LookupIdentifier(node.GetName(), m_exe_ctx, use_dynamic);

  if (!identifier && m_allow_globals)
    identifier = LookupGlobalIdentifier(node.GetName(), m_exe_ctx, use_dynamic);

  if (!identifier)
    identifier = LookupEnumValue(node.GetName(), m_exe_ctx);

  if (!identifier && node.GetName()[0] == '$') {
    auto language = GetSourceLanguageFromCU();
    if (language)
      identifier =
          LookupPersistentIdentifier(node.GetName(), m_exe_ctx, language.get());
    else
      // Fall through to the unknown identifier diagnostic without a CU.
      llvm::consumeError(language.takeError());
  }

  if (!identifier && node.GetName() == "nullptr") {
    // If we got a "nullptr" identifier, and there is no defined variable with
    // this name, resolve it as a null pointer.
    llvm::Expected<lldb::TypeSystemSP> type_system = GetTypeSystemFromCU();
    if (!type_system)
      return type_system.takeError();
    llvm::APInt value(type_system.get()->GetPointerByteSize() * CHAR_BIT, 0);
    Scalar scalar(value);
    CompilerType type = GetBasicType(*type_system, lldb::eBasicTypeNullPtr);
    return ValueObject::CreateValueObjectFromScalar(m_exe_ctx, scalar, type,
                                                    "result");
  }

  if (!identifier) {
    std::string errMsg =
        llvm::formatv("use of undeclared identifier '{0}'", node.GetName());
    return llvm::make_error<DILDiagnosticError>(
        m_expr, errMsg, node.GetLocation(), node.GetName().size());
  }

  return identifier;
}

llvm::Expected<lldb::ValueObjectSP>
Interpreter::Visit(const UnaryOpNode &node) {
  Status error;
  auto op_or_err = Evaluate(node.GetOperand());
  if (!op_or_err)
    return op_or_err;

  lldb::ValueObjectSP operand = *op_or_err;

  switch (node.GetKind()) {
  case UnaryOpKind::Deref: {
    lldb::ValueObjectSP dynamic_op = operand->GetDynamicValue(m_use_dynamic);
    if (dynamic_op)
      operand = dynamic_op;

    lldb::ValueObjectSP child_sp = operand->Dereference(error);
    if (!child_sp && m_use_synthetic) {
      if (lldb::ValueObjectSP synth_obj_sp = operand->GetSyntheticValue()) {
        error.Clear();
        child_sp = synth_obj_sp->Dereference(error);
      }
    }
    if (error.Fail())
      return llvm::make_error<DILDiagnosticError>(m_expr, error.AsCString(),
                                                  node.GetLocation());

    return child_sp;
  }
  case UnaryOpKind::AddrOf: {
    Status error;
    lldb::ValueObjectSP value = operand->AddressOf(error);
    if (error.Fail())
      return llvm::make_error<DILDiagnosticError>(m_expr, error.AsCString(),
                                                  node.GetLocation());

    return value;
  }
  case UnaryOpKind::Minus: {
    if (operand->GetCompilerType().IsReferenceType()) {
      operand = operand->Dereference(error);
      if (error.Fail())
        return error.ToError();
    }
    llvm::Expected<lldb::ValueObjectSP> conv_op =
        UnaryConversion(operand, node.GetOperand().GetLocation());
    if (!conv_op)
      return conv_op;
    operand = *conv_op;
    CompilerType operand_type = operand->GetCompilerType();
    if (!operand_type.IsScalarType()) {
      std::string errMsg =
          llvm::formatv("invalid argument type '{0}' to unary expression",
                        operand_type.GetTypeName());
      return llvm::make_error<DILDiagnosticError>(m_expr, errMsg,
                                                  node.GetLocation());
    }
    Scalar scalar;
    bool resolved = operand->ResolveValue(scalar);
    if (!resolved)
      break;

    bool negated = scalar.UnaryNegate();
    if (negated)
      return ValueObject::CreateValueObjectFromScalar(
          m_exe_ctx, scalar, operand->GetCompilerType(), "result");
    break;
  }
  case UnaryOpKind::Plus: {
    if (operand->GetCompilerType().IsReferenceType()) {
      operand = operand->Dereference(error);
      if (error.Fail())
        return error.ToError();
    }
    llvm::Expected<lldb::ValueObjectSP> conv_op =
        UnaryConversion(operand, node.GetOperand().GetLocation());
    if (!conv_op)
      return conv_op;
    operand = *conv_op;
    CompilerType operand_type = operand->GetCompilerType();
    if (!operand_type.IsScalarType() &&
        // Unary plus is allowed for pointers.
        !operand_type.IsPointerType()) {
      std::string errMsg =
          llvm::formatv("invalid argument type '{0}' to unary expression",
                        operand_type.GetTypeName());
      return llvm::make_error<DILDiagnosticError>(m_expr, errMsg,
                                                  node.GetLocation());
    }
    return operand;
  }
  case UnaryOpKind::Not: {
    if (operand->GetCompilerType().IsReferenceType()) {
      operand = operand->Dereference(error);
      if (error.Fail())
        return error.ToError();
    }
    llvm::Expected<lldb::ValueObjectSP> conv_op =
        UnaryConversion(operand, node.GetLocation());
    if (!conv_op)
      return conv_op;
    operand = *conv_op;
    CompilerType operand_type = operand->GetCompilerType();
    if (!operand_type.IsInteger()) {
      std::string errMsg =
          llvm::formatv("invalid argument type '{0}' to unary expression",
                        operand_type.GetTypeName());
      return llvm::make_error<DILDiagnosticError>(m_expr, errMsg,
                                                  node.GetLocation());
    }
    Scalar scalar;
    bool resolved = operand->ResolveValue(scalar);
    if (!resolved) {
      std::string errMsg = llvm::formatv("invalid operand value: {0}",
                                         operand->GetError().AsCString());
      return llvm::make_error<DILDiagnosticError>(m_expr, errMsg,
                                                  node.GetLocation());
    }

    bool flipped = scalar.OnesComplement();
    if (flipped)
      return ValueObject::CreateValueObjectFromScalar(
          m_exe_ctx, scalar, operand->GetCompilerType(), "result");
    break;
  }
  case UnaryOpKind::LNot: {
    if (operand->GetCompilerType().IsReferenceType()) {
      operand = operand->Dereference(error);
      if (error.Fail())
        return error.ToError();
    }
    CompilerType operand_type = operand->GetCompilerType();
    if (!operand_type.IsContextuallyConvertibleToBool()) {
      std::string errMsg =
          llvm::formatv("invalid argument type '{0}' to unary expression",
                        operand_type.GetTypeName());
      return llvm::make_error<DILDiagnosticError>(m_expr, errMsg,
                                                  node.GetLocation());
    }
    llvm::Expected<lldb::TypeSystemSP> type_system = GetTypeSystemFromCU();
    if (!type_system)
      return type_system.takeError();
    auto value_or_err = operand->GetValueAsBool();
    if (!value_or_err)
      return value_or_err.takeError();
    return ValueObject::CreateValueObjectFromBool(m_exe_ctx, *type_system,
                                                  !(*value_or_err), "result");
  }
  }
  return llvm::make_error<DILDiagnosticError>(m_expr, "invalid unary operation",
                                              node.GetLocation());
}

llvm::Expected<lldb::ValueObjectSP>
Interpreter::PointerOffset(lldb::ValueObjectSP ptr, lldb::ValueObjectSP offset,
                           BinaryOpKind operation, uint32_t location) {
  assert(operation == BinaryOpKind::Add || operation == BinaryOpKind::Sub);
  if (ptr->GetCompilerType().IsPointerToVoid())
    return llvm::make_error<DILDiagnosticError>(
        m_expr, "arithmetic on a pointer to void", location);
  if (ptr->GetValueAsUnsigned(0) == 0 && offset != 0)
    return llvm::make_error<DILDiagnosticError>(
        m_expr, "arithmetic on a nullptr is undefined", location);

  bool success;
  int64_t offset_int = offset->GetValueAsSigned(0, &success);
  if (!success) {
    std::string errMsg = llvm::formatv("could not get the offset: {0}",
                                       offset->GetError().AsCString());
    return llvm::make_error<DILDiagnosticError>(m_expr, std::move(errMsg),
                                                location);
  }

  llvm::Expected<uint64_t> byte_size =
      ptr->GetCompilerType().GetPointeeType().GetByteSize(
          m_exe_ctx.GetBestExecutionContextScope());
  if (!byte_size)
    return byte_size.takeError();
  uint64_t ptr_addr = ptr->GetValueAsUnsigned(0);
  if (operation == BinaryOpKind::Sub)
    ptr_addr -= offset_int * (*byte_size);
  else
    ptr_addr += offset_int * (*byte_size);

  Scalar scalar(ptr_addr);
  return ValueObject::CreateValueObjectFromScalar(
      m_exe_ctx, scalar, ptr->GetCompilerType(), "result");
}

llvm::Expected<lldb::ValueObjectSP>
Interpreter::EvaluateScalarOp(BinaryOpKind kind, lldb::ValueObjectSP lhs,
                              lldb::ValueObjectSP rhs, CompilerType result_type,
                              uint32_t location) {
  Scalar l, r;
  bool l_resolved = lhs->ResolveValue(l);
  if (!l_resolved) {
    std::string errMsg =
        llvm::formatv("invalid lhs value: {0}", lhs->GetError().AsCString());
    return llvm::make_error<DILDiagnosticError>(m_expr, errMsg, location);
  }
  bool r_resolved = rhs->ResolveValue(r);
  if (!r_resolved) {
    std::string errMsg =
        llvm::formatv("invalid rhs value: {0}", rhs->GetError().AsCString());
    return llvm::make_error<DILDiagnosticError>(m_expr, errMsg, location);
  }

  auto value_object = [this, result_type](Scalar scalar) {
    return ValueObject::CreateValueObjectFromScalar(m_exe_ctx, scalar,
                                                    result_type, "result");
  };

  switch (kind) {
  case BinaryOpKind::Add:
    return value_object(l + r);
  case BinaryOpKind::Sub:
    return value_object(l - r);
  case BinaryOpKind::Mul:
    return value_object(l * r);
  case BinaryOpKind::Div:
    return value_object(l / r);
  case BinaryOpKind::Rem:
    return value_object(l % r);
  case BinaryOpKind::And:
    return value_object(l & r);
  case BinaryOpKind::Xor:
    return value_object(l ^ r);
  case BinaryOpKind::Or:
    return value_object(l | r);
  case BinaryOpKind::Shl:
    return value_object(l << r);
  case BinaryOpKind::Shr:
    return value_object(l >> r);
  case BinaryOpKind::LT:
    return value_object(l < r);
  case BinaryOpKind::GT:
    return value_object(l > r);
  case BinaryOpKind::LE:
    return value_object(l <= r);
  case BinaryOpKind::GE:
    return value_object(l >= r);
  case BinaryOpKind::EQ:
    return value_object(l == r);
  case BinaryOpKind::NE:
    return value_object(l != r);
  default:
    break;
  }
  return llvm::make_error<DILDiagnosticError>(
      m_expr, "invalid arithmetic operation", location);
}

llvm::Expected<lldb::ValueObjectSP> Interpreter::EvaluateBinaryAddition(
    lldb::ValueObjectSP lhs, lldb::ValueObjectSP rhs, uint32_t location) {
  // Operation '+' works for:
  //   {scalar,unscoped_enum} <-> {scalar,unscoped_enum}
  //   {integer,unscoped_enum} <-> pointer
  //   pointer <-> {integer,unscoped_enum}
  auto orig_lhs_type = lhs->GetCompilerType();
  auto orig_rhs_type = rhs->GetCompilerType();
  auto type_or_err = ArithmeticConversion(lhs, rhs, location);
  if (!type_or_err)
    return type_or_err.takeError();
  CompilerType result_type = *type_or_err;

  if (result_type.IsScalarType())
    return EvaluateScalarOp(BinaryOpKind::Add, lhs, rhs, result_type, location);

  // Check for pointer arithmetics.
  // One of the operands must be a pointer and the other one an integer.
  lldb::ValueObjectSP ptr, offset;
  if (lhs->GetCompilerType().IsPointerType()) {
    ptr = lhs;
    offset = rhs;
  } else if (rhs->GetCompilerType().IsPointerType()) {
    ptr = rhs;
    offset = lhs;
  }

  if (!ptr || !offset->GetCompilerType().IsInteger()) {
    std::string errMsg =
        llvm::formatv("invalid operands to binary expression ('{0}' and '{1}')",
                      orig_lhs_type.GetTypeName(), orig_rhs_type.GetTypeName());
    return llvm::make_error<DILDiagnosticError>(m_expr, std::move(errMsg),
                                                location);
  }

  return PointerOffset(ptr, offset, BinaryOpKind::Add, location);
}

llvm::Expected<lldb::ValueObjectSP> Interpreter::EvaluateBinarySubtraction(
    lldb::ValueObjectSP lhs, lldb::ValueObjectSP rhs, uint32_t location) {
  // Operation '-' works for:
  //   {scalar,unscoped_enum} <-> {scalar,unscoped_enum}
  //   pointer <-> {integer,unscoped_enum}
  //   pointer <-> pointer (if pointee types are compatible)
  auto orig_lhs_type = lhs->GetCompilerType();
  auto orig_rhs_type = rhs->GetCompilerType();
  auto type_or_err = ArithmeticConversion(lhs, rhs, location);
  if (!type_or_err)
    return type_or_err.takeError();
  CompilerType result_type = *type_or_err;

  if (result_type.IsScalarType())
    return EvaluateScalarOp(BinaryOpKind::Sub, lhs, rhs, result_type, location);

  auto lhs_type = lhs->GetCompilerType();
  auto rhs_type = rhs->GetCompilerType();

  // "pointer - integer" operation.
  if (lhs_type.IsPointerType() && rhs_type.IsInteger())
    return PointerOffset(lhs, rhs, BinaryOpKind::Sub, location);

  // "pointer - pointer" operation.
  if (lhs_type.IsPointerType() && rhs_type.IsPointerType()) {
    if (lhs_type.IsPointerToVoid() && rhs_type.IsPointerToVoid()) {
      return llvm::make_error<DILDiagnosticError>(
          m_expr, "arithmetic on pointers to void", location);
    }
    // Compare canonical unqualified pointer types.
    CompilerType lhs_unqualified_type = lhs_type.GetCanonicalType();
    CompilerType rhs_unqualified_type = rhs_type.GetCanonicalType();
    if (!lhs_unqualified_type.CompareTypes(rhs_unqualified_type)) {
      std::string errMsg = llvm::formatv(
          "'{0}' and '{1}' are not pointers to compatible types",
          orig_lhs_type.GetTypeName(), orig_rhs_type.GetTypeName());
      return llvm::make_error<DILDiagnosticError>(m_expr, errMsg, location);
    }

    llvm::Expected<uint64_t> lhs_byte_size =
        lhs_type.GetPointeeType().GetByteSize(
            m_exe_ctx.GetBestExecutionContextScope());
    if (!lhs_byte_size)
      return lhs_byte_size.takeError();
    // Since pointers have compatible types, both have the same pointee size.
    int64_t item_size = *lhs_byte_size;
    int64_t diff = static_cast<int64_t>(lhs->GetValueAsUnsigned(0) -
                                        rhs->GetValueAsUnsigned(0));
    assert(item_size > 0 && "Pointee size cannot be 0");
    if (diff % item_size != 0) {
      // If address difference isn't divisible by pointee size then performing
      // the operation is undefined behaviour.
      return llvm::make_error<DILDiagnosticError>(
          m_expr, "undefined pointer arithmetic", location);
    }
    diff /= item_size;

    llvm::Expected<lldb::TypeSystemSP> type_system = GetTypeSystemFromCU();
    if (!type_system)
      return type_system.takeError();
    CompilerType ptrdiff_type = type_system.get()->GetPointerDiffType(true);
    if (!ptrdiff_type)
      return llvm::make_error<DILDiagnosticError>(
          m_expr, "unable to determine pointer diff type", location);

    Scalar scalar(diff);
    return ValueObject::CreateValueObjectFromScalar(m_exe_ctx, scalar,
                                                    ptrdiff_type, "result");
  }

  std::string errMsg =
      llvm::formatv("invalid operands to binary expression ('{0}' and '{1}')",
                    orig_lhs_type.GetTypeName(), orig_rhs_type.GetTypeName());
  return llvm::make_error<DILDiagnosticError>(m_expr, std::move(errMsg),
                                              location);
}

llvm::Expected<lldb::ValueObjectSP> Interpreter::EvaluateBinaryMultiplication(
    lldb::ValueObjectSP lhs, lldb::ValueObjectSP rhs, uint32_t location) {
  // Operation '*' works for:
  //  {scalar,unscoped_enum} <-> {scalar,unscoped_enum}
  auto orig_lhs_type = lhs->GetCompilerType();
  auto orig_rhs_type = rhs->GetCompilerType();
  auto type_or_err = ArithmeticConversion(lhs, rhs, location);
  if (!type_or_err)
    return type_or_err.takeError();
  CompilerType result_type = *type_or_err;

  if (!result_type.IsScalarType()) {
    std::string errMsg =
        llvm::formatv("invalid operands to binary expression ('{0}' and '{1}')",
                      orig_lhs_type.GetTypeName(), orig_rhs_type.GetTypeName());
    return llvm::make_error<DILDiagnosticError>(m_expr, std::move(errMsg),
                                                location);
  }

  return EvaluateScalarOp(BinaryOpKind::Mul, lhs, rhs, result_type, location);
}

llvm::Expected<lldb::ValueObjectSP> Interpreter::EvaluateBinaryDivision(
    lldb::ValueObjectSP lhs, lldb::ValueObjectSP rhs, uint32_t location) {
  // Operation '/' works for:
  //  {scalar,unscoped_enum} <-> {scalar,unscoped_enum}
  auto orig_lhs_type = lhs->GetCompilerType();
  auto orig_rhs_type = rhs->GetCompilerType();
  auto type_or_err = ArithmeticConversion(lhs, rhs, location);
  if (!type_or_err)
    return type_or_err.takeError();
  CompilerType result_type = *type_or_err;

  if (!result_type.IsScalarType()) {
    std::string errMsg =
        llvm::formatv("invalid operands to binary expression ('{0}' and '{1}')",
                      orig_lhs_type.GetTypeName(), orig_rhs_type.GetTypeName());
    return llvm::make_error<DILDiagnosticError>(m_expr, std::move(errMsg),
                                                location);
  }

  // Check for zero only for integer division.
  if (result_type.IsInteger() && rhs->GetValueAsSigned(-1) == 0) {
    return llvm::make_error<DILDiagnosticError>(
        m_expr, "division by zero is undefined", location);
  }

  return EvaluateScalarOp(BinaryOpKind::Div, lhs, rhs, result_type, location);
}

llvm::Expected<lldb::ValueObjectSP> Interpreter::EvaluateBinaryRemainder(
    lldb::ValueObjectSP lhs, lldb::ValueObjectSP rhs, uint32_t location) {
  // Operation '%' works for:
  //  {integer,unscoped_enum} <-> {integer,unscoped_enum}
  auto orig_lhs_type = lhs->GetCompilerType();
  auto orig_rhs_type = rhs->GetCompilerType();
  auto type_or_err = ArithmeticConversion(lhs, rhs, location);
  if (!type_or_err)
    return type_or_err.takeError();
  CompilerType result_type = *type_or_err;

  if (!result_type.IsInteger()) {
    std::string errMsg =
        llvm::formatv("invalid operands to binary expression ('{0}' and '{1}')",
                      orig_lhs_type.GetTypeName(), orig_rhs_type.GetTypeName());
    return llvm::make_error<DILDiagnosticError>(m_expr, std::move(errMsg),
                                                location);
  }

  if (rhs->GetValueAsSigned(-1) == 0) {
    return llvm::make_error<DILDiagnosticError>(
        m_expr, "division by zero is undefined", location);
  }

  return EvaluateScalarOp(BinaryOpKind::Rem, lhs, rhs, result_type, location);
}

static bool HasFloatingRepresentation(CompilerType ct) {
  return ct.GetTypeInfo() & lldb::eTypeIsFloat;
}

static llvm::Expected<bool> VerifyAssignmentTypes(CompilerType lhs_type,
                                                  CompilerType rhs_type) {
  // Make sure lhs is a legal type for DIL assignment.
  if (!lhs_type.IsInteger() && !lhs_type.IsUnscopedEnumerationType() &&
      !HasFloatingRepresentation(lhs_type) && !lhs_type.IsPointerType() &&
      !lhs_type.IsScalarType())
    return llvm::createStringError(
        "Illegal type for lhs of assignment (not scalar numeric type)");

  // Make sure rhs is a legal type for DIL assignment.
  if (!rhs_type.IsInteger() && !rhs_type.IsUnscopedEnumerationType() &&
      !HasFloatingRepresentation(rhs_type) && !rhs_type.IsPointerType())
    return llvm::createStringError(
        "Illegal type for rhs of assignment (not scalar numeric type)");

  // Only allow assigning pointers to pointers.
  if ((lhs_type.IsPointerType() && !rhs_type.IsPointerType()) ||
      (!lhs_type.IsPointerType() && rhs_type.IsPointerType()))
    return llvm::createStringError(
        "Invalid assignment: Can only assign pointers to pointers");

  // For "real numbers", the types must match exactly.
  if ((HasFloatingRepresentation(rhs_type) ||
       HasFloatingRepresentation(lhs_type)) &&
      lhs_type != rhs_type) {
    std::string err_msg =
        llvm::formatv("Incompatible types for assignment: Cannot assign {0} "
                      "to {1}",
                      rhs_type.TypeDescription(), lhs_type.TypeDescription());
    return llvm::createStringError(err_msg);
  }

  return true;
}

llvm::Expected<lldb::ValueObjectSP>
Interpreter::EvaluateAssignment(lldb::ValueObjectSP lhs,
                                lldb::ValueObjectSP rhs, uint32_t location) {

  // Verify that lhs can accept an assignment.
  if (llvm::Error err = lhs->CanSetValue())
    return err;

  auto all_ok =
      VerifyAssignmentTypes(lhs->GetCompilerType(), rhs->GetCompilerType());
  if (!all_ok)
    return all_ok.takeError();

  if (llvm::Error e = lhs->SetValueFromInteger(rhs, m_allow_var_updates))
    return e;

  return lhs;
}

static bool IsLiteralZero(lldb::ValueObjectSP &val, bool is_literal) {
  bool is_zero = val->GetValueAsUnsigned(-1) == 0;
  bool is_boolean = val->GetCompilerType().IsBoolean();
  return is_zero && !is_boolean && is_literal;
}

llvm::Error
Interpreter::ValidateComparison(BinaryOpKind kind, lldb::ValueObjectSP &lhs,
                                lldb::ValueObjectSP &rhs, bool lhs_is_literal,
                                bool rhs_is_literal, uint32_t location) {
  auto orig_lhs_type = lhs->GetCompilerType();
  auto orig_rhs_type = rhs->GetCompilerType();

  bool is_ordered = (kind == BinaryOpKind::LT || kind == BinaryOpKind::LE ||
                     kind == BinaryOpKind::GT || kind == BinaryOpKind::GE);
  bool lhs_nullptr_or_zero =
      orig_lhs_type.IsNullPtrType() || IsLiteralZero(lhs, lhs_is_literal);
  bool rhs_nullptr_or_zero =
      orig_rhs_type.IsNullPtrType() || IsLiteralZero(rhs, rhs_is_literal);

  if (orig_lhs_type.IsArrayType())
    lhs = ArrayToPointerConversion(*lhs, m_exe_ctx, "result");
  if (orig_rhs_type.IsArrayType())
    rhs = ArrayToPointerConversion(*rhs, m_exe_ctx, "result");

  CompilerType lhs_type = lhs->GetCompilerType();
  CompilerType rhs_type = rhs->GetCompilerType();

  if (lhs_type == rhs_type)
    return llvm::Error::success();

  lldb::ValueObjectSP lhs_child;
  lldb::ValueObjectSP rhs_child;
  bool is_signed;

  if (!lhs_nullptr_or_zero && !lhs_type.IsPointerType() &&
      !lhs_type.IsIntegerOrEnumerationType(is_signed)) {
    // lhs is not a nullptr, pointer, enum or integer. Check to see if its
    // first child could be a pointer. If so, update lhs_type accordingly.
    lhs_child = lhs->GetChildAtIndex(0);
    if (lhs_child && (lhs_child->IsPointerType() ||
                      lhs_child->GetCompilerType().IsNullPtrType()))
      lhs_type = lhs_child->GetCompilerType();
  }
  if (!rhs_nullptr_or_zero && !rhs_type.IsPointerType() &&
      !rhs_type.IsIntegerOrEnumerationType(is_signed)) {
    // rhs is not a nullptr, pointer, enum or integer. Check to see if its
    // first child could be a pointer. If so, update rhs_type accordingly.
    rhs_child = rhs->GetChildAtIndex(0);
    if (rhs_child && (rhs_child->IsPointerType() ||
                      rhs_child->GetCompilerType().IsNullPtrType()))
      rhs_type = rhs_child->GetCompilerType();
  }

  if ((lhs_type != orig_lhs_type) || (rhs_type != orig_rhs_type)) {
    if (lhs_type.IsNullPtrType() || rhs_type.IsNullPtrType())
      return llvm::Error::success();

    // May be an integer or enum.
    if (!lhs_type.IsPointerType() || !rhs_type.IsPointerType())
      return llvm::Error::success();

    CompilerType lhs_unqualified =
        lhs_type.GetCanonicalType().GetFullyUnqualifiedType();
    CompilerType rhs_unqualified =
        rhs_type.GetCanonicalType().GetFullyUnqualifiedType();

    if (lhs_unqualified.IsPointerToVoid() || rhs_unqualified.IsPointerToVoid())
      return llvm::Error::success();

    // We have two pointers, neither of which is nullptr or void *. Make
    // sure their types are compatible.
    bool comparable = lhs_unqualified.CompareTypes(rhs_unqualified);
    if (comparable)
      return llvm::Error::success();

    std::string errMsg = llvm::formatv(
        "comparison of distinct pointer types ({0} and {1})",
        orig_lhs_type.TypeDescription(), orig_rhs_type.TypeDescription());
    return llvm::make_error<DILDiagnosticError>(m_expr, errMsg, location);
  }

  if (!is_ordered && ((orig_lhs_type.IsNullPtrType() && rhs_nullptr_or_zero) ||
                      (lhs_nullptr_or_zero && orig_rhs_type.IsNullPtrType())))
    return llvm::Error::success();

  // If the operands has arithmetic or enumeration type (scoped or unscoped),
  // usual arithmetic conversions are performed on both operands following the
  // rules for arithmetic operators.
  auto type_or_err = ArithmeticConversion(lhs, rhs, location);
  if (!type_or_err)
    return type_or_err.takeError();

  lhs_type = lhs->GetCompilerType();
  rhs_type = rhs->GetCompilerType();
  if (lhs_type.IsScalarOrUnscopedEnumerationType() &&
      rhs_type.IsScalarOrUnscopedEnumerationType())
    return llvm::Error::success();

  // Scoped enums can be compared only to the instances of the same type.
  if (lhs_type.IsScopedEnumerationType() ||
      rhs_type.IsScopedEnumerationType()) {
    if (lhs_type.CompareTypes(rhs_type))
      return llvm::Error::success();
    std::string errMsg = llvm::formatv(
        "invalid operands to binary expression ({0} and {1})",
        orig_lhs_type.TypeDescription(), orig_rhs_type.TypeDescription());
    return llvm::make_error<DILDiagnosticError>(m_expr, errMsg, location);
  }

  // Check if the value can be compared to a pointer. We allow all pointers,
  // integers, unscoped enumerations and a `nullptr` literal if it's an
  // equality/inequality comparison, including comparing a pointer with an
  // integer representing an address. This also allows comparing `nullptr` and
  // any integer, not just literal zero, e.g. `nullptr == 1` is false.
  auto comparable_to_pointer = [&](CompilerType t) {
    return t.IsPointerType() || t.IsInteger() ||
           t.IsUnscopedEnumerationType() || (!is_ordered && t.IsNullPtrType());
  };

  if ((lhs_type.IsPointerType() && comparable_to_pointer(rhs_type)) ||
      (comparable_to_pointer(lhs_type) && rhs_type.IsPointerType())) {
    // If both are pointers, check if they have comparable types.
    if ((lhs_type.IsPointerType() && !lhs_type.IsPointerToVoid()) &&
        (rhs_type.IsPointerType() && !rhs_type.IsPointerToVoid())) {
      // Compare canonical unqualified pointer types.
      CompilerType lhs_unqualified_type =
          lhs_type.GetCanonicalType().GetFullyUnqualifiedType();
      CompilerType rhs_unqualified_type =
          rhs_type.GetCanonicalType().GetFullyUnqualifiedType();
      bool comparable = lhs_unqualified_type.CompareTypes(rhs_unqualified_type);

      if (!comparable) {

        std::string errMsg = llvm::formatv(
            "comparison of distinct pointer types ({0} and {1})",
            orig_lhs_type.TypeDescription(), orig_rhs_type.TypeDescription());
        return llvm::make_error<DILDiagnosticError>(m_expr, errMsg, location);
      }
    }
    // Comparing pointers to void is always allowed.
    return llvm::Error::success();
  }

  std::string errMsg = llvm::formatv(
      "invalid operands to binary expression ({0} and {1})",
      orig_lhs_type.TypeDescription(), orig_rhs_type.TypeDescription());
  return llvm::make_error<DILDiagnosticError>(m_expr, errMsg, location);
}

llvm::Expected<lldb::ValueObjectSP>
Interpreter::EvaluateComparison(BinaryOpKind kind, lldb::ValueObjectSP lhs,
                                lldb::ValueObjectSP rhs, bool lhs_is_literal,
                                bool rhs_is_literal, uint32_t location) {
  // Comparison works for:
  //  nullptr_t <-> {nullptr_t,integer} (if integer is literal zero)
  //  {nullptr_t,integer} <-> nullptr_t (if integer is literal zero)
  //  {scalar,unscoped_enum} <-> {scalar,unscoped_enum}
  //  scoped_enum <-> scoped_enum (if the same type)
  //  pointer <-> pointer (if pointee types are compatible)
  //  pointer <-> {integer,unscoped_enum,nullptr_t}
  //  {integer,unscoped_enum,nullptr_t} <-> pointer
  if (auto error = ValidateComparison(kind, lhs, rhs, lhs_is_literal,
                                      rhs_is_literal, location))
    return error;

  llvm::Expected<lldb::TypeSystemSP> type_system = GetTypeSystemFromCU();
  if (!type_system)
    return type_system.takeError();
  CompilerType boolean_type = GetBasicType(*type_system, lldb::eBasicTypeBool);

  return EvaluateScalarOp(kind, lhs, rhs, boolean_type, location);
}

llvm::Expected<lldb::ValueObjectSP>
Interpreter::EvaluateBinaryBitwise(BinaryOpKind kind, lldb::ValueObjectSP lhs,
                                   lldb::ValueObjectSP rhs, uint32_t location) {
  // Operations {'&', '|', '^'} work for:
  //  {integer,unscoped_enum} <-> {integer,unscoped_enum}
  auto orig_lhs_type = lhs->GetCompilerType();
  auto orig_rhs_type = rhs->GetCompilerType();
  auto type_or_err = ArithmeticConversion(lhs, rhs, location);
  if (!type_or_err)
    return type_or_err.takeError();
  CompilerType result_type = *type_or_err;

  if (!result_type.IsInteger()) {
    std::string errMsg =
        llvm::formatv("invalid operands to binary expression ('{0}' and '{1}')",
                      orig_lhs_type.GetTypeName(), orig_rhs_type.GetTypeName());
    return llvm::make_error<DILDiagnosticError>(m_expr, errMsg, location);
  }

  return EvaluateScalarOp(kind, lhs, rhs, result_type, location);
}

llvm::Expected<lldb::ValueObjectSP>
Interpreter::EvaluateBinaryShift(BinaryOpKind kind, lldb::ValueObjectSP lhs,
                                 lldb::ValueObjectSP rhs, uint32_t location) {
  // Operations {'>>', '<<'} work for:
  //  {integer,unscoped_enum} <-> {integer,unscoped_enum}
  CompilerType orig_lhs_type = lhs->GetCompilerType();
  CompilerType orig_rhs_type = rhs->GetCompilerType();
  auto lhs_or_err = UnaryConversion(lhs, location);
  if (!lhs_or_err)
    return lhs_or_err.takeError();
  lhs = *lhs_or_err;
  auto rhs_or_err = UnaryConversion(rhs, location);
  if (!rhs_or_err)
    return rhs_or_err.takeError();
  rhs = *rhs_or_err;

  CompilerType lhs_type = lhs->GetCompilerType();
  CompilerType rhs_type = rhs->GetCompilerType();
  if (!lhs_type.IsInteger() || !rhs_type.IsInteger()) {
    std::string errMsg =
        llvm::formatv("invalid operands to binary expression ('{0}' and '{1}')",
                      orig_lhs_type.GetTypeName(), orig_rhs_type.GetTypeName());
    return llvm::make_error<DILDiagnosticError>(m_expr, errMsg, location);
  }

  bool success;
  uint64_t amount = rhs->GetValueAsUnsigned(0, &success);
  if (!success)
    return llvm::make_error<DILDiagnosticError>(
        m_expr, "could not get the shift amount as an integer", location);
  llvm::Expected<uint64_t> lhs_size =
      lhs_type.GetBitSize(m_exe_ctx.GetBestExecutionContextScope());
  if (!lhs_size)
    return lhs_size.takeError();
  if (amount >= *lhs_size)
    return llvm::make_error<DILDiagnosticError>(m_expr, "invalid shift amount",
                                                location);

  return EvaluateScalarOp(kind, lhs, rhs, lhs_type, location);
}

llvm::Expected<lldb::ValueObjectSP>
Interpreter::EvaluateLogical(const BinaryOpNode &node) {
  // Operations {'&&', '||'} work for:
  //  {IsContextuallyConvertibleToBool} <-> {IsContextuallyConvertibleToBool}
  // Note: These operators will not evaluate or check the type of RHS
  // if the result is determined after evaluating LHS.
  auto lhs_or_err = EvaluateAndDereference(node.GetLHS());
  if (!lhs_or_err)
    return lhs_or_err;
  lldb::ValueObjectSP lhs = *lhs_or_err;
  auto lhs_type = lhs->GetCompilerType();
  if (!lhs_type.IsContextuallyConvertibleToBool()) {
    std::string errMsg = llvm::formatv(
        "value of type {0} is not contextually convertible to 'bool'",
        lhs_type.TypeDescription());
    return llvm::make_error<DILDiagnosticError>(m_expr, errMsg,
                                                node.GetLocation());
  }
  llvm::Expected<lldb::TypeSystemSP> type_system = GetTypeSystemFromCU();
  if (!type_system)
    return type_system.takeError();

  // For "&&", exit early if LHS is "false"
  // For "||", exit early if LHS is "true".
  auto lvalue_or_err = lhs->GetValueAsBool();
  if (!lvalue_or_err)
    return lvalue_or_err.takeError();
  bool lhs_val = *lvalue_or_err;
  bool exit_early = node.GetKind() == BinaryOpKind::LAnd ? !lhs_val : lhs_val;
  if (exit_early)
    return ValueObject::CreateValueObjectFromBool(m_exe_ctx, *type_system,
                                                  lhs_val, "result");

  // If the result is to be determined, evaluate the RHS.
  auto rhs_or_err = EvaluateAndDereference(node.GetRHS());
  if (!rhs_or_err)
    return rhs_or_err;
  lldb::ValueObjectSP rhs = *rhs_or_err;
  auto rhs_type = rhs->GetCompilerType();
  if (!rhs_type.IsContextuallyConvertibleToBool()) {
    std::string errMsg = llvm::formatv(
        "value of type {0} is not contextually convertible to 'bool'",
        rhs_type.TypeDescription());
    return llvm::make_error<DILDiagnosticError>(m_expr, errMsg,
                                                node.GetLocation());
  }

  auto rvalue_or_err = rhs->GetValueAsBool();
  if (!rvalue_or_err)
    return rvalue_or_err.takeError();
  return ValueObject::CreateValueObjectFromBool(m_exe_ctx, *type_system,
                                                *rvalue_or_err, "result");
}

llvm::Expected<lldb::ValueObjectSP>
Interpreter::Visit(const BinaryOpNode &node) {
  // Handle logical operators separately. They may or may not evaluate RHS.
  if (node.GetKind() == BinaryOpKind::LAnd ||
      node.GetKind() == BinaryOpKind::LOr)
    return EvaluateLogical(node);

  auto lhs_or_err = EvaluateAndDereference(node.GetLHS());
  if (!lhs_or_err)
    return lhs_or_err;
  lldb::ValueObjectSP lhs = *lhs_or_err;
  auto rhs_or_err = EvaluateAndDereference(node.GetRHS());
  if (!rhs_or_err)
    return rhs_or_err;
  lldb::ValueObjectSP rhs = *rhs_or_err;

  bool lhs_is_literal = node.GetLHS().IsConstLiteral();
  bool rhs_is_literal = node.GetRHS().IsConstLiteral();
  lldb::TypeSystemSP lhs_system =
      lhs->GetCompilerType().GetTypeSystem().GetSharedPointer();
  lldb::TypeSystemSP rhs_system =
      rhs->GetCompilerType().GetTypeSystem().GetSharedPointer();
  if (lhs_system->GetPluginName() != rhs_system->GetPluginName()) {
    // TODO: Attempt to convert values to current CU's type system
    return llvm::make_error<DILDiagnosticError>(
        m_expr, "operands have different type systems", node.GetLocation());
  }

  switch (node.GetKind()) {
  case BinaryOpKind::Assign:
    return EvaluateAssignment(lhs, rhs, node.GetLocation());
  case BinaryOpKind::Add:
    return EvaluateBinaryAddition(lhs, rhs, node.GetLocation());
  case BinaryOpKind::Sub:
    return EvaluateBinarySubtraction(lhs, rhs, node.GetLocation());
  case BinaryOpKind::Mul:
    return EvaluateBinaryMultiplication(lhs, rhs, node.GetLocation());
  case BinaryOpKind::Div:
    return EvaluateBinaryDivision(lhs, rhs, node.GetLocation());
  case BinaryOpKind::Rem:
    return EvaluateBinaryRemainder(lhs, rhs, node.GetLocation());
  case BinaryOpKind::And:
  case BinaryOpKind::Xor:
  case BinaryOpKind::Or:
    return EvaluateBinaryBitwise(node.GetKind(), lhs, rhs, node.GetLocation());
  case BinaryOpKind::Shl:
  case BinaryOpKind::Shr:
    return EvaluateBinaryShift(node.GetKind(), lhs, rhs, node.GetLocation());
  case BinaryOpKind::AddAssign: {
    auto ret_or_err = EvaluateBinaryAddition(lhs, rhs, node.GetLocation());
    if (!ret_or_err)
      return ret_or_err;
    return EvaluateAssignment(lhs, *ret_or_err, node.GetLocation());
  }
  case BinaryOpKind::SubAssign: {
    auto ret_or_err = EvaluateBinarySubtraction(lhs, rhs, node.GetLocation());
    if (!ret_or_err)
      return ret_or_err;
    return EvaluateAssignment(lhs, *ret_or_err, node.GetLocation());
  }
  case BinaryOpKind::MulAssign: {
    auto ret_or_err =
        EvaluateBinaryMultiplication(lhs, rhs, node.GetLocation());
    if (!ret_or_err)
      return ret_or_err;
    return EvaluateAssignment(lhs, *ret_or_err, node.GetLocation());
  }
  case BinaryOpKind::DivAssign: {
    auto ret_or_err = EvaluateBinaryDivision(lhs, rhs, node.GetLocation());
    if (!ret_or_err)
      return ret_or_err;
    return EvaluateAssignment(lhs, *ret_or_err, node.GetLocation());
  }
  case BinaryOpKind::RemAssign: {
    auto ret_or_err = EvaluateBinaryRemainder(lhs, rhs, node.GetLocation());
    if (!ret_or_err)
      return ret_or_err;
    return EvaluateAssignment(lhs, *ret_or_err, node.GetLocation());
  }
  case BinaryOpKind::AndAssign: {
    auto ret_or_err =
        EvaluateBinaryBitwise(BinaryOpKind::And, lhs, rhs, node.GetLocation());
    if (!ret_or_err)
      return ret_or_err;
    return EvaluateAssignment(lhs, *ret_or_err, node.GetLocation());
  }
  case BinaryOpKind::XorAssign: {
    auto ret_or_err =
        EvaluateBinaryBitwise(BinaryOpKind::Xor, lhs, rhs, node.GetLocation());
    if (!ret_or_err)
      return ret_or_err;
    return EvaluateAssignment(lhs, *ret_or_err, node.GetLocation());
  }
  case BinaryOpKind::OrAssign: {
    auto ret_or_err =
        EvaluateBinaryBitwise(BinaryOpKind::Or, lhs, rhs, node.GetLocation());
    if (!ret_or_err)
      return ret_or_err;
    return EvaluateAssignment(lhs, *ret_or_err, node.GetLocation());
  }
  case BinaryOpKind::ShlAssign: {
    auto ret_or_err =
        EvaluateBinaryShift(BinaryOpKind::Shl, lhs, rhs, node.GetLocation());
    if (!ret_or_err)
      return ret_or_err;
    return EvaluateAssignment(lhs, *ret_or_err, node.GetLocation());
  }
  case BinaryOpKind::ShrAssign: {
    auto ret_or_err =
        EvaluateBinaryShift(BinaryOpKind::Shr, lhs, rhs, node.GetLocation());
    if (!ret_or_err)
      return ret_or_err;
    return EvaluateAssignment(lhs, *ret_or_err, node.GetLocation());
  }
  case BinaryOpKind::EQ:
  case BinaryOpKind::NE:
  case BinaryOpKind::LT:
  case BinaryOpKind::LE:
  case BinaryOpKind::GT:
  case BinaryOpKind::GE:
    return EvaluateComparison(node.GetKind(), lhs, rhs, lhs_is_literal,
                              rhs_is_literal, node.GetLocation());
  default:
    break;
  }

  return llvm::make_error<DILDiagnosticError>(
      m_expr, "unimplemented binary operation", node.GetLocation());
}

llvm::Expected<lldb::ValueObjectSP>
Interpreter::Visit(const MemberOfNode &node) {
  if (std::optional<std::string> register_name = GetRegisterPathName(node)) {
    auto frame_sp = m_exe_ctx.GetFrameSP();
    lldb::RegisterContextSP reg_ctx_sp =
        frame_sp ? frame_sp->GetRegisterContext() : nullptr;
    if (reg_ctx_sp) {
      if (const RegisterInfo *reg_info =
              reg_ctx_sp->GetRegisterInfoByName(*register_name))
        return ValueObjectRegister::Create(
            m_exe_ctx.GetBestExecutionContextScope(), reg_ctx_sp, reg_info);
    }
  }

  auto base_or_err = Evaluate(node.GetBase());
  if (!base_or_err)
    return base_or_err;
  bool expr_is_ptr = node.GetIsArrow();
  lldb::ValueObjectSP base = *base_or_err;

  // Perform some basic type & correctness checking.
  if (node.GetIsArrow()) {
    // If we have a non-pointer type with a synthetic value then lets check
    // if we have a synthetic dereference specified.
    if (!base->IsPointerType() && base->HasSyntheticValue()) {
      Status deref_error;
      if (lldb::ValueObjectSP synth_deref_sp =
              base->GetSyntheticValue()->Dereference(deref_error);
          synth_deref_sp && deref_error.Success()) {
        base = std::move(synth_deref_sp);
      }
      if (!base || deref_error.Fail()) {
        std::string errMsg = llvm::formatv(
            "Failed to dereference synthetic value: {0}", deref_error);
        return llvm::make_error<DILDiagnosticError>(
            m_expr, errMsg, node.GetLocation(), node.GetFieldName().size());
      }

      // Some synthetic plug-ins fail to set the error in Dereference
      if (!base) {
        std::string errMsg = "Failed to dereference synthetic value";
        return llvm::make_error<DILDiagnosticError>(
            m_expr, errMsg, node.GetLocation(), node.GetFieldName().size());
      }
      expr_is_ptr = false;
    }
  }

  if (m_check_ptr_vs_member) {
    bool base_is_ptr = base->IsPointerType();

    if (expr_is_ptr != base_is_ptr) {
      if (base_is_ptr) {
        std::string errMsg =
            llvm::formatv("member reference type {0} is a pointer; "
                          "did you mean to use '->'?",
                          base->GetCompilerType().TypeDescription());
        return llvm::make_error<DILDiagnosticError>(
            m_expr, errMsg, node.GetLocation(), node.GetFieldName().size());
      } else {
        std::string errMsg =
            llvm::formatv("member reference type {0} is not a pointer; "
                          "did you mean to use '.'?",
                          base->GetCompilerType().TypeDescription());
        return llvm::make_error<DILDiagnosticError>(
            m_expr, errMsg, node.GetLocation(), node.GetFieldName().size());
      }
    }
  }

  lldb::ValueObjectSP field_obj =
      base->GetChildMemberWithName(node.GetFieldName());
  if (!field_obj) {
    if (m_use_synthetic) {
      field_obj = base->GetSyntheticValue();
      if (field_obj)
        field_obj = field_obj->GetChildMemberWithName(node.GetFieldName());
    }

    if (!m_use_synthetic || !field_obj) {
      std::string errMsg = llvm::formatv(
          "\"{0}\" is not a member of \"({1}) {2}\"", node.GetFieldName(),
          base->GetTypeName().AsCString("<invalid type>"), base->GetName());
      return llvm::make_error<DILDiagnosticError>(
          m_expr, errMsg, node.GetLocation(), node.GetFieldName().size());
    }
  }

  if (field_obj) {
    if (m_use_dynamic != lldb::eNoDynamicValues) {
      lldb::ValueObjectSP dynamic_val_sp =
          field_obj->GetDynamicValue(m_use_dynamic);
      if (dynamic_val_sp)
        field_obj = dynamic_val_sp;
    }
    return field_obj;
  }

  CompilerType base_type = base->GetCompilerType();
  if (node.GetIsArrow() && base->IsPointerType())
    base_type = base_type.GetPointeeType();
  std::string errMsg = llvm::formatv(
      "\"{0}\" is not a member of \"({1}) {2}\"", node.GetFieldName(),
      base->GetTypeName().AsCString("<invalid type>"), base->GetName());
  return llvm::make_error<DILDiagnosticError>(
      m_expr, errMsg, node.GetLocation(), node.GetFieldName().size());
}

llvm::Expected<lldb::ValueObjectSP>
Interpreter::Visit(const ArraySubscriptNode &node) {
  auto idx_or_err = EvaluateAndDereference(node.GetIndex());
  if (!idx_or_err)
    return idx_or_err;
  lldb::ValueObjectSP idx = *idx_or_err;

  if (!idx->GetCompilerType().IsIntegerOrUnscopedEnumerationType()) {
    return llvm::make_error<DILDiagnosticError>(
        m_expr, "array subscript is not an integer", node.GetLocation());
  }

  StreamString var_expr_path_strm;
  uint64_t child_idx = idx->GetValueAsUnsigned(0);
  lldb::ValueObjectSP child_valobj_sp;

  auto base_or_err = Evaluate(node.GetBase());
  if (!base_or_err)
    return base_or_err;
  lldb::ValueObjectSP base = *base_or_err;

  CompilerType base_type = base->GetCompilerType().GetNonReferenceType();
  base->GetExpressionPath(var_expr_path_strm);
  if (base->GetValueType() == lldb::eValueTypeRegister &&
      !base_type.IsPointerType() &&
      child_idx > std::numeric_limits<uint32_t>::max()) {
    std::string err_msg = llvm::formatv(
        "array index {0} is not valid for \"({1}) {2}\"", child_idx,
        base->GetTypeName().AsCString("<invalid type>"),
        var_expr_path_strm.GetData());
    return llvm::make_error<DILDiagnosticError>(m_expr, std::move(err_msg),
                                                node.GetLocation());
  }

  bool is_incomplete_array = false;
  if (base_type.IsPointerType()) {
    bool is_objc_pointer = true;

    if (base->GetCompilerType().GetMinimumLanguage() != lldb::eLanguageTypeObjC)
      is_objc_pointer = false;
    else if (!base->GetCompilerType().IsPointerType())
      is_objc_pointer = false;

    if (!m_use_synthetic && is_objc_pointer) {
      std::string err_msg = llvm::formatv(
          "\"({0}) {1}\" is an Objective-C pointer, and cannot be subscripted",
          base->GetTypeName().AsCString("<invalid type>"),
          var_expr_path_strm.GetData());
      return llvm::make_error<DILDiagnosticError>(m_expr, std::move(err_msg),
                                                  node.GetLocation());
    }
    if (is_objc_pointer) {
      lldb::ValueObjectSP synthetic = base->GetSyntheticValue();
      if (!synthetic || synthetic == base) {
        std::string err_msg =
            llvm::formatv("\"({0}) {1}\" is not an array type",
                          base->GetTypeName().AsCString("<invalid type>"),
                          var_expr_path_strm.GetData());
        return llvm::make_error<DILDiagnosticError>(m_expr, std::move(err_msg),
                                                    node.GetLocation());
      }
      if (static_cast<uint32_t>(child_idx) >=
          synthetic->GetNumChildrenIgnoringErrors()) {
        std::string err_msg = llvm::formatv(
            "array index {0} is not valid for \"({1}) {2}\"", child_idx,
            base->GetTypeName().AsCString("<invalid type>"),
            var_expr_path_strm.GetData());
        return llvm::make_error<DILDiagnosticError>(m_expr, std::move(err_msg),
                                                    node.GetLocation());
      }
      child_valobj_sp = synthetic->GetChildAtIndex(child_idx);
      if (!child_valobj_sp) {
        std::string err_msg = llvm::formatv(
            "array index {0} is not valid for \"({1}) {2}\"", child_idx,
            base->GetTypeName().AsCString("<invalid type>"),
            var_expr_path_strm.GetData());
        return llvm::make_error<DILDiagnosticError>(m_expr, std::move(err_msg),
                                                    node.GetLocation());
      }
      if (m_use_dynamic != lldb::eNoDynamicValues) {
        if (auto dynamic_sp = child_valobj_sp->GetDynamicValue(m_use_dynamic))
          child_valobj_sp = std::move(dynamic_sp);
      }
      return child_valobj_sp;
    }

    child_valobj_sp = base->GetSyntheticArrayMember(child_idx, true);
    if (!child_valobj_sp) {
      std::string err_msg = llvm::formatv(
          "failed to use pointer as array for index {0} for "
          "\"({1}) {2}\"",
          child_idx, base->GetTypeName().AsCString("<invalid type>"),
          var_expr_path_strm.GetData());
      if (base_type.IsPointerToVoid())
        err_msg = "subscript of pointer to incomplete type 'void'";
      return llvm::make_error<DILDiagnosticError>(m_expr, std::move(err_msg),
                                                  node.GetLocation());
    }
  } else if (base_type.IsArrayType(nullptr, nullptr, &is_incomplete_array) ||
             base_type.IsVectorType()) {
    child_valobj_sp = base->GetChildAtIndex(child_idx);
    if (!child_valobj_sp && (is_incomplete_array || m_use_synthetic))
      child_valobj_sp = base->GetSyntheticArrayMember(child_idx, true);
    if (!child_valobj_sp) {
      std::string err_msg = llvm::formatv(
          "array index {0} is not valid for \"({1}) {2}\"", child_idx,
          base->GetTypeName().AsCString("<invalid type>"),
          var_expr_path_strm.GetData());
      return llvm::make_error<DILDiagnosticError>(m_expr, std::move(err_msg),
                                                  node.GetLocation());
    }
  } else if (base_type.IsScalarType()) {
    child_valobj_sp =
        base->GetSyntheticBitFieldChild(child_idx, child_idx, true);
    if (!child_valobj_sp) {
      std::string err_msg = llvm::formatv(
          "bitfield range {0}:{1} is not valid for \"({2}) {3}\"", child_idx,
          child_idx, base->GetTypeName().AsCString("<invalid type>"),
          var_expr_path_strm.GetData());
      return llvm::make_error<DILDiagnosticError>(m_expr, std::move(err_msg),
                                                  node.GetLocation(), 1);
    }
  } else {
    lldb::ValueObjectSP synthetic = base->GetSyntheticValue();
    if (!m_use_synthetic || !synthetic || synthetic == base) {
      std::string err_msg =
          llvm::formatv("\"{0}\" is not an array type",
                        base->GetTypeName().AsCString("<invalid type>"));
      return llvm::make_error<DILDiagnosticError>(m_expr, std::move(err_msg),
                                                  node.GetLocation(), 1);
    }
    if (static_cast<uint32_t>(child_idx) >=
        synthetic->GetNumChildrenIgnoringErrors(child_idx + 1)) {
      std::string err_msg = llvm::formatv(
          "array index {0} is not valid for \"({1}) {2}\"", child_idx,
          base->GetTypeName().AsCString("<invalid type>"),
          var_expr_path_strm.GetData());
      return llvm::make_error<DILDiagnosticError>(m_expr, std::move(err_msg),
                                                  node.GetLocation(), 1);
    }
    child_valobj_sp = synthetic->GetChildAtIndex(child_idx);
    if (!child_valobj_sp) {
      std::string err_msg = llvm::formatv(
          "array index {0} is not valid for \"({1}) {2}\"", child_idx,
          base->GetTypeName().AsCString("<invalid type>"),
          var_expr_path_strm.GetData());
      return llvm::make_error<DILDiagnosticError>(m_expr, std::move(err_msg),
                                                  node.GetLocation(), 1);
    }
  }

  if (child_valobj_sp) {
    if (m_use_dynamic != lldb::eNoDynamicValues) {
      if (auto dynamic_sp = child_valobj_sp->GetDynamicValue(m_use_dynamic))
        child_valobj_sp = std::move(dynamic_sp);
    }
    return child_valobj_sp;
  }

  bool success;
  int64_t signed_child_idx = idx->GetValueAsSigned(0, &success);
  if (!success)
    return llvm::make_error<DILDiagnosticError>(
        m_expr, "could not get the index as an integer",
        node.GetIndex().GetLocation());
  return base->GetSyntheticArrayMember(signed_child_idx, true);
}

llvm::Expected<lldb::ValueObjectSP>
Interpreter::Visit(const BitFieldExtractionNode &node) {
  auto first_idx_or_err = EvaluateAndDereference(node.GetFirstIndex());
  if (!first_idx_or_err)
    return first_idx_or_err;
  lldb::ValueObjectSP first_idx = *first_idx_or_err;
  auto last_idx_or_err = EvaluateAndDereference(node.GetLastIndex());
  if (!last_idx_or_err)
    return last_idx_or_err;
  lldb::ValueObjectSP last_idx = *last_idx_or_err;

  if (!first_idx->GetCompilerType().IsIntegerOrUnscopedEnumerationType() ||
      !last_idx->GetCompilerType().IsIntegerOrUnscopedEnumerationType()) {
    return llvm::make_error<DILDiagnosticError>(
        m_expr, "bit index is not an integer", node.GetLocation());
  }

  bool success_first, success_last;
  int64_t first_index = first_idx->GetValueAsSigned(0, &success_first);
  int64_t last_index = last_idx->GetValueAsSigned(0, &success_last);
  if (!success_first || !success_last)
    return llvm::make_error<DILDiagnosticError>(
        m_expr, "could not get the index as an integer", node.GetLocation());

  // Reject negative indices before the swap below, so the diagnostic reports
  // the range as the user wrote it. A negative index would also wrap to a huge
  // offset in the uint32_t GetSyntheticBitFieldChild call below.
  if (first_index < 0 || last_index < 0) {
    std::string message =
        llvm::formatv("bitfield range {0}:{1} is not valid (negative index)",
                      first_index, last_index);
    return llvm::make_error<DILDiagnosticError>(m_expr, message,
                                                node.GetLocation());
  }

  // if the format given is [high-low], swap range
  if (first_index > last_index)
    std::swap(first_index, last_index);

  // GetMaxU64Bitfield in the data layer only supports up to 64 bits (it asserts
  // bitfield_bit_size <= 64 and otherwise shifts out of bounds), so reject a
  // wider range here.
  if (last_index - first_index >= 64) {
    std::string message =
        llvm::formatv("bitfield range {0}:{1} is not valid (more than 64 bits)",
                      first_index, last_index);
    return llvm::make_error<DILDiagnosticError>(m_expr, message,
                                                node.GetLocation());
  }

  auto base_or_err = EvaluateAndDereference(node.GetBase());
  if (!base_or_err)
    return base_or_err;
  lldb::ValueObjectSP base = *base_or_err;

  // The high index must lie within the base object's storage; a bit index past
  // its bit size shifts out of bounds when the child is later read or formatted
  // (GetMaxU64Bitfield).
  llvm::Expected<uint64_t> base_bit_size = base->GetCompilerType().GetBitSize(
      m_exe_ctx.GetBestExecutionContextScope());
  if (!base_bit_size)
    return base_bit_size.takeError();
  if (static_cast<uint64_t>(last_index) >= *base_bit_size) {
    std::string message = llvm::formatv(
        "bitfield range {0}:{1} is not valid for \"({2}) {3}\"", first_index,
        last_index, base->GetTypeName().AsCString("<invalid type>"),
        base->GetName().GetStringRef());
    return llvm::make_error<DILDiagnosticError>(m_expr, message,
                                                node.GetLocation());
  }

  lldb::ValueObjectSP child_valobj_sp =
      base->GetSyntheticBitFieldChild(first_index, last_index, true);
  if (!child_valobj_sp) {
    std::string message = llvm::formatv(
        "bitfield range {0}:{1} is not valid for \"({2}) {3}\"", first_index,
        last_index, base->GetTypeName().AsCString("<invalid type>"),
        base->GetName().GetStringRef());
    return llvm::make_error<DILDiagnosticError>(m_expr, message,
                                                node.GetLocation());
  }
  return child_valobj_sp;
}

llvm::Expected<CompilerType>
Interpreter::PickIntegerType(lldb::TypeSystemSP type_system,
                             ExecutionContext &exe_ctx,
                             const IntegerLiteralNode &literal) {
  // Binary, Octal, Hexadecimal and literals with a U suffix are allowed to be
  // an unsigned integer.
  bool unsigned_is_allowed = literal.IsUnsigned() || literal.GetRadix() != 10;
  llvm::APInt apint = literal.GetValue();

  llvm::SmallVector<std::pair<lldb::BasicType, lldb::BasicType>, 3> candidates;
  if (literal.GetTypeSuffix() <= IntegerTypeSuffix::None)
    candidates.emplace_back(lldb::eBasicTypeInt,
                            unsigned_is_allowed ? lldb::eBasicTypeUnsignedInt
                                                : lldb::eBasicTypeInvalid);
  if (literal.GetTypeSuffix() <= IntegerTypeSuffix::Long)
    candidates.emplace_back(lldb::eBasicTypeLong,
                            unsigned_is_allowed ? lldb::eBasicTypeUnsignedLong
                                                : lldb::eBasicTypeInvalid);
  candidates.emplace_back(lldb::eBasicTypeLongLong,
                          lldb::eBasicTypeUnsignedLongLong);
  for (auto [signed_, unsigned_] : candidates) {
    CompilerType signed_type = type_system->GetBasicTypeFromAST(signed_);
    if (!signed_type)
      continue;
    llvm::Expected<uint64_t> size =
        signed_type.GetBitSize(exe_ctx.GetBestExecutionContextScope());
    if (!size)
      return size.takeError();
    if (!literal.IsUnsigned() && apint.isIntN(*size - 1))
      return signed_type;
    if (unsigned_ != lldb::eBasicTypeInvalid && apint.isIntN(*size))
      return type_system->GetBasicTypeFromAST(unsigned_);
  }

  return llvm::make_error<DILDiagnosticError>(
      m_expr,
      "integer literal is too large to be represented in any integer type",
      literal.GetLocation());
}

llvm::Expected<lldb::ValueObjectSP>
Interpreter::Visit(const IntegerLiteralNode &node) {
  llvm::Expected<lldb::TypeSystemSP> type_system = GetTypeSystemFromCU();
  if (!type_system)
    return type_system.takeError();

  llvm::Expected<CompilerType> type =
      PickIntegerType(*type_system, m_exe_ctx, node);
  if (!type)
    return type.takeError();

  Scalar scalar = node.GetValue();
  // APInt from StringRef::getAsInteger comes with just enough bitwidth to
  // hold the value. This adjusts APInt bitwidth to match the compiler type.
  llvm::Expected<uint64_t> type_bitsize =
      type->GetBitSize(m_exe_ctx.GetBestExecutionContextScope());
  if (!type_bitsize)
    return type_bitsize.takeError();
  // Literal itself cannot be a negative value, so we do an unsigned extension.
  scalar.TruncOrExtendTo(*type_bitsize, false);
  // If the picked compiler type is signed, make the scalar signed as well.
  if (type->IsSigned())
    scalar.MakeSigned();
  return ValueObject::CreateValueObjectFromScalar(m_exe_ctx, scalar, *type,
                                                  "result");
}

llvm::Expected<lldb::ValueObjectSP>
Interpreter::Visit(const FloatLiteralNode &node) {
  llvm::Expected<lldb::TypeSystemSP> type_system = GetTypeSystemFromCU();
  if (!type_system)
    return type_system.takeError();

  bool isFloat =
      &node.GetValue().getSemantics() == &llvm::APFloat::IEEEsingle();
  lldb::BasicType basic_type =
      isFloat ? lldb::eBasicTypeFloat : lldb::eBasicTypeDouble;
  CompilerType type = GetBasicType(*type_system, basic_type);

  if (!type)
    return llvm::make_error<DILDiagnosticError>(
        m_expr, "unable to create a const literal", node.GetLocation());

  Scalar scalar = node.GetValue();
  return ValueObject::CreateValueObjectFromScalar(m_exe_ctx, scalar, type,
                                                  "result");
}

llvm::Expected<lldb::ValueObjectSP>
Interpreter::Visit(const BooleanLiteralNode &node) {
  bool value = node.GetValue();
  llvm::Expected<lldb::TypeSystemSP> type_system = GetTypeSystemFromCU();
  if (!type_system)
    return type_system.takeError();
  return ValueObject::CreateValueObjectFromBool(m_exe_ctx, *type_system, value,
                                                "result");
}

llvm::Expected<CastKind>
Interpreter::VerifyArithmeticCast(CompilerType source_type,
                                  CompilerType target_type, int location) {
  if (source_type.IsPointerType() || source_type.IsNullPtrType()) {
    // Cast from pointer to float/double is not allowed.
    if (target_type.GetTypeInfo() & lldb::eTypeIsFloat) {
      std::string errMsg = llvm::formatv("Cast from {0} to {1} is not allowed",
                                         source_type.TypeDescription(),
                                         target_type.TypeDescription());
      return llvm::make_error<DILDiagnosticError>(
          m_expr, std::move(errMsg), location,
          source_type.TypeDescription().length());
    }

    // Casting from pointer to bool is always valid.
    if (target_type.IsBoolean())
      return CastKind::eArithmetic;

    // Otherwise check if the result type is at least as big as the pointer
    // size.
    uint64_t type_byte_size = 0;
    uint64_t rhs_type_byte_size = 0;
    if (auto temp =
            target_type.GetByteSize(m_exe_ctx.GetBestExecutionContextScope())) {
      type_byte_size = *temp;
    } else {
      std::string errMsg = llvm::formatv("unable to get byte size for type {0}",
                                         target_type.TypeDescription());
      LLDB_LOG_ERROR(GetLog(LLDBLog::Expressions), temp.takeError(),
                     "GetByteSize failed: {0}");
      return llvm::make_error<DILDiagnosticError>(
          m_expr, std::move(errMsg), location,
          target_type.TypeDescription().length());
    }

    if (auto temp =
            source_type.GetByteSize(m_exe_ctx.GetBestExecutionContextScope())) {
      rhs_type_byte_size = *temp;
    } else {
      std::string errMsg = llvm::formatv("unable to get byte size for type {0}",
                                         source_type.TypeDescription());
      LLDB_LOG_ERROR(GetLog(LLDBLog::Expressions), temp.takeError(),
                     "GetByteSize failed: {0}");
      return llvm::make_error<DILDiagnosticError>(
          m_expr, std::move(errMsg), location,
          source_type.TypeDescription().length());
    }

    if (type_byte_size < rhs_type_byte_size) {
      std::string errMsg = llvm::formatv(
          "cast from pointer to smaller type {0} loses information",
          target_type.TypeDescription());
      return llvm::make_error<DILDiagnosticError>(
          m_expr, std::move(errMsg), location,
          source_type.TypeDescription().length());
    }
  } else if (!source_type.IsScalarType() && !source_type.IsEnumerationType()) {
    // Otherwise accept only arithmetic types and enums.
    std::string errMsg = llvm::formatv("cannot convert {0} to {1}",
                                       source_type.TypeDescription(),
                                       target_type.TypeDescription());

    return llvm::make_error<DILDiagnosticError>(
        m_expr, std::move(errMsg), location,
        source_type.TypeDescription().length());
  }
  return CastKind::eArithmetic;
}

llvm::Expected<CastKind>
Interpreter::VerifyCastType(lldb::ValueObjectSP operand,
                            CompilerType source_type, CompilerType target_type,
                            int location) {

  if (target_type.IsScalarType())
    return VerifyArithmeticCast(source_type, target_type, location);

  if (target_type.IsEnumerationType()) {
    // Cast to enum type.
    if (!source_type.IsScalarType() && !source_type.IsEnumerationType()) {
      std::string errMsg = llvm::formatv("Cast from {0} to {1} is not allowed",
                                         source_type.TypeDescription(),
                                         target_type.TypeDescription());

      return llvm::make_error<DILDiagnosticError>(
          m_expr, std::move(errMsg), location,
          source_type.TypeDescription().length());
    }
    return CastKind::eEnumeration;
  }

  if (target_type.IsPointerType()) {
    if (!source_type.IsInteger() && !source_type.IsEnumerationType() &&
        !source_type.IsArrayType() && !source_type.IsPointerType() &&
        !source_type.IsNullPtrType()) {
      std::string errMsg = llvm::formatv(
          "cannot cast from type {0} to pointer type {1}",
          source_type.TypeDescription(), target_type.TypeDescription());

      return llvm::make_error<DILDiagnosticError>(
          m_expr, std::move(errMsg), location,
          source_type.TypeDescription().length());
    }
    return CastKind::ePointer;
  }

  // Unsupported cast.
  std::string errMsg = llvm::formatv(
      "casting of {0} to {1} is not implemented yet",
      source_type.TypeDescription(), target_type.TypeDescription());
  return llvm::make_error<DILDiagnosticError>(
      m_expr, std::move(errMsg), location,
      source_type.TypeDescription().length());
}

llvm::Expected<lldb::ValueObjectSP> Interpreter::Visit(const CastNode &node) {
  auto operand_or_err = Evaluate(node.GetOperand());

  if (!operand_or_err)
    return operand_or_err;

  lldb::ValueObjectSP operand = *operand_or_err;
  CompilerType op_type = operand->GetCompilerType();
  CompilerType target_type = node.GetType();

  if (op_type.IsReferenceType())
    op_type = op_type.GetNonReferenceType();
  if (target_type.IsScalarType() && op_type.IsArrayType()) {
    operand = ArrayToPointerConversion(*operand, m_exe_ctx,
                                       operand->GetName().GetStringRef());
    op_type = operand->GetCompilerType();
  }
  auto type_or_err =
      VerifyCastType(operand, op_type, target_type, node.GetLocation());
  if (!type_or_err)
    return type_or_err.takeError();

  CastKind cast_kind = *type_or_err;
  if (operand->GetCompilerType().IsReferenceType()) {
    Status error;
    operand = operand->Dereference(error);
    if (error.Fail())
      return llvm::make_error<DILDiagnosticError>(m_expr, error.AsCString(),
                                                  node.GetLocation());
  }

  lldb::ValueObjectSP result;
  switch (cast_kind) {
  case CastKind::eEnumeration: {
    // FIXME: is this correct for float vector types?
    if (op_type.GetTypeInfo() & lldb::eTypeIsFloat || op_type.IsInteger() ||
        op_type.IsEnumerationType())
      result = operand->CastToEnumType(target_type);
    break;
  }
  case CastKind::eArithmetic: {
    if (op_type.IsPointerType() || op_type.IsNullPtrType() ||
        op_type.IsScalarType() || op_type.IsEnumerationType())
      result = operand->CastToBasicType(target_type);
    break;
  }
  case CastKind::ePointer: {
    uint64_t addr = op_type.IsArrayType()
                        ? operand->GetLoadAddress()
                        : (op_type.IsSigned() ? operand->GetValueAsSigned(0)
                                              : operand->GetValueAsUnsigned(0));
    result = ValueObject::CreateValueObjectFromAddress("result", addr,
                                                       m_exe_ctx, target_type,
                                                       /* do_deref */ false);
    break;
  }
  case CastKind::eNone: {
    return lldb::ValueObjectSP();
  }
  } // switch

  if (result) {
    // If cast failed, retrieve the error message from the result.
    if (result->GetError().Fail())
      return llvm::make_error<DILDiagnosticError>(
          m_expr, result->GetError().AsCString(), node.GetLocation());
    return result;
  }

  std::string errMsg =
      llvm::formatv("unable to cast from '{0}' to '{1}'",
                    op_type.TypeDescription(), target_type.TypeDescription());
  return llvm::make_error<DILDiagnosticError>(m_expr, std::move(errMsg),
                                              node.GetLocation());
}

llvm::Expected<lldb::ValueObjectSP>
Interpreter::Visit(const ConditionalNode &node) {
  auto cond_or_err = EvaluateAndDereference(node.GetCondition());
  if (!cond_or_err)
    return cond_or_err;
  lldb::ValueObjectSP condition = *cond_or_err;

  CompilerType cond_type = condition->GetCompilerType();
  if (!cond_type.IsContextuallyConvertibleToBool()) {
    std::string errMsg = llvm::formatv(
        "value of type {0} is not contextually convertible to 'bool'",
        cond_type.TypeDescription());
    return llvm::make_error<DILDiagnosticError>(m_expr, errMsg,
                                                node.GetLocation());
  }
  // Note: DIL evaluates only the operand chosen by the condition,
  // and doesn't check the type or evaluate the other operand.
  auto value_or_err = condition->GetValueAsBool();
  if (value_or_err) {
    if (*value_or_err) {
      auto true_or_err = EvaluateAndDereference(node.GetTrueOperand());
      if (!true_or_err)
        return true_or_err;
      return *true_or_err;
    }
    auto false_or_err = EvaluateAndDereference(node.GetFalseOperand());
    if (!false_or_err)
      return false_or_err;
    return *false_or_err;
  }
  return value_or_err.takeError();
}

llvm::Expected<lldb::ValueObjectSP> Interpreter::Visit(const SizeOfNode &node) {
  CompilerType typearg = node.GetTypeArg();
  Scalar size;
  if (typearg.IsValid()) {
    if (typearg.IsReferenceType())
      typearg = typearg.GetNonReferenceType();
    llvm::Expected<uint64_t> byte_size =
        typearg.GetByteSize(m_exe_ctx.GetTargetSP().get());
    if (!byte_size)
      return byte_size.takeError();
    size = *byte_size;
  } else {
    auto arg_or_err = EvaluateAndDereference(node.GetNodeArg());
    if (!arg_or_err)
      return arg_or_err;
    lldb::ValueObjectSP arg = *arg_or_err;

    if (arg->IsBitfield())
      return llvm::make_error<DILDiagnosticError>(
          m_expr, "invalid application of 'sizeof' to bit-field",
          node.GetLocation());

    llvm::Expected<uint64_t> byte_size = arg->GetByteSize();
    if (!byte_size)
      return byte_size.takeError();
    size = *byte_size;
  }

  llvm::Expected<lldb::TypeSystemSP> type_system = GetTypeSystemFromCU();
  if (!type_system)
    return type_system.takeError();
  CompilerType size_type = type_system.get()->GetSizeType();
  if (!size_type)
    return llvm::make_error<DILDiagnosticError>(
        m_expr, "unable to determine size type", node.GetLocation());

  return ValueObject::CreateValueObjectFromScalar(m_exe_ctx, size, size_type,
                                                  "result");
}

} // namespace lldb_private::dil
