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 | |
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 | |
56 | void setSource(DeclTy D) { Source = D; } |
57 | |
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 | } |
64 | void setPointer(const Pointer P) { |
65 | assert(empty()); |
66 | Value = P; |
67 | Kind = LValue; |
68 | } |
69 | void setFunctionPointer(const FunctionPointer &P) { |
70 | assert(empty()); |
71 | Value = P; |
72 | Kind = LValue; |
73 | } |
74 | void setInvalid() { |
75 | // We are NOT asserting empty() here, since setting it to invalid |
76 | // is allowed even if there is already a result. |
77 | Kind = Invalid; |
78 | } |
79 | void setValid() { |
80 | assert(empty()); |
81 | Kind = Valid; |
82 | } |
83 | |
84 | public: |
85 | EvaluationResult(const Context *Ctx) : Ctx(Ctx) {} |
86 | |
87 | bool empty() const { return Kind == Empty; } |
88 | bool isInvalid() const { return Kind == Invalid; } |
89 | bool isLValue() const { return Kind == LValue; } |
90 | bool isRValue() const { return Kind == RValue; } |
91 | |
92 | /// Returns an APValue for the evaluation result. The returned |
93 | /// APValue might be an LValue or RValue. |
94 | APValue toAPValue() const; |
95 | |
96 | /// If the result is an LValue, convert that to an RValue |
97 | /// and return it. This may fail, e.g. if the result is an |
98 | /// LValue and we can't read from it. |
99 | std::optional<APValue> toRValue() const; |
100 | |
101 | bool checkFullyInitialized(InterpState &S, const Pointer &Ptr) const; |
102 | |
103 | /// Dump to stderr. |
104 | void dump() const; |
105 | |
106 | friend class EvalEmitter; |
107 | }; |
108 | |
109 | } // namespace interp |
110 | } // namespace clang |
111 | |
112 | #endif |
113 | |