//===-- 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/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>

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() {
  llvm::Expected<SymbolContext> symbol_context =
      GetSymbolContexFromFrame(m_exe_ctx);
  if (!symbol_context)
    return symbol_context.takeError();

  lldb::LanguageType language = symbol_context->comp_unit->GetLanguage();
  return symbol_context->module_sp->GetTypeSystemForLanguage(language);
}

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)
      return language.takeError();
    identifier =
        LookupPersistentIdentifier(node.GetName(), m_exe_ctx, language.get());
  }

  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) {
  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);
  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)) {
    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
