xref: /llvm-project/clang/lib/AST/ByteCode/State.h (revision 83fea8b809b284594e6dd133150bb6d365775e5b)
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 
19 namespace clang {
20 class 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.
26 enum 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.
41 enum 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 
52 namespace interp {
53 class Frame;
54 class SourceInfo;
55 
56 /// Interface for the VM to interact with the AST walker's context.
57 class State {
58 public:
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 
77 public:
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 
130 private:
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