Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/clang/lib/AST/Interp/EvaluationResult.h
35292 views
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
/// Check that all subobjects of the given pointer have been initialized.
102
bool checkFullyInitialized(InterpState &S, const Pointer &Ptr) const;
103
/// Check that none of the blocks the given pointer (transitively) points
104
/// to are dynamically allocated.
105
bool checkReturnValue(InterpState &S, const Context &Ctx, const Pointer &Ptr,
106
const SourceInfo &Info);
107
108
QualType getSourceType() const {
109
if (const auto *D =
110
dyn_cast_if_present<ValueDecl>(Source.dyn_cast<const Decl *>()))
111
return D->getType();
112
else if (const auto *E = Source.dyn_cast<const Expr *>())
113
return E->getType();
114
return QualType();
115
}
116
117
/// Dump to stderr.
118
void dump() const;
119
120
friend class EvalEmitter;
121
friend class InterpState;
122
};
123
124
} // namespace interp
125
} // namespace clang
126
127
#endif
128
129