1*7a6dacacSDimitry Andric //===------ EvaluationResult.h - Result class for the VM -------*- C++ -*-===// 2*7a6dacacSDimitry Andric // 3*7a6dacacSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*7a6dacacSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*7a6dacacSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*7a6dacacSDimitry Andric // 7*7a6dacacSDimitry Andric //===----------------------------------------------------------------------===// 8*7a6dacacSDimitry Andric 9*7a6dacacSDimitry Andric #ifndef LLVM_CLANG_AST_INTERP_EVALUATION_RESULT_H 10*7a6dacacSDimitry Andric #define LLVM_CLANG_AST_INTERP_EVALUATION_RESULT_H 11*7a6dacacSDimitry Andric 12*7a6dacacSDimitry Andric #include "FunctionPointer.h" 13*7a6dacacSDimitry Andric #include "Pointer.h" 14*7a6dacacSDimitry Andric #include "clang/AST/APValue.h" 15*7a6dacacSDimitry Andric #include "clang/AST/Decl.h" 16*7a6dacacSDimitry Andric #include "clang/AST/Expr.h" 17*7a6dacacSDimitry Andric #include <optional> 18*7a6dacacSDimitry Andric #include <variant> 19*7a6dacacSDimitry Andric 20*7a6dacacSDimitry Andric namespace clang { 21*7a6dacacSDimitry Andric namespace interp { 22*7a6dacacSDimitry Andric class EvalEmitter; 23*7a6dacacSDimitry Andric class Context; 24*7a6dacacSDimitry Andric 25*7a6dacacSDimitry Andric /// Defines the result of an evaluation. 26*7a6dacacSDimitry Andric /// 27*7a6dacacSDimitry Andric /// The result might be in different forms--one of the pointer types, 28*7a6dacacSDimitry Andric /// an APValue, or nothing. 29*7a6dacacSDimitry Andric /// 30*7a6dacacSDimitry Andric /// We use this class to inspect and diagnose the result, as well as 31*7a6dacacSDimitry Andric /// convert it to the requested form. 32*7a6dacacSDimitry Andric class EvaluationResult final { 33*7a6dacacSDimitry Andric public: 34*7a6dacacSDimitry Andric enum ResultKind { 35*7a6dacacSDimitry Andric Empty, // Initial state. 36*7a6dacacSDimitry Andric LValue, // Result is an lvalue/pointer. 37*7a6dacacSDimitry Andric RValue, // Result is an rvalue. 38*7a6dacacSDimitry Andric Invalid, // Result is invalid. 39*7a6dacacSDimitry Andric Valid, // Result is valid and empty. 40*7a6dacacSDimitry Andric }; 41*7a6dacacSDimitry Andric 42*7a6dacacSDimitry Andric using DeclTy = llvm::PointerUnion<const Decl *, const Expr *>; 43*7a6dacacSDimitry Andric 44*7a6dacacSDimitry Andric private: 45*7a6dacacSDimitry Andric const Context *Ctx = nullptr; 46*7a6dacacSDimitry Andric std::variant<std::monostate, Pointer, FunctionPointer, APValue> Value; 47*7a6dacacSDimitry Andric ResultKind Kind = Empty; 48*7a6dacacSDimitry Andric DeclTy Source = nullptr; // Currently only needed for dump(). 49*7a6dacacSDimitry Andric 50*7a6dacacSDimitry Andric EvaluationResult(ResultKind Kind) : Kind(Kind) { 51*7a6dacacSDimitry Andric // Leave everything empty. Can be used as an 52*7a6dacacSDimitry Andric // error marker or for void return values. 53*7a6dacacSDimitry Andric assert(Kind == Valid || Kind == Invalid); 54*7a6dacacSDimitry Andric } 55*7a6dacacSDimitry Andric 56*7a6dacacSDimitry Andric void setSource(DeclTy D) { Source = D; } 57*7a6dacacSDimitry Andric 58*7a6dacacSDimitry Andric void setValue(const APValue &V) { 59*7a6dacacSDimitry Andric assert(empty()); 60*7a6dacacSDimitry Andric assert(!V.isLValue()); 61*7a6dacacSDimitry Andric Value = std::move(V); 62*7a6dacacSDimitry Andric Kind = RValue; 63*7a6dacacSDimitry Andric } 64*7a6dacacSDimitry Andric void setPointer(const Pointer P) { 65*7a6dacacSDimitry Andric assert(empty()); 66*7a6dacacSDimitry Andric Value = P; 67*7a6dacacSDimitry Andric Kind = LValue; 68*7a6dacacSDimitry Andric } 69*7a6dacacSDimitry Andric void setFunctionPointer(const FunctionPointer &P) { 70*7a6dacacSDimitry Andric assert(empty()); 71*7a6dacacSDimitry Andric Value = P; 72*7a6dacacSDimitry Andric Kind = LValue; 73*7a6dacacSDimitry Andric } 74*7a6dacacSDimitry Andric void setInvalid() { 75*7a6dacacSDimitry Andric assert(empty()); 76*7a6dacacSDimitry Andric Kind = Invalid; 77*7a6dacacSDimitry Andric } 78*7a6dacacSDimitry Andric void setValid() { 79*7a6dacacSDimitry Andric assert(empty()); 80*7a6dacacSDimitry Andric Kind = Valid; 81*7a6dacacSDimitry Andric } 82*7a6dacacSDimitry Andric 83*7a6dacacSDimitry Andric public: 84*7a6dacacSDimitry Andric EvaluationResult(const Context *Ctx) : Ctx(Ctx) {} 85*7a6dacacSDimitry Andric 86*7a6dacacSDimitry Andric bool empty() const { return Kind == Empty; } 87*7a6dacacSDimitry Andric bool isInvalid() const { return Kind == Invalid; } 88*7a6dacacSDimitry Andric bool isLValue() const { return Kind == LValue; } 89*7a6dacacSDimitry Andric bool isRValue() const { return Kind == RValue; } 90*7a6dacacSDimitry Andric 91*7a6dacacSDimitry Andric /// Returns an APValue for the evaluation result. The returned 92*7a6dacacSDimitry Andric /// APValue might be an LValue or RValue. 93*7a6dacacSDimitry Andric APValue toAPValue() const; 94*7a6dacacSDimitry Andric 95*7a6dacacSDimitry Andric /// If the result is an LValue, convert that to an RValue 96*7a6dacacSDimitry Andric /// and return it. This may fail, e.g. if the result is an 97*7a6dacacSDimitry Andric /// LValue and we can't read from it. 98*7a6dacacSDimitry Andric std::optional<APValue> toRValue() const; 99*7a6dacacSDimitry Andric 100*7a6dacacSDimitry Andric bool checkFullyInitialized(InterpState &S) const; 101*7a6dacacSDimitry Andric 102*7a6dacacSDimitry Andric /// Dump to stderr. 103*7a6dacacSDimitry Andric void dump() const; 104*7a6dacacSDimitry Andric 105*7a6dacacSDimitry Andric friend class EvalEmitter; 106*7a6dacacSDimitry Andric }; 107*7a6dacacSDimitry Andric 108*7a6dacacSDimitry Andric } // namespace interp 109*7a6dacacSDimitry Andric } // namespace clang 110*7a6dacacSDimitry Andric 111*7a6dacacSDimitry Andric #endif 112