xref: /freebsd/contrib/llvm-project/clang/lib/AST/ByteCode/EvaluationResult.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
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