clang 24.0.0git
State.h
Go to the documentation of this file.
1//===--- State.h - State chain for the VM and AST Walker --------*- 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// Defines the base class of the interpreter and evaluator state.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef LLVM_CLANG_AST_INTERP_STATE_H
14#define LLVM_CLANG_AST_INTERP_STATE_H
15
18#include "clang/AST/Expr.h"
20
21namespace clang {
22class SemaProxy;
23
24/// Kinds of access we can perform on an object, for diagnostics. Note that
25/// we consider a member function call to be a kind of access, even though
26/// it is not formally an access of the object, because it has (largely) the
27/// same set of semantic restrictions.
42
43/// The order of this enum is important for diagnostics.
54
55enum class EvaluationMode {
56 /// Evaluate as a constant expression. Stop if we find that the expression
57 /// is not a constant expression.
59
60 /// Evaluate as a constant expression. Stop if we find that the expression
61 /// is not a constant expression. Some expressions can be retried in the
62 /// optimizer if we don't constant fold them here, but in an unevaluated
63 /// context we try to fold them immediately since the optimizer never
64 /// gets a chance to look at it.
66
67 /// Fold the expression to a constant. Stop if we hit a side-effect that
68 /// we can't model.
70
71 /// Evaluate in any way we know how. Don't worry about side-effects that
72 /// can't be modeled.
74};
75
76namespace interp {
77class Frame;
78class SourceInfo;
79
80/// Interface for the VM to interact with the AST walker's context.
81class State {
82public:
85 virtual ~State();
86
87 virtual const Frame *getCurrentFrame() = 0;
88 virtual unsigned getCallStackDepth() = 0;
89 virtual bool stepsLeft() const = 0;
90
92 ASTContext &getASTContext() const { return Ctx; }
93 SemaProxy *getSemaProxy() const { return SProxy; }
94 const LangOptions &getLangOpts() const { return Ctx.getLangOpts(); }
95
96 /// If \c DiagId should be relaxed as per the current evaluation settings,
97 /// emit it as a warning instead of an error. Returns \c true if a relaxed
98 /// diagnostic was emitted, \c false otherwise.
100
101 /// Note that we have had a side-effect, and determine whether we should
102 /// keep evaluating.
103 bool noteSideEffect() const {
104 EvalStatus.HasSideEffects = true;
106 }
107
108 /// Should we continue evaluation as much as possible after encountering a
109 /// construct which can't be reduced to a value?
110 bool keepEvaluatingAfterFailure() const;
111 /// Should we continue evaluation after encountering a side-effect that we
112 /// couldn't model?
114
115 /// Note that we hit something that was technically undefined behavior, but
116 /// that we can evaluate past it (such as signed overflow or floating-point
117 /// division by zero.)
119 EvalStatus.HasUndefinedBehavior = true;
120 return keepEvaluatingAfterUndefinedBehavior();
121 }
122
123 /// Are we checking whether the expression is a potential constant
124 /// expression?
128 /// Are we checking an expression for overflow?
132
133 /// Diagnose that the evaluation could not be folded (FF => FoldFailure)
136 diag::kind DiagId = diag::note_invalid_subexpr_in_const_expr,
137 unsigned ExtraNotes = 0);
138
140 FFDiag(const Expr *E,
141 diag::kind DiagId = diag::note_invalid_subexpr_in_const_expr,
142 unsigned ExtraNotes = 0);
143
146 diag::kind DiagId = diag::note_invalid_subexpr_in_const_expr,
147 unsigned ExtraNotes = 0);
148
149 /// Diagnose that the evaluation does not produce a C++11 core constant
150 /// expression.
151 ///
152 /// FIXME: Stop evaluating if we're in EM_ConstantExpression or
153 /// EM_PotentialConstantExpression mode and we produce one of these.
156 diag::kind DiagId = diag::note_invalid_subexpr_in_const_expr,
157 unsigned ExtraNotes = 0);
158
160 CCEDiag(const Expr *E,
161 diag::kind DiagId = diag::note_invalid_subexpr_in_const_expr,
162 unsigned ExtraNotes = 0);
163
166 diag::kind DiagId = diag::note_invalid_subexpr_in_const_expr,
167 unsigned ExtraNotes = 0);
168
169 /// Add a note to a prior diagnostic.
172
173 /// Directly reports a diagnostic message.
175
176 /// Whether or not we're in a context where the front end requires a
177 /// constant value.
178 bool InConstantContext = false;
179
180 /// Whether we're checking that an expression is a potential constant
181 /// expression. If so, do not fail on constructs that could become constant
182 /// later on (such as a use of an undefined global).
184
185 /// Whether we're checking for an expression that has undefined behavior.
186 /// If so, we will produce warnings if we encounter an operation that is
187 /// always undefined.
188 ///
189 /// Note that we still need to evaluate the expression normally when this
190 /// is set; this is used when evaluating ICEs in C.
192
197
198private:
199 /// HasActiveDiagnostic - Was the previous diagnostic stored? If so, further
200 /// notes attached to it will also be stored, otherwise they will not be.
201 bool HasActiveDiagnostic = false;
202
203 /// Have we emitted a diagnostic explaining why we couldn't constant
204 /// fold (not just why it's not strictly a constant expression)?
205 bool HasFoldFailureDiagnostic = false;
206
207 void addCallStack(unsigned Limit);
208
209 PartialDiagnostic &addDiag(SourceLocation Loc, diag::kind DiagId);
210
211 void addExtendedDiag(SourceLocation Loc, diag::kind DiagId);
212
214 unsigned ExtraNotes, bool IsFFDiag);
215
216 /// Should we continue evaluation after encountering undefined behavior?
217 bool keepEvaluatingAfterUndefinedBehavior() const;
218
219 // If we have a prior diagnostic, it will be noting that the expression
220 // isn't a constant expression. This diagnostic is more important,
221 // unless we require this evaluation to produce a constant expression.
222 //
223 // FIXME: We might want to show both diagnostics to the user in
224 // EvaluationMode::ConstantFold mode.
225 bool hasPriorDiagnostic();
226
227 void setFoldFailureDiagnostic(bool Flag) { HasFoldFailureDiagnostic = Flag; };
228 void setActiveDiagnostic(bool Flag) { HasActiveDiagnostic = Flag; };
229 bool hasActiveDiagnostic() const { return HasActiveDiagnostic; }
230};
231
232} // namespace interp
233} // namespace clang
234
235#endif
Defines the clang::ASTContext interface.
Implements a partial diagnostic which may not be emitted.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:245
A little helper class used to produce diagnostics.
This represents one expression.
Definition Expr.h:114
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
A partial diagnostic which we might know in advance that we are not going to emit.
Classes implementing SemaProxy present a restricted view of the (possibly mutating) actions and queri...
Definition SemaProxy.h:29
Encodes a location in the source.
Base class for stack frames, shared between VM and walker.
Definition Frame.h:28
Describes the statement/declaration an opcode was generated from.
Definition Source.h:77
bool checkingForUndefinedBehavior() const
Are we checking an expression for overflow?
Definition State.h:129
virtual const Frame * getCurrentFrame()=0
EvaluationMode EvalMode
Definition State.h:193
virtual bool stepsLeft() const =0
Expr::EvalStatus & getEvalStatus() const
Definition State.h:91
DiagnosticBuilder report(SourceLocation Loc, diag::kind DiagId)
Directly reports a diagnostic message.
Definition State.cpp:98
bool emitRelaxedDiag(SourceLocation Loc, diag::kind DiagId)
If DiagId should be relaxed as per the current evaluation settings, emit it as a warning instead of a...
Definition State.cpp:20
OptionalDiagnostic FFDiag(SourceLocation Loc, diag::kind DiagId=diag::note_invalid_subexpr_in_const_expr, unsigned ExtraNotes=0)
Diagnose that the evaluation could not be folded (FF => FoldFailure)
Definition State.cpp:37
SemaProxy * getSemaProxy() const
Definition State.h:93
bool CheckingPotentialConstantExpression
Whether we're checking that an expression is a potential constant expression.
Definition State.h:183
OptionalDiagnostic Note(SourceInfo Loc, diag::kind DiagId)
virtual unsigned getCallStackDepth()=0
bool CheckingForUndefinedBehavior
Whether we're checking for an expression that has undefined behavior.
Definition State.h:191
bool noteSideEffect() const
Note that we have had a side-effect, and determine whether we should keep evaluating.
Definition State.h:103
Expr::EvalStatus & EvalStatus
Definition State.h:196
ASTContext & getASTContext() const
Definition State.h:92
SemaProxy * SProxy
Definition State.h:195
bool noteUndefinedBehavior() const
Note that we hit something that was technically undefined behavior, but that we can evaluate past it ...
Definition State.h:118
State(ASTContext &ASTCtx, SemaProxy *SProxy, Expr::EvalStatus &EvalStatus)
Definition State.h:83
OptionalDiagnostic CCEDiag(SourceLocation Loc, diag::kind DiagId=diag::note_invalid_subexpr_in_const_expr, unsigned ExtraNotes=0)
Diagnose that the evaluation does not produce a C++11 core constant expression.
Definition State.cpp:60
const LangOptions & getLangOpts() const
Definition State.h:94
bool checkingPotentialConstantExpression() const
Are we checking whether the expression is a potential constant expression?
Definition State.h:125
bool keepEvaluatingAfterSideEffect() const
Should we continue evaluation after encountering a side-effect that we couldn't model?
Definition State.cpp:225
bool keepEvaluatingAfterFailure() const
Should we continue evaluation as much as possible after encountering a construct which can't be reduc...
Definition State.cpp:209
bool InConstantContext
Whether or not we're in a context where the front end requires a constant value.
Definition State.h:178
ASTContext & Ctx
Definition State.h:194
virtual ~State()
Definition State.cpp:18
unsigned kind
All of the diagnostics that can be emitted by the frontend.
Top level wrappers for InstallAPI frontend operations.
CheckSubobjectKind
The order of this enum is important for diagnostics.
Definition State.h:44
@ CSK_ArrayToPointer
Definition State.h:48
@ CSK_Derived
Definition State.h:46
@ CSK_Base
Definition State.h:45
@ CSK_Real
Definition State.h:50
@ CSK_ArrayIndex
Definition State.h:49
@ CSK_Imag
Definition State.h:51
@ CSK_VectorElement
Definition State.h:52
@ CSK_Field
Definition State.h:47
AccessKinds
Kinds of access we can perform on an object, for diagnostics.
Definition State.h:28
@ AK_TypeId
Definition State.h:36
@ AK_Construct
Definition State.h:37
@ AK_Increment
Definition State.h:32
@ AK_DynamicCast
Definition State.h:35
@ AK_Read
Definition State.h:29
@ AK_Assign
Definition State.h:31
@ AK_IsWithinLifetime
Definition State.h:39
@ AK_MemberCall
Definition State.h:34
@ AK_ReadObjectRepresentation
Definition State.h:30
@ AK_Dereference
Definition State.h:40
@ AK_Destroy
Definition State.h:38
@ AK_Decrement
Definition State.h:33
EvaluationMode
Definition State.h:55
@ ConstantFold
Fold the expression to a constant.
Definition State.h:69
@ ConstantExpressionUnevaluated
Evaluate as a constant expression.
Definition State.h:65
@ ConstantExpression
Evaluate as a constant expression.
Definition State.h:58
@ IgnoreSideEffects
Evaluate in any way we know how.
Definition State.h:73
EvalStatus is a struct with detailed info about an evaluation in progress.
Definition Expr.h:623