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 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
|
//===--- 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;
class BlockExpr;
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);
bool evaluateCharRange(State &Parent, const Expr *SizeExpr,
const Expr *PtrExpr, APValue &Result);
bool evaluateCharRange(State &Parent, const Expr *SizeExpr,
const Expr *PtrExpr, std::string &Result);
/// Returns the AST context.
ASTContext &getASTContext() const { return Ctx; }
/// Returns the language options.
const LangOptions &getLangOpts() const;
/// 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())
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 *FuncDecl);
const Function *getOrCreateObjCBlock(const BlockExpr *E);
/// 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; }
unsigned collectBaseOffset(const RecordDecl *BaseDecl,
const RecordDecl *DerivedDecl) const;
const Record *getRecord(const RecordDecl *D) const;
unsigned getEvalID() const { return EvalID; }
/// Unevaluated builtins don't get their arguments put on the stack
/// automatically. They instead operate on the AST of their Call
/// Expression.
/// Similar information is available via ASTContext::BuiltinInfo,
/// but that is not correct for our use cases.
static bool isUnevaluatedBuiltin(unsigned ID);
private:
/// Runs a function.
bool Run(State &Parent, const Function *Func);
template <typename ResultT>
bool evaluateStringRepr(State &Parent, const Expr *SizeExpr,
const Expr *PtrExpr, ResultT &Result);
/// 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;
/// Cached widths (in bits) of common types, for a faster classify().
unsigned ShortWidth;
unsigned IntWidth;
unsigned LongWidth;
unsigned LongLongWidth;
};
} // namespace interp
} // namespace clang
#endif
|