//===------------------------- MemberPointer.cpp ----------------*- C++ -*-===//
//
// 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 "MemberPointer.h"
#include "Context.h"
#include "Program.h"
#include "Record.h"

namespace clang {
namespace interp {

std::optional<Pointer> MemberPointer::toPointer(const Context &Ctx) const {
  if (!getDecl() || isa<FunctionDecl>(getDecl()))
    return Base;
  assert((isa<FieldDecl, IndirectFieldDecl>(getDecl())));

  if (!Base.isBlockPointer())
    return std::nullopt;

  unsigned BlockMDSize = Base.block()->getMetadataSize();

  if (PtrOffset >= 0) {
    // If the resulting base would be too small, return nullopt.
    if (Base.BS.Base < static_cast<unsigned>(PtrOffset) ||
        (Base.BS.Base - PtrOffset < BlockMDSize))
      return std::nullopt;
  }

  Pointer CastedBase =
      (PtrOffset < 0 ? Base.atField(-PtrOffset) : Base.atFieldSub(PtrOffset));

  const Record *BaseRecord = CastedBase.getRecord();
  if (!BaseRecord)
    return std::nullopt;

  unsigned Offset = 0;
  Offset += BlockMDSize;

  if (const auto *FD = dyn_cast<FieldDecl>(getDecl())) {
    if (FD->getParent() == BaseRecord->getDecl())
      return CastedBase.atField(BaseRecord->getField(FD)->Offset);

    const RecordDecl *FieldParent = FD->getParent();
    const Record *FieldRecord = Ctx.getRecord(FieldParent);

    Offset += FieldRecord->getField(FD)->Offset;
    if (Offset > CastedBase.block()->getSize())
      return std::nullopt;

    if (const RecordDecl *BaseDecl = Base.getDeclPtr().getRecord()->getDecl();
        BaseDecl != FieldParent)
      Offset += Ctx.collectBaseOffset(FieldParent, BaseDecl);

  } else {
    const auto *IFD = cast<IndirectFieldDecl>(getDecl());

    for (const NamedDecl *ND : IFD->chain()) {
      const FieldDecl *F = cast<FieldDecl>(ND);
      const RecordDecl *FieldParent = F->getParent();
      const Record *FieldRecord = Ctx.getRecord(FieldParent);
      Offset += FieldRecord->getField(F)->Offset;
    }
  }

  assert(BaseRecord);
  if (Offset > CastedBase.block()->getSize())
    return std::nullopt;

  assert(Offset <= CastedBase.block()->getSize());
  return Pointer(const_cast<Block *>(Base.block()), Offset, Offset);
}

APValue MemberPointer::toAPValue(const ASTContext &ASTCtx) const {
  if (isZero())
    return APValue(static_cast<ValueDecl *>(nullptr), /*IsDerivedMember=*/false,
                   /*Path=*/{});

  if (hasBase())
    return Base.toAPValue(ASTCtx);

  return APValue(getDecl(), /*IsDerivedMember=*/isDerivedMember(),
                 /*Path=*/ArrayRef(Path, PathLength));
}

ComparisonCategoryResult
MemberPointer::compare(const MemberPointer &RHS) const {
  assert(!isZero());
  assert(!RHS.isZero());

  const auto getCmpDecl = [](const MemberPointer &P) -> const Decl * {
    const Decl *D = P.getDecl()->getMostRecentDecl();
    if (const auto *FD = dyn_cast<FieldDecl>(D))
      D = FD->getFirstDecl();
    return D;
  };

  const Decl *LHSCmpDecl = getCmpDecl(*this);
  const Decl *RHSCmpDecl = getCmpDecl(RHS);

  if (LHSCmpDecl == RHSCmpDecl) {
    if (this->PathLength != RHS.PathLength)
      return ComparisonCategoryResult::Unordered;

    if (PathLength != 0 &&
        std::memcmp(Path, RHS.Path, PathLength * sizeof(CXXRecordDecl *)) != 0)
      return ComparisonCategoryResult::Unordered;

    return ComparisonCategoryResult::Equal;
  }
  return ComparisonCategoryResult::Unordered;
}

} // namespace interp
} // namespace clang
