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