mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-26 22:26:05 +00:00
118 lines
3.2 KiB
C++
118 lines
3.2 KiB
C++
//===------------------------- MemberPointer.h ------------------*- 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
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef LLVM_CLANG_AST_INTERP_MEMBER_POINTER_H
|
|
#define LLVM_CLANG_AST_INTERP_MEMBER_POINTER_H
|
|
|
|
#include "Pointer.h"
|
|
#include <optional>
|
|
|
|
namespace clang {
|
|
class ASTContext;
|
|
namespace interp {
|
|
|
|
class Context;
|
|
class FunctionPointer;
|
|
|
|
class MemberPointer final {
|
|
private:
|
|
Pointer Base;
|
|
const ValueDecl *Dcl = nullptr;
|
|
int32_t PtrOffset = 0;
|
|
|
|
MemberPointer(Pointer Base, const ValueDecl *Dcl, int32_t PtrOffset)
|
|
: Base(Base), Dcl(Dcl), PtrOffset(PtrOffset) {}
|
|
|
|
public:
|
|
MemberPointer() = default;
|
|
MemberPointer(Pointer Base, const ValueDecl *Dcl) : Base(Base), Dcl(Dcl) {}
|
|
MemberPointer(uint32_t Address, const Descriptor *D) {
|
|
// We only reach this for Address == 0, when creating a null member pointer.
|
|
assert(Address == 0);
|
|
}
|
|
|
|
MemberPointer(const ValueDecl *D) : Dcl(D) {
|
|
assert((isa<FieldDecl, IndirectFieldDecl, CXXMethodDecl>(D)));
|
|
}
|
|
|
|
uint64_t getIntegerRepresentation() const {
|
|
assert(
|
|
false &&
|
|
"getIntegerRepresentation() shouldn't be reachable for MemberPointers");
|
|
return 17;
|
|
}
|
|
|
|
std::optional<Pointer> toPointer(const Context &Ctx) const;
|
|
|
|
FunctionPointer toFunctionPointer(const Context &Ctx) const;
|
|
|
|
Pointer getBase() const {
|
|
if (PtrOffset < 0)
|
|
return Base.atField(-PtrOffset);
|
|
return Base.atFieldSub(PtrOffset);
|
|
}
|
|
bool isMemberFunctionPointer() const {
|
|
return isa_and_nonnull<CXXMethodDecl>(Dcl);
|
|
}
|
|
const CXXMethodDecl *getMemberFunction() const {
|
|
return dyn_cast_if_present<CXXMethodDecl>(Dcl);
|
|
}
|
|
const FieldDecl *getField() const {
|
|
return dyn_cast_if_present<FieldDecl>(Dcl);
|
|
}
|
|
|
|
bool hasDecl() const { return Dcl; }
|
|
const ValueDecl *getDecl() const { return Dcl; }
|
|
|
|
MemberPointer atInstanceBase(unsigned Offset) const {
|
|
if (Base.isZero())
|
|
return MemberPointer(Base, Dcl, Offset);
|
|
return MemberPointer(this->Base, Dcl, Offset + PtrOffset);
|
|
}
|
|
|
|
MemberPointer takeInstance(Pointer Instance) const {
|
|
assert(this->Base.isZero());
|
|
return MemberPointer(Instance, this->Dcl, this->PtrOffset);
|
|
}
|
|
|
|
APValue toAPValue(const ASTContext &) const;
|
|
|
|
bool isZero() const { return Base.isZero() && !Dcl; }
|
|
bool hasBase() const { return !Base.isZero(); }
|
|
bool isWeak() const {
|
|
if (const auto *MF = getMemberFunction())
|
|
return MF->isWeak();
|
|
return false;
|
|
}
|
|
|
|
void print(llvm::raw_ostream &OS) const {
|
|
OS << "MemberPtr(" << Base << " " << (const void *)Dcl << " + " << PtrOffset
|
|
<< ")";
|
|
}
|
|
|
|
std::string toDiagnosticString(const ASTContext &Ctx) const {
|
|
return toAPValue(Ctx).getAsString(Ctx, Dcl->getType());
|
|
}
|
|
|
|
ComparisonCategoryResult compare(const MemberPointer &RHS) const {
|
|
if (this->Dcl == RHS.Dcl)
|
|
return ComparisonCategoryResult::Equal;
|
|
return ComparisonCategoryResult::Unordered;
|
|
}
|
|
};
|
|
|
|
inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, MemberPointer FP) {
|
|
FP.print(OS);
|
|
return OS;
|
|
}
|
|
|
|
} // namespace interp
|
|
} // namespace clang
|
|
|
|
#endif
|