//===------ EvaluationResult.h - Result class for the 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 // //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_AST_INTERP_EVALUATION_RESULT_H #define LLVM_CLANG_AST_INTERP_EVALUATION_RESULT_H #include "clang/AST/APValue.h" #include "clang/AST/Decl.h" #include "clang/AST/Expr.h" namespace clang { namespace interp { class EvalEmitter; class Context; class Pointer; class SourceInfo; class InterpState; /// Defines the result of an evaluation. /// /// The Kind defined if the evaluation was invalid, valid (but empty, e.g. for /// void expressions) or if we have a valid evaluation result. /// /// We use this class to inspect and diagnose the result, as well as /// convert it to the requested form. class EvaluationResult final { public: enum ResultKind { Empty, // Initial state. Invalid, // Result is invalid. Valid, // Result is valid and empty. }; using DeclTy = llvm::PointerUnion; private: #ifndef NDEBUG const Context *Ctx = nullptr; #endif APValue Value; ResultKind Kind = Empty; DeclTy Source = nullptr; void setSource(DeclTy D) { Source = D; } void takeValue(APValue &&V) { assert(empty()); Value = std::move(V); } void setInvalid() { // We are NOT asserting empty() here, since setting it to invalid // is allowed even if there is already a result. Kind = Invalid; } void setValid() { assert(empty()); Kind = Valid; } public: #ifndef NDEBUG EvaluationResult(const Context *Ctx) : Ctx(Ctx) {} #else EvaluationResult(const Context *Ctx) {} #endif bool empty() const { return Kind == Empty; } bool isInvalid() const { return Kind == Invalid; } /// Returns an APValue for the evaluation result. APValue toAPValue() const { assert(!empty()); assert(!isInvalid()); return Value; } APValue stealAPValue() { return std::move(Value); } /// Check that all subobjects of the given pointer have been initialized. bool checkFullyInitialized(InterpState &S, const Pointer &Ptr) const; /// Check that none of the blocks the given pointer (transitively) points /// to are dynamically allocated. bool checkReturnValue(InterpState &S, const Context &Ctx, const Pointer &Ptr, const SourceInfo &Info); QualType getSourceType() const { if (const auto *D = dyn_cast_if_present(Source.dyn_cast())) return D->getType(); if (const auto *E = Source.dyn_cast()) return E->getType(); return QualType(); } /// Dump to stderr. void dump() const; friend class EvalEmitter; friend class InterpState; }; } // namespace interp } // namespace clang #endif