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
16#include "clang/AST/ASTDiagnostic.h"
17#include "clang/AST/Expr.h"
18
19namespace clang {
20class OptionalDiagnostic;
21
22/// Kinds of access we can perform on an object, for diagnostics. Note that
23/// we consider a member function call to be a kind of access, even though
24/// it is not formally an access of the object, because it has (largely) the
25/// same set of semantic restrictions.
26enum AccessKinds {
27 AK_Read,
28 AK_ReadObjectRepresentation,
29 AK_Assign,
30 AK_Increment,
31 AK_Decrement,
32 AK_MemberCall,
33 AK_DynamicCast,
34 AK_TypeId,
35 AK_Construct,
36 AK_Destroy,
37 AK_IsWithinLifetime,
38};
39
40/// The order of this enum is important for diagnostics.
41enum CheckSubobjectKind {
42 CSK_Base,
43 CSK_Derived,
44 CSK_Field,
45 CSK_ArrayToPointer,
46 CSK_ArrayIndex,
47 CSK_Real,
48 CSK_Imag,
49 CSK_VectorElement
50};
51
52namespace interp {
53class Frame;
54class SourceInfo;
55
56/// Interface for the VM to interact with the AST walker's context.
57class State {
58public:
59 virtual ~State();
60
61 virtual bool checkingForUndefinedBehavior() const = 0;
62 virtual bool checkingPotentialConstantExpression() const = 0;
63 virtual bool noteUndefinedBehavior() = 0;
64 virtual bool keepEvaluatingAfterFailure() const = 0;
65 virtual bool keepEvaluatingAfterSideEffect() const = 0;
66 virtual Frame *getCurrentFrame() = 0;
67 virtual const Frame *getBottomFrame() const = 0;
68 virtual bool hasActiveDiagnostic() = 0;
69 virtual void setActiveDiagnostic(bool Flag) = 0;
70 virtual void setFoldFailureDiagnostic(bool Flag) = 0;
71 virtual Expr::EvalStatus &getEvalStatus() const = 0;
72 virtual ASTContext &getASTContext() const = 0;
73 virtual bool hasPriorDiagnostic() = 0;
74 virtual unsigned getCallStackDepth() = 0;
75 virtual bool noteSideEffect() = 0;
76
77public:
78 State() = default;
79 /// Diagnose that the evaluation could not be folded (FF => FoldFailure)
80 OptionalDiagnostic
81 FFDiag(SourceLocation Loc,
82 diag::kind DiagId = diag::note_invalid_subexpr_in_const_expr,
83 unsigned ExtraNotes = 0);
84
85 OptionalDiagnostic
86 FFDiag(const Expr *E,
87 diag::kind DiagId = diag::note_invalid_subexpr_in_const_expr,
88 unsigned ExtraNotes = 0);
89
90 OptionalDiagnostic
91 FFDiag(const SourceInfo &SI,
92 diag::kind DiagId = diag::note_invalid_subexpr_in_const_expr,
93 unsigned ExtraNotes = 0);
94
95 /// Diagnose that the evaluation does not produce a C++11 core constant
96 /// expression.
97 ///
98 /// FIXME: Stop evaluating if we're in EM_ConstantExpression or
99 /// EM_PotentialConstantExpression mode and we produce one of these.
100 OptionalDiagnostic
101 CCEDiag(SourceLocation Loc,
102 diag::kind DiagId = diag::note_invalid_subexpr_in_const_expr,
103 unsigned ExtraNotes = 0);
104
105 OptionalDiagnostic
106 CCEDiag(const Expr *E,
107 diag::kind DiagId = diag::note_invalid_subexpr_in_const_expr,
108 unsigned ExtraNotes = 0);
109
110 OptionalDiagnostic
111 CCEDiag(const SourceInfo &SI,
112 diag::kind DiagId = diag::note_invalid_subexpr_in_const_expr,
113 unsigned ExtraNotes = 0);
114
115 /// Add a note to a prior diagnostic.
116 OptionalDiagnostic Note(SourceLocation Loc, diag::kind DiagId);
117
118 /// Add a stack of notes to a prior diagnostic.
119 void addNotes(ArrayRef<PartialDiagnosticAt> Diags);
120
121 /// Directly reports a diagnostic message.
122 DiagnosticBuilder report(SourceLocation Loc, diag::kind DiagId);
123
124 const LangOptions &getLangOpts() const;
125
126 /// Whether or not we're in a context where the front end requires a
127 /// constant value.
128 bool InConstantContext = false;
129
130private:
131 void addCallStack(unsigned Limit);
132
133 PartialDiagnostic &addDiag(SourceLocation Loc, diag::kind DiagId);
134
135 OptionalDiagnostic diag(SourceLocation Loc, diag::kind DiagId,
136 unsigned ExtraNotes, bool IsCCEDiag);
137};
138
139} // namespace interp
140} // namespace clang
141
142#endif
143