1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
|
//===--- Context.h - Context 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
//
//===----------------------------------------------------------------------===//
//
// Defines the constexpr execution context.
//
// The execution context manages cached bytecode and the global context.
// It invokes the compiler and interpreter, propagating errors.
//
//===----------------------------------------------------------------------===//
#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;
};
/// Holds all information required to evaluate constexpr code in a module.
class Context final {
public:
/// Initialises the constexpr VM.
Context(ASTContext &Ctx);
/// Cleans up the constexpr VM.
~Context();
/// Checks if a function is a potential constant expression.
bool isPotentialConstantExpr(State &Parent, const FunctionDecl *FnDecl);
/// Evaluates a toplevel expression as an rvalue.
bool evaluateAsRValue(State &Parent, const Expr *E, APValue &Result);
/// Like evaluateAsRvalue(), but does no implicit lvalue-to-rvalue conversion.
bool evaluate(State &Parent, const Expr *E, APValue &Result,
ConstantExprKind Kind);
/// Evaluates a toplevel initializer.
bool evaluateAsInitializer(State &Parent, const VarDecl *VD, APValue &Result);
/// Returns the AST context.
ASTContext &getASTContext() const { return Ctx; }
/// Returns the language options.
const LangOptions &getLangOpts() const;
/// Returns the interpreter stack.
InterpStack &getStack() { return Stk; }
/// Returns CHAR_BIT.
unsigned getCharBit() const;
/// Return the floating-point semantics for T.
const llvm::fltSemantics &getFloatSemantics(QualType T) const;
/// Return the size of T in bits.
uint32_t getBitWidth(QualType T) const { return Ctx.getIntWidth(T); }
/// Classifies a type.
std::optional<PrimType> classify(QualType T) const;
/// Classifies an expression.
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);
/// Returns whether we should create a global variable for the
/// given ValueDecl.
static bool shouldBeGloballyIndexed(const ValueDecl *VD) {
if (const auto *V = dyn_cast<VarDecl>(VD))
return V->hasGlobalStorage() || V->isConstexpr();
return false;
}
/// Returns the program. This is only needed for unittests.
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:
/// Runs a function.
bool Run(State &Parent, const Function *Func);
/// Current compilation context.
ASTContext &Ctx;
/// Interpreter stack, shared across invocations.
InterpStack Stk;
/// Constexpr program.
std::unique_ptr<Program> P;
/// ID identifying an evaluation.
unsigned EvalID = 0;
};
} // namespace interp
} // namespace clang
#endif
|