//===-- 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/Symbol/CompileUnit.h"
#include "lldb/Symbol/TypeSystem.h"
#include "lldb/Symbol/VariableList.h"
#include "lldb/Target/RegisterContext.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/FormatAdapters.h"
#include <memory>

namespace lldb_private::dil {

lldb::ValueObjectSP
GetDynamicOrSyntheticValue(lldb::ValueObjectSP value_sp,
                           lldb::DynamicValueType use_dynamic,
                           bool use_synthetic) {
  if (!value_sp)
    return nullptr;

  if (use_dynamic != lldb::eNoDynamicValues) {
    lldb::ValueObjectSP dynamic_sp = value_sp->GetDynamicValue(use_dynamic);
    if (dynamic_sp)
      value_sp = dynamic_sp;
  }

  if (use_synthetic) {
    lldb::ValueObjectSP synthetic_sp = value_sp->GetSyntheticValue();
    if (synthetic_sp)
      value_sp = synthetic_sp;
  }

  return value_sp;
}

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,
                                                    ExecutionContextScope &ctx,
                                                    llvm::StringRef name) {
  uint64_t addr = valobj.GetLoadAddress();
  ExecutionContext exe_ctx;
  ctx.CalculateExecutionContext(exe_ctx);
  return ValueObject::CreateValueObjectFromAddress(
      name, addr, exe_ctx,
      valobj.GetCompilerType().GetArrayElementType(&ctx).GetPointerType(),
      /* do_deref */ false);
}

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(m_exe_ctx_scope);
  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_scope.get());
      if (!int_bit_size)
        return int_bit_size.takeError();
      llvm::Expected<uint64_t> uint_bit_size =
          uint_type.GetBitSize(m_exe_ctx_scope.get());
      if (!uint_bit_size)
        return int_bit_size.takeError();
      if (bitfield_size < *int_bit_size ||
          (in_type.IsSigned() && bitfield_size == *int_bit_size))
        return valobj->CastToBasicType(int_type);
      if (bitfield_size <= *uint_bit_size)
        return valobj->CastToBasicType(uint_type);
      // 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_target, scalar, in_type,
                                                      "result");
    }
  }

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

  if (valobj->GetCompilerType().IsInteger() ||
      valobj->GetCompilerType().IsUnscopedEnumerationType()) {
    llvm::Expected<CompilerType> promoted_type =
        type_system.get()->DoIntegralPromotion(valobj->GetCompilerType(),
                                               m_exe_ctx_scope.get());
    if (!promoted_type)
      return promoted_type.takeError();
    if (!promoted_type->CompareTypes(valobj->GetCompilerType()))
      return valobj->CastToBasicType(*promoted_type);
  }

  return valobj;
}

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, std::shared_ptr<StackFrame> stack_frame,
    lldb::TargetSP target_sp, lldb::DynamicValueType use_dynamic) {
  // Get a global variables list without the locals from the current frame
  SymbolContext symbol_context =
      stack_frame->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 =
          stack_frame->GetValueObjectForFrameVariable(var_sp, use_dynamic);
  }

  if (value_sp)
    return value_sp;

  // Check for match in modules global variables.
  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(stack_frame.get(), var_sp);

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

lldb::ValueObjectSP LookupIdentifier(llvm::StringRef name_ref,
                                     std::shared_ptr<StackFrame> stack_frame,
                                     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.
  if (name_ref.consume_front("$")) {
    lldb::RegisterContextSP reg_ctx(stack_frame->GetRegisterContext());
    if (!reg_ctx)
      return nullptr;

    if (const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(name_ref))
      return ValueObjectRegister::Create(stack_frame.get(), 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(
        stack_frame->GetInScopeVariableList(false));

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

    if (value_sp)
      return value_sp;

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

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

Interpreter::Interpreter(lldb::TargetSP target, llvm::StringRef expr,
                         std::shared_ptr<StackFrame> frame_sp,
                         lldb::DynamicValueType use_dynamic, bool use_synthetic,
                         bool fragile_ivar, bool check_ptr_vs_member)
    : m_target(std::move(target)), m_expr(expr), m_exe_ctx_scope(frame_sp),
      m_use_dynamic(use_dynamic), m_use_synthetic(use_synthetic),
      m_fragile_ivar(fragile_ivar), m_check_ptr_vs_member(check_ptr_vs_member) {
}

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_scope, use_dynamic);

  if (!identifier)
    identifier = LookupGlobalIdentifier(node.GetName(), m_exe_ctx_scope,
                                        m_target, use_dynamic);
  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_target, 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;
  }
  }
  return llvm::make_error<DILDiagnosticError>(m_expr, "invalid unary 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 (!m_fragile_ivar) {
      // Make sure we aren't trying to deref an objective
      // C ivar if this is not allowed
      const uint32_t pointer_type_flags =
          base->GetCompilerType().GetTypeInfo(nullptr);
      if ((pointer_type_flags & lldb::eTypeIsObjC) &&
          (pointer_type_flags & lldb::eTypeIsPointer)) {
        // This was an objective C object pointer and it was requested we
        // skip any fragile ivars so return nothing here
        return lldb::ValueObjectSP();
      }
    }

    // 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());

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

  auto base_or_err = EvaluateAndDereference(node.GetBase());
  if (!base_or_err)
    return base_or_err;
  lldb::ValueObjectSP base = *base_or_err;
  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().AsCString());
    return llvm::make_error<DILDiagnosticError>(m_expr, message,
                                                node.GetLocation());
  }
  return child_valobj_sp;
}

llvm::Expected<CompilerType>
Interpreter::PickIntegerType(lldb::TypeSystemSP type_system,
                             std::shared_ptr<ExecutionContextScope> 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(ctx.get());
    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(m_exe_ctx_scope);
  if (!type_system)
    return type_system.takeError();

  llvm::Expected<CompilerType> type =
      PickIntegerType(*type_system, m_exe_ctx_scope, 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_scope.get());
  if (!type_bitsize)
    return type_bitsize.takeError();
  scalar.TruncOrExtendTo(*type_bitsize, false);
  return ValueObject::CreateValueObjectFromScalar(m_target, scalar, *type,
                                                  "result");
}

llvm::Expected<lldb::ValueObjectSP>
Interpreter::Visit(const FloatLiteralNode &node) {
  llvm::Expected<lldb::TypeSystemSP> type_system =
      GetTypeSystemFromCU(m_exe_ctx_scope);
  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_target, scalar, type,
                                                  "result");
}

llvm::Expected<lldb::ValueObjectSP>
Interpreter::Visit(const BooleanLiteralNode &node) {
  bool value = node.GetValue();
  return ValueObject::CreateValueObjectFromBool(m_target, 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_scope.get())) {
      type_byte_size = *temp;
    } else {
      std::string errMsg = llvm::formatv("unable to get byte size for type {0}",
                                         target_type.TypeDescription());
      return llvm::make_error<DILDiagnosticError>(
          m_expr, std::move(errMsg), location,
          target_type.TypeDescription().length());
    }

    if (auto temp = source_type.GetByteSize(m_exe_ctx_scope.get())) {
      rhs_type_byte_size = *temp;
    } else {
      std::string errMsg = llvm::formatv("unable to get byte size for type {0}",
                                         source_type.TypeDescription());
      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_scope,
                                       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());
  }

  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())
      return operand->CastToEnumType(target_type);
    break;
  }
  case CastKind::eArithmetic: {
    if (op_type.IsPointerType() || op_type.IsNullPtrType() ||
        op_type.IsScalarType() || op_type.IsEnumerationType())
      return 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));
    llvm::StringRef name = "result";
    ExecutionContext exe_ctx(m_target.get(), false);
    return ValueObject::CreateValueObjectFromAddress(name, addr, exe_ctx,
                                                     target_type,
                                                     /* do_deref */ false);
  }
  case CastKind::eNone: {
    return lldb::ValueObjectSP();
  }
  } // switch

  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());
}

} // namespace lldb_private::dil
