1 //===--- InterpState.h - Interpreter state for the constexpr VM -*- 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 // Definition of the interpreter state and entry point. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #ifndef LLVM_CLANG_AST_INTERP_INTERPSTATE_H 14 #define LLVM_CLANG_AST_INTERP_INTERPSTATE_H 15 16 #include "Context.h" 17 #include "DynamicAllocator.h" 18 #include "Function.h" 19 #include "InterpFrame.h" 20 #include "InterpStack.h" 21 #include "State.h" 22 #include "clang/AST/APValue.h" 23 #include "clang/AST/ASTDiagnostic.h" 24 #include "clang/AST/Expr.h" 25 #include "clang/AST/OptionalDiagnostic.h" 26 27 namespace clang { 28 namespace interp { 29 class Context; 30 class Function; 31 class InterpStack; 32 class InterpFrame; 33 class SourceMapper; 34 35 /// Interpreter context. 36 class InterpState final : public State, public SourceMapper { 37 public: 38 InterpState(State &Parent, Program &P, InterpStack &Stk, Context &Ctx, 39 SourceMapper *M = nullptr); 40 41 ~InterpState(); 42 43 void cleanup(); 44 45 InterpState(const InterpState &) = delete; 46 InterpState &operator=(const InterpState &) = delete; 47 48 // Stack frame accessors. 49 Frame *getSplitFrame() { return Parent.getCurrentFrame(); } 50 Frame *getCurrentFrame() override; 51 unsigned getCallStackDepth() override { 52 return Current ? (Current->getDepth() + 1) : 1; 53 } 54 const Frame *getBottomFrame() const override { 55 return Parent.getBottomFrame(); 56 } 57 58 // Access objects from the walker context. 59 Expr::EvalStatus &getEvalStatus() const override { 60 return Parent.getEvalStatus(); 61 } 62 ASTContext &getASTContext() const override { return Parent.getASTContext(); } 63 64 // Forward status checks and updates to the walker. 65 bool checkingForUndefinedBehavior() const override { 66 return Parent.checkingForUndefinedBehavior(); 67 } 68 bool keepEvaluatingAfterFailure() const override { 69 return Parent.keepEvaluatingAfterFailure(); 70 } 71 bool keepEvaluatingAfterSideEffect() const override { 72 return Parent.keepEvaluatingAfterSideEffect(); 73 } 74 bool checkingPotentialConstantExpression() const override { 75 return Parent.checkingPotentialConstantExpression(); 76 } 77 bool noteUndefinedBehavior() override { 78 return Parent.noteUndefinedBehavior(); 79 } 80 bool inConstantContext() const; 81 bool hasActiveDiagnostic() override { return Parent.hasActiveDiagnostic(); } 82 void setActiveDiagnostic(bool Flag) override { 83 Parent.setActiveDiagnostic(Flag); 84 } 85 void setFoldFailureDiagnostic(bool Flag) override { 86 Parent.setFoldFailureDiagnostic(Flag); 87 } 88 bool hasPriorDiagnostic() override { return Parent.hasPriorDiagnostic(); } 89 bool noteSideEffect() override { return Parent.noteSideEffect(); } 90 91 /// Reports overflow and return true if evaluation should continue. 92 bool reportOverflow(const Expr *E, const llvm::APSInt &Value); 93 94 /// Deallocates a pointer. 95 void deallocate(Block *B); 96 97 /// Delegates source mapping to the mapper. 98 SourceInfo getSource(const Function *F, CodePtr PC) const override { 99 if (M) 100 return M->getSource(F, PC); 101 102 assert(F && "Function cannot be null"); 103 return F->getSource(PC); 104 } 105 106 Context &getContext() const { return Ctx; } 107 108 void setEvalLocation(SourceLocation SL) { this->EvalLocation = SL; } 109 110 DynamicAllocator &getAllocator() { return Alloc; } 111 112 /// Diagnose any dynamic allocations that haven't been freed yet. 113 /// Will return \c false if there were any allocations to diagnose, 114 /// \c true otherwise. 115 bool maybeDiagnoseDanglingAllocations(); 116 117 private: 118 friend class EvaluationResult; 119 friend class InterpStateCCOverride; 120 /// AST Walker state. 121 State &Parent; 122 /// Dead block chain. 123 DeadBlock *DeadBlocks = nullptr; 124 /// Reference to the offset-source mapping. 125 SourceMapper *M; 126 /// Allocator used for dynamic allocations performed via the program. 127 DynamicAllocator Alloc; 128 std::optional<bool> ConstantContextOverride; 129 130 public: 131 /// Reference to the module containing all bytecode. 132 Program &P; 133 /// Temporary stack. 134 InterpStack &Stk; 135 /// Interpreter Context. 136 Context &Ctx; 137 /// The current frame. 138 InterpFrame *Current = nullptr; 139 /// Source location of the evaluating expression 140 SourceLocation EvalLocation; 141 /// Declaration we're initializing/evaluting, if any. 142 const VarDecl *EvaluatingDecl = nullptr; 143 144 llvm::SmallVector< 145 std::pair<const Expr *, const LifetimeExtendedTemporaryDecl *>> 146 SeenGlobalTemporaries; 147 }; 148 149 class InterpStateCCOverride final { 150 public: 151 InterpStateCCOverride(InterpState &Ctx, bool Value) 152 : Ctx(Ctx), OldCC(Ctx.ConstantContextOverride) { 153 // We only override this if the new value is true. 154 Enabled = Value; 155 if (Enabled) 156 Ctx.ConstantContextOverride = Value; 157 } 158 ~InterpStateCCOverride() { 159 if (Enabled) 160 Ctx.ConstantContextOverride = OldCC; 161 } 162 163 private: 164 bool Enabled; 165 InterpState &Ctx; 166 std::optional<bool> OldCC; 167 }; 168 169 } // namespace interp 170 } // namespace clang 171 172 #endif 173