brintos

brintos / llvm-project-archived public Read only

0
0
Text · 2.9 KiB · 8b1b018 Raw
97 lines · cpp
1//===------------------------- MemberPointer.cpp ----------------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "MemberPointer.h"10#include "Context.h"11#include "FunctionPointer.h"12#include "Program.h"13#include "Record.h"14 15namespace clang {16namespace interp {17 18std::optional<Pointer> MemberPointer::toPointer(const Context &Ctx) const {19  if (!Dcl || isa<FunctionDecl>(Dcl))20    return Base;21  assert((isa<FieldDecl, IndirectFieldDecl>(Dcl)));22 23  if (!Base.isBlockPointer())24    return std::nullopt;25 26  unsigned BlockMDSize = Base.block()->getDescriptor()->getMetadataSize();27 28  if (PtrOffset >= 0) {29    // If the resulting base would be too small, return nullopt.30    if (Base.BS.Base < static_cast<unsigned>(PtrOffset) ||31        (Base.BS.Base - PtrOffset < BlockMDSize))32      return std::nullopt;33  }34 35  Pointer CastedBase =36      (PtrOffset < 0 ? Base.atField(-PtrOffset) : Base.atFieldSub(PtrOffset));37 38  const Record *BaseRecord = CastedBase.getRecord();39  if (!BaseRecord)40    return std::nullopt;41 42  unsigned Offset = 0;43  Offset += BlockMDSize;44 45  if (const auto *FD = dyn_cast<FieldDecl>(Dcl)) {46    if (FD->getParent() == BaseRecord->getDecl())47      return CastedBase.atField(BaseRecord->getField(FD)->Offset);48 49    const RecordDecl *FieldParent = FD->getParent();50    const Record *FieldRecord = Ctx.getRecord(FieldParent);51 52    Offset += FieldRecord->getField(FD)->Offset;53    if (Offset > CastedBase.block()->getSize())54      return std::nullopt;55 56    if (const RecordDecl *BaseDecl = Base.getDeclPtr().getRecord()->getDecl();57        BaseDecl != FieldParent)58      Offset += Ctx.collectBaseOffset(FieldParent, BaseDecl);59 60  } else {61    const auto *IFD = cast<IndirectFieldDecl>(Dcl);62 63    for (const NamedDecl *ND : IFD->chain()) {64      const FieldDecl *F = cast<FieldDecl>(ND);65      const RecordDecl *FieldParent = F->getParent();66      const Record *FieldRecord = Ctx.getRecord(FieldParent);67      Offset += FieldRecord->getField(F)->Offset;68    }69  }70 71  assert(BaseRecord);72  if (Offset > CastedBase.block()->getSize())73    return std::nullopt;74 75  assert(Offset <= CastedBase.block()->getSize());76  return Pointer(const_cast<Block *>(Base.block()), Offset, Offset);77}78 79FunctionPointer MemberPointer::toFunctionPointer(const Context &Ctx) const {80  return FunctionPointer(Ctx.getProgram().getFunction(cast<FunctionDecl>(Dcl)));81}82 83APValue MemberPointer::toAPValue(const ASTContext &ASTCtx) const {84  if (isZero())85    return APValue(static_cast<ValueDecl *>(nullptr), /*IsDerivedMember=*/false,86                   /*Path=*/{});87 88  if (hasBase())89    return Base.toAPValue(ASTCtx);90 91  return APValue(getDecl(), /*IsDerivedMember=*/false,92                 /*Path=*/{});93}94 95} // namespace interp96} // namespace clang97