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