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 };
38 
39 /// The order of this enum is important for diagnostics.
40 enum CheckSubobjectKind {
41   CSK_Base,
42   CSK_Derived,
43   CSK_Field,
44   CSK_ArrayToPointer,
45   CSK_ArrayIndex,
46   CSK_Real,
47   CSK_Imag
48 };
49 
50 namespace interp {
51 class Frame;
52 class SourceInfo;
53 
54 /// Interface for the VM to interact with the AST walker's context.
55 class State {
56 public:
57   virtual ~State();
58 
59   virtual bool checkingForUndefinedBehavior() const = 0;
60   virtual bool checkingPotentialConstantExpression() const = 0;
61   virtual bool noteUndefinedBehavior() = 0;
62   virtual bool keepEvaluatingAfterFailure() const = 0;
63   virtual Frame *getCurrentFrame() = 0;
64   virtual const Frame *getBottomFrame() const = 0;
65   virtual bool hasActiveDiagnostic() = 0;
66   virtual void setActiveDiagnostic(bool Flag) = 0;
67   virtual void setFoldFailureDiagnostic(bool Flag) = 0;
68   virtual Expr::EvalStatus &getEvalStatus() const = 0;
69   virtual ASTContext &getCtx() const = 0;
70   virtual bool hasPriorDiagnostic() = 0;
71   virtual unsigned getCallStackDepth() = 0;
72 
73 public:
74   State() = default;
75   /// Diagnose that the evaluation could not be folded (FF => FoldFailure)
76   OptionalDiagnostic
77   FFDiag(SourceLocation Loc,
78          diag::kind DiagId = diag::note_invalid_subexpr_in_const_expr,
79          unsigned ExtraNotes = 0);
80 
81   OptionalDiagnostic
82   FFDiag(const Expr *E,
83          diag::kind DiagId = diag::note_invalid_subexpr_in_const_expr,
84          unsigned ExtraNotes = 0);
85 
86   OptionalDiagnostic
87   FFDiag(const SourceInfo &SI,
88          diag::kind DiagId = diag::note_invalid_subexpr_in_const_expr,
89          unsigned ExtraNotes = 0);
90 
91   /// Diagnose that the evaluation does not produce a C++11 core constant
92   /// expression.
93   ///
94   /// FIXME: Stop evaluating if we're in EM_ConstantExpression or
95   /// EM_PotentialConstantExpression mode and we produce one of these.
96   OptionalDiagnostic
97   CCEDiag(SourceLocation Loc,
98           diag::kind DiagId = diag::note_invalid_subexpr_in_const_expr,
99           unsigned ExtraNotes = 0);
100 
101   OptionalDiagnostic
102   CCEDiag(const Expr *E,
103           diag::kind DiagId = diag::note_invalid_subexpr_in_const_expr,
104           unsigned ExtraNotes = 0);
105 
106   OptionalDiagnostic
107   CCEDiag(const SourceInfo &SI,
108           diag::kind DiagId = diag::note_invalid_subexpr_in_const_expr,
109           unsigned ExtraNotes = 0);
110 
111   /// Add a note to a prior diagnostic.
112   OptionalDiagnostic Note(SourceLocation Loc, diag::kind DiagId);
113 
114   /// Add a stack of notes to a prior diagnostic.
115   void addNotes(ArrayRef<PartialDiagnosticAt> Diags);
116 
117   /// Directly reports a diagnostic message.
118   DiagnosticBuilder report(SourceLocation Loc, diag::kind DiagId);
119 
120   const LangOptions &getLangOpts() const;
121 
122   /// Whether or not we're in a context where the front end requires a
123   /// constant value.
124   bool InConstantContext = false;
125 
126 private:
127   void addCallStack(unsigned Limit);
128 
129   PartialDiagnostic &addDiag(SourceLocation Loc, diag::kind DiagId);
130 
131   OptionalDiagnostic diag(SourceLocation Loc, diag::kind DiagId,
132                           unsigned ExtraNotes, bool IsCCEDiag);
133 };
134 
135 } // namespace interp
136 } // namespace clang
137 
138 #endif
139