#ifndef LLVM_CLANG_AST_INTERP_CONTEXT_H
#define LLVM_CLANG_AST_INTERP_CONTEXT_H
#include "InterpStack.h"
namespace clang {
class ASTContext;
class LangOptions;
class FunctionDecl;
class VarDecl;
class APValue;
namespace interp {
class Function;
class Program;
class State;
enum PrimType : unsigned;
struct ParamOffset {
unsigned Offset;
bool IsPtr;
};
class Context final {
public:
Context(ASTContext &Ctx);
~Context();
bool isPotentialConstantExpr(State &Parent, const FunctionDecl *FnDecl);
bool evaluateAsRValue(State &Parent, const Expr *E, APValue &Result);
bool evaluate(State &Parent, const Expr *E, APValue &Result);
bool evaluateAsInitializer(State &Parent, const VarDecl *VD, APValue &Result);
ASTContext &getASTContext() const { return Ctx; }
const LangOptions &getLangOpts() const;
InterpStack &getStack() { return Stk; }
unsigned getCharBit() const;
const llvm::fltSemantics &getFloatSemantics(QualType T) const;
uint32_t getBitWidth(QualType T) const { return Ctx.getIntWidth(T); }
std::optional<PrimType> classify(QualType T) const;
std::optional<PrimType> classify(const Expr *E) const {
assert(E);
if (E->isGLValue()) {
if (E->getType()->isFunctionType())
return PT_FnPtr;
return PT_Ptr;
}
return classify(E->getType());
}
const CXXMethodDecl *
getOverridingFunction(const CXXRecordDecl *DynamicDecl,
const CXXRecordDecl *StaticDecl,
const CXXMethodDecl *InitialFunction) const;
const Function *getOrCreateFunction(const FunctionDecl *FD);
static bool shouldBeGloballyIndexed(const ValueDecl *VD) {
if (const auto *V = dyn_cast<VarDecl>(VD))
return V->hasGlobalStorage() || V->isConstexpr();
return false;
}
Program &getProgram() const { return *P.get(); }
unsigned collectBaseOffset(const RecordDecl *BaseDecl,
const RecordDecl *DerivedDecl) const;
const Record *getRecord(const RecordDecl *D) const;
unsigned getEvalID() const { return EvalID; }
private:
bool Run(State &Parent, const Function *Func, APValue &Result);
ASTContext &Ctx;
InterpStack Stk;
std::unique_ptr<Program> P;
unsigned EvalID = 0;
};
}
}
#endif