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