1 //===--- InterpState.h - Interpreter state for the constexpr VM -*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 // Definition of the interpreter state and entry point.
11 //===----------------------------------------------------------------------===//
13 #ifndef LLVM_CLANG_AST_INTERP_INTERPSTATE_H
14 #define LLVM_CLANG_AST_INTERP_INTERPSTATE_H
17 #include "DynamicAllocator.h"
19 #include "InterpFrame.h"
20 #include "InterpStack.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"
35 /// Interpreter context.
36 class InterpState final
: public State
, public SourceMapper
{
38 InterpState(State
&Parent
, Program
&P
, InterpStack
&Stk
, Context
&Ctx
,
39 SourceMapper
*M
= nullptr);
40 InterpState(State
&Parent
, Program
&P
, InterpStack
&Stk
, Context
&Ctx
,
41 const Function
*Func
);
47 InterpState(const InterpState
&) = delete;
48 InterpState
&operator=(const InterpState
&) = delete;
50 // Stack frame accessors.
51 Frame
*getSplitFrame() { return Parent
.getCurrentFrame(); }
52 Frame
*getCurrentFrame() override
;
53 unsigned getCallStackDepth() override
{
54 return Current
? (Current
->getDepth() + 1) : 1;
56 const Frame
*getBottomFrame() const override
{
57 return Parent
.getBottomFrame();
60 // Access objects from the walker context.
61 Expr::EvalStatus
&getEvalStatus() const override
{
62 return Parent
.getEvalStatus();
64 ASTContext
&getASTContext() const override
{ return Parent
.getASTContext(); }
66 // Forward status checks and updates to the walker.
67 bool checkingForUndefinedBehavior() const override
{
68 return Parent
.checkingForUndefinedBehavior();
70 bool keepEvaluatingAfterFailure() const override
{
71 return Parent
.keepEvaluatingAfterFailure();
73 bool keepEvaluatingAfterSideEffect() const override
{
74 return Parent
.keepEvaluatingAfterSideEffect();
76 bool checkingPotentialConstantExpression() const override
{
77 return Parent
.checkingPotentialConstantExpression();
79 bool noteUndefinedBehavior() override
{
80 return Parent
.noteUndefinedBehavior();
82 bool inConstantContext() const;
83 bool hasActiveDiagnostic() override
{ return Parent
.hasActiveDiagnostic(); }
84 void setActiveDiagnostic(bool Flag
) override
{
85 Parent
.setActiveDiagnostic(Flag
);
87 void setFoldFailureDiagnostic(bool Flag
) override
{
88 Parent
.setFoldFailureDiagnostic(Flag
);
90 bool hasPriorDiagnostic() override
{ return Parent
.hasPriorDiagnostic(); }
91 bool noteSideEffect() override
{ return Parent
.noteSideEffect(); }
93 /// Reports overflow and return true if evaluation should continue.
94 bool reportOverflow(const Expr
*E
, const llvm::APSInt
&Value
);
96 /// Deallocates a pointer.
97 void deallocate(Block
*B
);
99 /// Delegates source mapping to the mapper.
100 SourceInfo
getSource(const Function
*F
, CodePtr PC
) const override
{
102 return M
->getSource(F
, PC
);
104 assert(F
&& "Function cannot be null");
105 return F
->getSource(PC
);
108 Context
&getContext() const { return Ctx
; }
110 void setEvalLocation(SourceLocation SL
) { this->EvalLocation
= SL
; }
112 DynamicAllocator
&getAllocator() { return Alloc
; }
114 /// Diagnose any dynamic allocations that haven't been freed yet.
115 /// Will return \c false if there were any allocations to diagnose,
116 /// \c true otherwise.
117 bool maybeDiagnoseDanglingAllocations();
120 friend class EvaluationResult
;
121 friend class InterpStateCCOverride
;
122 /// AST Walker state.
124 /// Dead block chain.
125 DeadBlock
*DeadBlocks
= nullptr;
126 /// Reference to the offset-source mapping.
128 /// Allocator used for dynamic allocations performed via the program.
129 DynamicAllocator Alloc
;
130 std::optional
<bool> ConstantContextOverride
;
133 /// Reference to the module containing all bytecode.
137 /// Interpreter Context.
139 /// Bottom function frame.
140 InterpFrame BottomFrame
;
141 /// The current frame.
142 InterpFrame
*Current
= nullptr;
143 /// Source location of the evaluating expression
144 SourceLocation EvalLocation
;
145 /// Declaration we're initializing/evaluting, if any.
146 const VarDecl
*EvaluatingDecl
= nullptr;
149 std::pair
<const Expr
*, const LifetimeExtendedTemporaryDecl
*>>
150 SeenGlobalTemporaries
;
153 class InterpStateCCOverride final
{
155 InterpStateCCOverride(InterpState
&Ctx
, bool Value
)
156 : Ctx(Ctx
), OldCC(Ctx
.ConstantContextOverride
) {
157 // We only override this if the new value is true.
160 Ctx
.ConstantContextOverride
= Value
;
162 ~InterpStateCCOverride() {
164 Ctx
.ConstantContextOverride
= OldCC
;
170 std::optional
<bool> OldCC
;
173 } // namespace interp