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