Add an `EvaluationResult` class. This contains the result either as a `Pointer` or as a `APValue`. This way, we can inspect the result of the evaluation and diagnose problems with it (e.g. uninitialized fields in global initializers or pointers pointing to things they shouldn't point to).
114 lines
3.4 KiB
C++
114 lines
3.4 KiB
C++
//===--- 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);
|
|
|
|
/// 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 an expression.
|
|
std::optional<PrimType> classify(QualType T) const;
|
|
|
|
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(); }
|
|
|
|
private:
|
|
/// Runs a function.
|
|
bool Run(State &Parent, const Function *Func, APValue &Result);
|
|
|
|
/// Checks a result from the interpreter.
|
|
bool Check(State &Parent, llvm::Expected<bool> &&R);
|
|
|
|
/// Current compilation context.
|
|
ASTContext &Ctx;
|
|
/// Interpreter stack, shared across invocations.
|
|
InterpStack Stk;
|
|
/// Constexpr program.
|
|
std::unique_ptr<Program> P;
|
|
};
|
|
|
|
} // namespace interp
|
|
} // namespace clang
|
|
|
|
#endif
|