[clang][bytecode] Remove FunctionPointer class (#186757)

It's been mostly living inside `Pointer` for a long time now, so remove
the leftovers.
This commit is contained in:
Timm Baeder 2026-03-16 11:54:04 +01:00 committed by GitHub
parent 5709638262
commit e4a2d9cd8a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 26 additions and 125 deletions

View File

@ -16,7 +16,6 @@
#include "FixedPoint.h"
#include "Floating.h"
#include "Function.h"
#include "FunctionPointer.h"
#include "Integral.h"
#include "IntegralAP.h"
#include "InterpFrame.h"

View File

@ -1,36 +0,0 @@
//===----------------------- FunctionPointer.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 "FunctionPointer.h"
namespace clang {
namespace interp {
APValue FunctionPointer::toAPValue(const ASTContext &) const {
if (!Func)
return APValue(static_cast<Expr *>(nullptr), CharUnits::Zero(), {},
/*OnePastTheEnd=*/false, /*IsNull=*/true);
if (Func->getDecl())
return APValue(Func->getDecl(), CharUnits::fromQuantity(0), {},
/*OnePastTheEnd=*/false, /*IsNull=*/false);
return APValue(Func->getExpr(), CharUnits::fromQuantity(0), {},
/*OnePastTheEnd=*/false, /*IsNull=*/false);
}
void FunctionPointer::print(llvm::raw_ostream &OS) const {
OS << "FnPtr(";
if (Func)
OS << Func->getName();
else
OS << "nullptr";
OS << ")";
}
} // namespace interp
} // namespace clang

View File

@ -1,55 +0,0 @@
//===--- FunctionPointer.h - Types for the constexpr VM ---------*- 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_FUNCTION_POINTER_H
#define LLVM_CLANG_AST_INTERP_FUNCTION_POINTER_H
#include "Function.h"
#include "Primitives.h"
namespace clang {
class ASTContext;
class APValue;
namespace interp {
class FunctionPointer final {
private:
const Function *Func;
public:
FunctionPointer() = default;
FunctionPointer(const Function *Func) : Func(Func) {}
const Function *getFunction() const { return Func; }
bool isZero() const { return !Func; }
bool isWeak() const {
if (!Func || !Func->getDecl())
return false;
return Func->getDecl()->isWeak();
}
APValue toAPValue(const ASTContext &) const;
void print(llvm::raw_ostream &OS) const;
std::string toDiagnosticString(const ASTContext &Ctx) const {
if (!Func)
return "nullptr";
return toAPValue(Ctx).getAsString(Ctx, Func->getDecl()->getType());
}
uint64_t getIntegerRepresentation() const {
return static_cast<uint64_t>(reinterpret_cast<uintptr_t>(Func));
}
};
} // namespace interp
} // namespace clang
#endif

View File

@ -1903,8 +1903,7 @@ bool CallPtr(InterpState &S, CodePtr OpPC, uint32_t ArgSize,
if (!Ptr.isFunctionPointer())
return Invalid(S, OpPC);
const FunctionPointer &FuncPtr = Ptr.asFunctionPointer();
const Function *F = FuncPtr.getFunction();
const Function *F = Ptr.asFunctionPointer().Func;
assert(F);
// Don't allow calling block pointers.
if (!F->getDecl())

View File

@ -2310,7 +2310,7 @@ std::optional<Pointer> OffsetHelper(InterpState &S, CodePtr OpPC,
if (N > 1)
S.CCEDiag(S.Current->getSource(OpPC), diag::note_constexpr_array_index)
<< N << /*non-array*/ true << 0;
return Pointer(Ptr.asFunctionPointer().getFunction(), N);
return Pointer(Ptr.asFunctionPointer().Func, N);
} else if (!Ptr.isBlockPointer()) {
return std::nullopt;
}

View File

@ -8,7 +8,6 @@
#include "MemberPointer.h"
#include "Context.h"
#include "FunctionPointer.h"
#include "Program.h"
#include "Record.h"
@ -76,11 +75,6 @@ std::optional<Pointer> MemberPointer::toPointer(const Context &Ctx) const {
return Pointer(const_cast<Block *>(Base.block()), Offset, Offset);
}
FunctionPointer MemberPointer::toFunctionPointer(const Context &Ctx) const {
return FunctionPointer(
Ctx.getProgram().getFunction(cast<FunctionDecl>(getDecl())));
}
APValue MemberPointer::toAPValue(const ASTContext &ASTCtx) const {
if (isZero())
return APValue(static_cast<ValueDecl *>(nullptr), /*IsDerivedMember=*/false,

View File

@ -19,7 +19,6 @@ class CXXRecordDecl;
namespace interp {
class Context;
class FunctionPointer;
class MemberPointer final {
private:
@ -100,7 +99,6 @@ public:
ComparisonCategoryResult compare(const MemberPointer &RHS) const;
std::optional<Pointer> toPointer(const Context &Ctx) const;
FunctionPointer toFunctionPointer(const Context &Ctx) const;
bool isBaseCastPossible() const {
if (PtrOffset < 0)

View File

@ -182,11 +182,10 @@ APValue Pointer::toAPValue(const ASTContext &ASTCtx) const {
/*IsOnePastEnd=*/false, /*IsNullPtr=*/false);
if (isFunctionPointer()) {
const FunctionPointer &FP = asFunctionPointer();
if (const FunctionDecl *FD = FP.getFunction()->getDecl())
if (const FunctionDecl *FD = FP.Func->getDecl())
return APValue(FD, CharUnits::fromQuantity(Offset), {},
/*OnePastTheEnd=*/false, /*IsNull=*/false);
return APValue(FP.getFunction()->getExpr(), CharUnits::fromQuantity(Offset),
{},
return APValue(FP.Func->getExpr(), CharUnits::fromQuantity(Offset), {},
/*OnePastTheEnd=*/false, /*IsNull=*/false);
}
@ -352,8 +351,7 @@ void Pointer::print(llvm::raw_ostream &OS) const {
OS << "}";
break;
case Storage::Fn:
OS << "(Fn) { " << asFunctionPointer().getFunction() << " + " << Offset
<< " }";
OS << "(Fn) { " << Fn.Func << " + " << Offset << " }";
break;
case Storage::Typeid:
OS << "(Typeid) { " << (const void *)asTypeidPointer().TypePtr << ", "
@ -376,7 +374,7 @@ size_t Pointer::computeOffsetForComparison(const ASTContext &ASTCtx) const {
// See below.
break;
case Storage::Fn:
return Fn.getIntegerRepresentation() + Offset;
return getIntegerRepresentation();
case Storage::Typeid:
return reinterpret_cast<uintptr_t>(asTypeidPointer().TypePtr) + Offset;
}
@ -438,9 +436,6 @@ std::string Pointer::toDiagnosticString(const ASTContext &Ctx) const {
if (isIntegralPointer())
return (Twine("&(") + Twine(asIntPointer().Value + Offset) + ")").str();
if (isFunctionPointer())
return asFunctionPointer().toDiagnosticString(Ctx);
return toAPValue(Ctx).getAsString(Ctx, getType());
}

View File

@ -14,7 +14,7 @@
#define LLVM_CLANG_AST_INTERP_POINTER_H
#include "Descriptor.h"
#include "FunctionPointer.h"
#include "Function.h"
#include "InitMap.h"
#include "InterpBlock.h"
#include "clang/AST/ComparisonCategories.h"
@ -53,6 +53,10 @@ struct IntPointer {
IntPointer baseCast(const ASTContext &ASTCtx, unsigned BaseOffset) const;
};
struct FunctionPointer {
const Function *Func;
};
struct TypeidPointer {
const Type *TypePtr;
const Type *TypeInfoType;
@ -106,7 +110,7 @@ public:
Pointer(uint64_t Address, const Descriptor *Desc, uint64_t Offset = 0)
: Offset(Offset), StorageKind(Storage::Int), Int{Desc, Address} {}
Pointer(const Function *F, uint64_t Offset = 0)
: Offset(Offset), StorageKind(Storage::Fn), Fn(F) {}
: Offset(Offset), StorageKind(Storage::Fn), Fn{F} {}
Pointer(const Type *TypePtr, const Type *TypeInfoType, uint64_t Offset = 0)
: Offset(Offset), StorageKind(Storage::Typeid) {
Typeid.TypePtr = TypePtr;
@ -127,7 +131,7 @@ public:
P.Offset == Offset;
if (isFunctionPointer())
return P.Fn.getFunction() == Fn.getFunction() && P.Offset == Offset;
return P.Fn.Func == Fn.Func && P.Offset == Offset;
assert(isBlockPointer());
return P.BS.Pointee == BS.Pointee && P.BS.Base == BS.Base &&
@ -146,7 +150,7 @@ public:
if (isIntegralPointer())
return Int.Value + (Offset * elemSize());
if (isFunctionPointer())
return Fn.getIntegerRepresentation() + Offset;
return reinterpret_cast<uint64_t>(Fn.Func) + Offset;
return reinterpret_cast<uint64_t>(BS.Pointee) + Offset;
}
@ -159,7 +163,7 @@ public:
if (isIntegralPointer())
return Pointer(Int.Value, Int.Desc, Idx);
if (isFunctionPointer())
return Pointer(Fn.getFunction(), Idx);
return Pointer(Fn.Func, Idx);
if (BS.Base == RootPtrMark)
return Pointer(BS.Pointee, RootPtrMark, getDeclDesc()->getSize());
@ -264,7 +268,7 @@ public:
case Storage::Block:
return BS.Pointee == nullptr;
case Storage::Fn:
return Fn.isZero();
return !Fn.Func;
case Storage::Typeid:
return false;
}
@ -302,7 +306,7 @@ public:
if (isBlockPointer())
return getDeclDesc()->getSource();
if (isFunctionPointer()) {
const Function *F = Fn.getFunction();
const Function *F = Fn.Func;
return F ? F->getDecl() : DeclTy();
}
assert(isIntegralPointer());
@ -343,7 +347,7 @@ public:
if (isTypeidPointer())
return QualType(Typeid.TypeInfoType, 0);
if (isFunctionPointer())
return Fn.getFunction()->getDecl()->getType();
return Fn.Func->getDecl()->getType();
if (inPrimitiveArray() && Offset != BS.Base) {
// Unfortunately, complex and vector types are not array types in clang,
@ -531,8 +535,12 @@ public:
}
bool isWeak() const {
if (isFunctionPointer())
return Fn.isWeak();
if (isFunctionPointer()) {
if (!Fn.Func || !Fn.Func->getDecl())
return false;
return Fn.Func->getDecl()->isWeak();
}
if (!isBlockPointer())
return false;

View File

@ -24,7 +24,6 @@ namespace interp {
class Pointer;
class Boolean;
class Floating;
class FunctionPointer;
class MemberPointer;
class FixedPoint;
template <bool Signed> class IntegralAP;

View File

@ -76,7 +76,6 @@ add_clang_library(clangAST
ByteCode/Disasm.cpp
ByteCode/EvalEmitter.cpp
ByteCode/Function.cpp
ByteCode/FunctionPointer.cpp
ByteCode/InterpBuiltin.cpp
ByteCode/InterpBuiltinBitCast.cpp
ByteCode/Floating.cpp

View File

@ -151,7 +151,8 @@ TEST(ToAPValue, FunctionPointers) {
const ValueDecl *D = getDecl("nullp");
ASSERT_NE(D, nullptr);
const Pointer &GP = getGlobalPtr("nullp");
const auto &P = GP.deref<FunctionPointer>();
const auto &P = GP.deref<Pointer>();
ASSERT_TRUE(P.isZero());
APValue A = P.toAPValue(ASTCtx);
ASSERT_TRUE(A.isLValue());
ASSERT_TRUE(A.getLValueBase().isNull());