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