186 lines · c
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-exception6//7//===----------------------------------------------------------------------===//8//9// Defines the base class of the interpreter and evaluator state.10//11//===----------------------------------------------------------------------===//12 13#ifndef LLVM_CLANG_AST_INTERP_STATE_H14#define LLVM_CLANG_AST_INTERP_STATE_H15 16#include "clang/AST/ASTDiagnostic.h"17#include "clang/AST/Expr.h"18 19namespace clang {20class OptionalDiagnostic;21 22/// Kinds of access we can perform on an object, for diagnostics. Note that23/// we consider a member function call to be a kind of access, even though24/// it is not formally an access of the object, because it has (largely) the25/// same set of semantic restrictions.26enum 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 AK_Dereference39};40 41/// The order of this enum is important for diagnostics.42enum CheckSubobjectKind {43 CSK_Base,44 CSK_Derived,45 CSK_Field,46 CSK_ArrayToPointer,47 CSK_ArrayIndex,48 CSK_Real,49 CSK_Imag,50 CSK_VectorElement51};52 53enum class EvaluationMode {54 /// Evaluate as a constant expression. Stop if we find that the expression55 /// is not a constant expression.56 ConstantExpression,57 58 /// Evaluate as a constant expression. Stop if we find that the expression59 /// is not a constant expression. Some expressions can be retried in the60 /// optimizer if we don't constant fold them here, but in an unevaluated61 /// context we try to fold them immediately since the optimizer never62 /// gets a chance to look at it.63 ConstantExpressionUnevaluated,64 65 /// Fold the expression to a constant. Stop if we hit a side-effect that66 /// we can't model.67 ConstantFold,68 69 /// Evaluate in any way we know how. Don't worry about side-effects that70 /// can't be modeled.71 IgnoreSideEffects,72};73 74namespace interp {75class Frame;76class SourceInfo;77 78/// Interface for the VM to interact with the AST walker's context.79class State {80public:81 virtual ~State();82 83 virtual bool noteUndefinedBehavior() = 0;84 virtual bool keepEvaluatingAfterFailure() const = 0;85 virtual bool keepEvaluatingAfterSideEffect() const = 0;86 virtual Frame *getCurrentFrame() = 0;87 virtual const Frame *getBottomFrame() const = 0;88 virtual bool hasActiveDiagnostic() = 0;89 virtual void setActiveDiagnostic(bool Flag) = 0;90 virtual void setFoldFailureDiagnostic(bool Flag) = 0;91 virtual Expr::EvalStatus &getEvalStatus() const = 0;92 virtual ASTContext &getASTContext() const = 0;93 virtual bool hasPriorDiagnostic() = 0;94 virtual unsigned getCallStackDepth() = 0;95 virtual bool noteSideEffect() = 0;96 97 /// Are we checking whether the expression is a potential constant98 /// expression?99 bool checkingPotentialConstantExpression() const {100 return CheckingPotentialConstantExpression;101 }102 /// Are we checking an expression for overflow?103 bool checkingForUndefinedBehavior() const {104 return CheckingForUndefinedBehavior;105 }106 107public:108 State() = default;109 /// Diagnose that the evaluation could not be folded (FF => FoldFailure)110 OptionalDiagnostic111 FFDiag(SourceLocation Loc,112 diag::kind DiagId = diag::note_invalid_subexpr_in_const_expr,113 unsigned ExtraNotes = 0);114 115 OptionalDiagnostic116 FFDiag(const Expr *E,117 diag::kind DiagId = diag::note_invalid_subexpr_in_const_expr,118 unsigned ExtraNotes = 0);119 120 OptionalDiagnostic121 FFDiag(const SourceInfo &SI,122 diag::kind DiagId = diag::note_invalid_subexpr_in_const_expr,123 unsigned ExtraNotes = 0);124 125 /// Diagnose that the evaluation does not produce a C++11 core constant126 /// expression.127 ///128 /// FIXME: Stop evaluating if we're in EM_ConstantExpression or129 /// EM_PotentialConstantExpression mode and we produce one of these.130 OptionalDiagnostic131 CCEDiag(SourceLocation Loc,132 diag::kind DiagId = diag::note_invalid_subexpr_in_const_expr,133 unsigned ExtraNotes = 0);134 135 OptionalDiagnostic136 CCEDiag(const Expr *E,137 diag::kind DiagId = diag::note_invalid_subexpr_in_const_expr,138 unsigned ExtraNotes = 0);139 140 OptionalDiagnostic141 CCEDiag(const SourceInfo &SI,142 diag::kind DiagId = diag::note_invalid_subexpr_in_const_expr,143 unsigned ExtraNotes = 0);144 145 /// Add a note to a prior diagnostic.146 OptionalDiagnostic Note(SourceLocation Loc, diag::kind DiagId);147 148 /// Add a stack of notes to a prior diagnostic.149 void addNotes(ArrayRef<PartialDiagnosticAt> Diags);150 151 /// Directly reports a diagnostic message.152 DiagnosticBuilder report(SourceLocation Loc, diag::kind DiagId);153 154 /// Whether or not we're in a context where the front end requires a155 /// constant value.156 bool InConstantContext = false;157 158 /// Whether we're checking that an expression is a potential constant159 /// expression. If so, do not fail on constructs that could become constant160 /// later on (such as a use of an undefined global).161 bool CheckingPotentialConstantExpression = false;162 163 /// Whether we're checking for an expression that has undefined behavior.164 /// If so, we will produce warnings if we encounter an operation that is165 /// always undefined.166 ///167 /// Note that we still need to evaluate the expression normally when this168 /// is set; this is used when evaluating ICEs in C.169 bool CheckingForUndefinedBehavior = false;170 171 EvaluationMode EvalMode;172 173private:174 void addCallStack(unsigned Limit);175 176 PartialDiagnostic &addDiag(SourceLocation Loc, diag::kind DiagId);177 178 OptionalDiagnostic diag(SourceLocation Loc, diag::kind DiagId,179 unsigned ExtraNotes, bool IsCCEDiag);180};181 182} // namespace interp183} // namespace clang184 185#endif186