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