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