17a6dacacSDimitry Andric //===------ EvaluationResult.h - Result class for the VM -------*- C++ -*-===// 27a6dacacSDimitry Andric // 37a6dacacSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 47a6dacacSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 57a6dacacSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 67a6dacacSDimitry Andric // 77a6dacacSDimitry Andric //===----------------------------------------------------------------------===// 87a6dacacSDimitry Andric 97a6dacacSDimitry Andric #ifndef LLVM_CLANG_AST_INTERP_EVALUATION_RESULT_H 107a6dacacSDimitry Andric #define LLVM_CLANG_AST_INTERP_EVALUATION_RESULT_H 117a6dacacSDimitry Andric 127a6dacacSDimitry Andric #include "FunctionPointer.h" 137a6dacacSDimitry Andric #include "Pointer.h" 147a6dacacSDimitry Andric #include "clang/AST/APValue.h" 157a6dacacSDimitry Andric #include "clang/AST/Decl.h" 167a6dacacSDimitry Andric #include "clang/AST/Expr.h" 177a6dacacSDimitry Andric #include <optional> 187a6dacacSDimitry Andric #include <variant> 197a6dacacSDimitry Andric 207a6dacacSDimitry Andric namespace clang { 217a6dacacSDimitry Andric namespace interp { 227a6dacacSDimitry Andric class EvalEmitter; 237a6dacacSDimitry Andric class Context; 247a6dacacSDimitry Andric 257a6dacacSDimitry Andric /// Defines the result of an evaluation. 267a6dacacSDimitry Andric /// 277a6dacacSDimitry Andric /// The result might be in different forms--one of the pointer types, 287a6dacacSDimitry Andric /// an APValue, or nothing. 297a6dacacSDimitry Andric /// 307a6dacacSDimitry Andric /// We use this class to inspect and diagnose the result, as well as 317a6dacacSDimitry Andric /// convert it to the requested form. 327a6dacacSDimitry Andric class EvaluationResult final { 337a6dacacSDimitry Andric public: 347a6dacacSDimitry Andric enum ResultKind { 357a6dacacSDimitry Andric Empty, // Initial state. 367a6dacacSDimitry Andric LValue, // Result is an lvalue/pointer. 377a6dacacSDimitry Andric RValue, // Result is an rvalue. 387a6dacacSDimitry Andric Invalid, // Result is invalid. 397a6dacacSDimitry Andric Valid, // Result is valid and empty. 407a6dacacSDimitry Andric }; 417a6dacacSDimitry Andric 427a6dacacSDimitry Andric using DeclTy = llvm::PointerUnion<const Decl *, const Expr *>; 437a6dacacSDimitry Andric 447a6dacacSDimitry Andric private: 457a6dacacSDimitry Andric const Context *Ctx = nullptr; 467a6dacacSDimitry Andric std::variant<std::monostate, Pointer, FunctionPointer, APValue> Value; 477a6dacacSDimitry Andric ResultKind Kind = Empty; 487a6dacacSDimitry Andric DeclTy Source = nullptr; // Currently only needed for dump(). 497a6dacacSDimitry Andric 507a6dacacSDimitry Andric EvaluationResult(ResultKind Kind) : Kind(Kind) { 517a6dacacSDimitry Andric // Leave everything empty. Can be used as an 527a6dacacSDimitry Andric // error marker or for void return values. 537a6dacacSDimitry Andric assert(Kind == Valid || Kind == Invalid); 547a6dacacSDimitry Andric } 557a6dacacSDimitry Andric 567a6dacacSDimitry Andric void setSource(DeclTy D) { Source = D; } 577a6dacacSDimitry Andric 587a6dacacSDimitry Andric void setValue(const APValue &V) { 59*0fca6ea1SDimitry Andric // V could still be an LValue. 607a6dacacSDimitry Andric assert(empty()); 617a6dacacSDimitry Andric Value = std::move(V); 627a6dacacSDimitry Andric Kind = RValue; 637a6dacacSDimitry Andric } 647a6dacacSDimitry Andric void setPointer(const Pointer P) { 657a6dacacSDimitry Andric assert(empty()); 667a6dacacSDimitry Andric Value = P; 677a6dacacSDimitry Andric Kind = LValue; 687a6dacacSDimitry Andric } 697a6dacacSDimitry Andric void setFunctionPointer(const FunctionPointer &P) { 707a6dacacSDimitry Andric assert(empty()); 717a6dacacSDimitry Andric Value = P; 727a6dacacSDimitry Andric Kind = LValue; 737a6dacacSDimitry Andric } 747a6dacacSDimitry Andric void setInvalid() { 75*0fca6ea1SDimitry Andric // We are NOT asserting empty() here, since setting it to invalid 76*0fca6ea1SDimitry Andric // is allowed even if there is already a result. 777a6dacacSDimitry Andric Kind = Invalid; 787a6dacacSDimitry Andric } 797a6dacacSDimitry Andric void setValid() { 807a6dacacSDimitry Andric assert(empty()); 817a6dacacSDimitry Andric Kind = Valid; 827a6dacacSDimitry Andric } 837a6dacacSDimitry Andric 847a6dacacSDimitry Andric public: 857a6dacacSDimitry Andric EvaluationResult(const Context *Ctx) : Ctx(Ctx) {} 867a6dacacSDimitry Andric 877a6dacacSDimitry Andric bool empty() const { return Kind == Empty; } 887a6dacacSDimitry Andric bool isInvalid() const { return Kind == Invalid; } 897a6dacacSDimitry Andric bool isLValue() const { return Kind == LValue; } 907a6dacacSDimitry Andric bool isRValue() const { return Kind == RValue; } 917a6dacacSDimitry Andric 927a6dacacSDimitry Andric /// Returns an APValue for the evaluation result. The returned 937a6dacacSDimitry Andric /// APValue might be an LValue or RValue. 947a6dacacSDimitry Andric APValue toAPValue() const; 957a6dacacSDimitry Andric 967a6dacacSDimitry Andric /// If the result is an LValue, convert that to an RValue 977a6dacacSDimitry Andric /// and return it. This may fail, e.g. if the result is an 987a6dacacSDimitry Andric /// LValue and we can't read from it. 997a6dacacSDimitry Andric std::optional<APValue> toRValue() const; 1007a6dacacSDimitry Andric 101*0fca6ea1SDimitry Andric /// Check that all subobjects of the given pointer have been initialized. 102*0fca6ea1SDimitry Andric bool checkFullyInitialized(InterpState &S, const Pointer &Ptr) const; 103*0fca6ea1SDimitry Andric /// Check that none of the blocks the given pointer (transitively) points 104*0fca6ea1SDimitry Andric /// to are dynamically allocated. 105*0fca6ea1SDimitry Andric bool checkReturnValue(InterpState &S, const Context &Ctx, const Pointer &Ptr, 106*0fca6ea1SDimitry Andric const SourceInfo &Info); 107*0fca6ea1SDimitry Andric 108*0fca6ea1SDimitry Andric QualType getSourceType() const { 109*0fca6ea1SDimitry Andric if (const auto *D = 110*0fca6ea1SDimitry Andric dyn_cast_if_present<ValueDecl>(Source.dyn_cast<const Decl *>())) 111*0fca6ea1SDimitry Andric return D->getType(); 112*0fca6ea1SDimitry Andric else if (const auto *E = Source.dyn_cast<const Expr *>()) 113*0fca6ea1SDimitry Andric return E->getType(); 114*0fca6ea1SDimitry Andric return QualType(); 115*0fca6ea1SDimitry Andric } 1167a6dacacSDimitry Andric 1177a6dacacSDimitry Andric /// Dump to stderr. 1187a6dacacSDimitry Andric void dump() const; 1197a6dacacSDimitry Andric 1207a6dacacSDimitry Andric friend class EvalEmitter; 121*0fca6ea1SDimitry Andric friend class InterpState; 1227a6dacacSDimitry Andric }; 1237a6dacacSDimitry Andric 1247a6dacacSDimitry Andric } // namespace interp 1257a6dacacSDimitry Andric } // namespace clang 1267a6dacacSDimitry Andric 1277a6dacacSDimitry Andric #endif 128