xref: /llvm-project/clang/lib/AST/ByteCode/Compiler.h (revision ceaf6e912a846b88f19df682c6bdbe9516be04e9)
1 //===--- Compiler.h - Code generator for expressions -----*- 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 // Defines the constexpr bytecode compiler.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef LLVM_CLANG_AST_INTERP_BYTECODEEXPRGEN_H
14 #define LLVM_CLANG_AST_INTERP_BYTECODEEXPRGEN_H
15 
16 #include "ByteCodeEmitter.h"
17 #include "EvalEmitter.h"
18 #include "Pointer.h"
19 #include "PrimType.h"
20 #include "Record.h"
21 #include "clang/AST/Decl.h"
22 #include "clang/AST/Expr.h"
23 #include "clang/AST/StmtVisitor.h"
24 #include "clang/Basic/TargetInfo.h"
25 
26 namespace clang {
27 class QualType;
28 
29 namespace interp {
30 
31 template <class Emitter> class LocalScope;
32 template <class Emitter> class DestructorScope;
33 template <class Emitter> class VariableScope;
34 template <class Emitter> class DeclScope;
35 template <class Emitter> class InitLinkScope;
36 template <class Emitter> class InitStackScope;
37 template <class Emitter> class OptionScope;
38 template <class Emitter> class ArrayIndexScope;
39 template <class Emitter> class SourceLocScope;
40 template <class Emitter> class LoopScope;
41 template <class Emitter> class LabelScope;
42 template <class Emitter> class SwitchScope;
43 template <class Emitter> class StmtExprScope;
44 
45 template <class Emitter> class Compiler;
46 struct InitLink {
47 public:
48   enum {
49     K_This = 0,
50     K_Field = 1,
51     K_Temp = 2,
52     K_Decl = 3,
53     K_Elem = 5,
54   };
55 
56   static InitLink This() { return InitLink{K_This}; }
57   static InitLink Field(unsigned Offset) {
58     InitLink IL{K_Field};
59     IL.Offset = Offset;
60     return IL;
61   }
62   static InitLink Temp(unsigned Offset) {
63     InitLink IL{K_Temp};
64     IL.Offset = Offset;
65     return IL;
66   }
67   static InitLink Decl(const ValueDecl *D) {
68     InitLink IL{K_Decl};
69     IL.D = D;
70     return IL;
71   }
72   static InitLink Elem(unsigned Index) {
73     InitLink IL{K_Elem};
74     IL.Offset = Index;
75     return IL;
76   }
77 
78   InitLink(uint8_t Kind) : Kind(Kind) {}
79   template <class Emitter>
80   bool emit(Compiler<Emitter> *Ctx, const Expr *E) const;
81 
82   uint32_t Kind;
83   union {
84     unsigned Offset;
85     const ValueDecl *D;
86   };
87 };
88 
89 /// State encapsulating if a the variable creation has been successful,
90 /// unsuccessful, or no variable has been created at all.
91 struct VarCreationState {
92   std::optional<bool> S = std::nullopt;
93   VarCreationState() = default;
94   VarCreationState(bool b) : S(b) {}
95   static VarCreationState NotCreated() { return VarCreationState(); }
96 
97   operator bool() const { return S && *S; }
98   bool notCreated() const { return !S; }
99 };
100 
101 /// Compilation context for expressions.
102 template <class Emitter>
103 class Compiler : public ConstStmtVisitor<Compiler<Emitter>, bool>,
104                  public Emitter {
105 protected:
106   // Aliases for types defined in the emitter.
107   using LabelTy = typename Emitter::LabelTy;
108   using AddrTy = typename Emitter::AddrTy;
109   using OptLabelTy = std::optional<LabelTy>;
110   using CaseMap = llvm::DenseMap<const SwitchCase *, LabelTy>;
111 
112   /// Current compilation context.
113   Context &Ctx;
114   /// Program to link to.
115   Program &P;
116 
117 public:
118   /// Initializes the compiler and the backend emitter.
119   template <typename... Tys>
120   Compiler(Context &Ctx, Program &P, Tys &&...Args)
121       : Emitter(Ctx, P, Args...), Ctx(Ctx), P(P) {}
122 
123   // Expressions.
124   bool VisitCastExpr(const CastExpr *E);
125   bool VisitIntegerLiteral(const IntegerLiteral *E);
126   bool VisitFloatingLiteral(const FloatingLiteral *E);
127   bool VisitImaginaryLiteral(const ImaginaryLiteral *E);
128   bool VisitFixedPointLiteral(const FixedPointLiteral *E);
129   bool VisitParenExpr(const ParenExpr *E);
130   bool VisitBinaryOperator(const BinaryOperator *E);
131   bool VisitLogicalBinOp(const BinaryOperator *E);
132   bool VisitPointerArithBinOp(const BinaryOperator *E);
133   bool VisitComplexBinOp(const BinaryOperator *E);
134   bool VisitVectorBinOp(const BinaryOperator *E);
135   bool VisitFixedPointBinOp(const BinaryOperator *E);
136   bool VisitFixedPointUnaryOperator(const UnaryOperator *E);
137   bool VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *E);
138   bool VisitCallExpr(const CallExpr *E);
139   bool VisitBuiltinCallExpr(const CallExpr *E, unsigned BuiltinID);
140   bool VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *E);
141   bool VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *E);
142   bool VisitCXXNullPtrLiteralExpr(const CXXNullPtrLiteralExpr *E);
143   bool VisitGNUNullExpr(const GNUNullExpr *E);
144   bool VisitCXXThisExpr(const CXXThisExpr *E);
145   bool VisitUnaryOperator(const UnaryOperator *E);
146   bool VisitVectorUnaryOperator(const UnaryOperator *E);
147   bool VisitComplexUnaryOperator(const UnaryOperator *E);
148   bool VisitDeclRefExpr(const DeclRefExpr *E);
149   bool VisitImplicitValueInitExpr(const ImplicitValueInitExpr *E);
150   bool VisitSubstNonTypeTemplateParmExpr(const SubstNonTypeTemplateParmExpr *E);
151   bool VisitArraySubscriptExpr(const ArraySubscriptExpr *E);
152   bool VisitInitListExpr(const InitListExpr *E);
153   bool VisitCXXParenListInitExpr(const CXXParenListInitExpr *E);
154   bool VisitConstantExpr(const ConstantExpr *E);
155   bool VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *E);
156   bool VisitMemberExpr(const MemberExpr *E);
157   bool VisitArrayInitIndexExpr(const ArrayInitIndexExpr *E);
158   bool VisitArrayInitLoopExpr(const ArrayInitLoopExpr *E);
159   bool VisitOpaqueValueExpr(const OpaqueValueExpr *E);
160   bool VisitAbstractConditionalOperator(const AbstractConditionalOperator *E);
161   bool VisitStringLiteral(const StringLiteral *E);
162   bool VisitObjCStringLiteral(const ObjCStringLiteral *E);
163   bool VisitObjCEncodeExpr(const ObjCEncodeExpr *E);
164   bool VisitSYCLUniqueStableNameExpr(const SYCLUniqueStableNameExpr *E);
165   bool VisitCharacterLiteral(const CharacterLiteral *E);
166   bool VisitCompoundAssignOperator(const CompoundAssignOperator *E);
167   bool VisitFloatCompoundAssignOperator(const CompoundAssignOperator *E);
168   bool VisitPointerCompoundAssignOperator(const CompoundAssignOperator *E);
169   bool VisitExprWithCleanups(const ExprWithCleanups *E);
170   bool VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *E);
171   bool VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *E);
172   bool VisitCompoundLiteralExpr(const CompoundLiteralExpr *E);
173   bool VisitTypeTraitExpr(const TypeTraitExpr *E);
174   bool VisitArrayTypeTraitExpr(const ArrayTypeTraitExpr *E);
175   bool VisitLambdaExpr(const LambdaExpr *E);
176   bool VisitPredefinedExpr(const PredefinedExpr *E);
177   bool VisitCXXThrowExpr(const CXXThrowExpr *E);
178   bool VisitCXXReinterpretCastExpr(const CXXReinterpretCastExpr *E);
179   bool VisitCXXNoexceptExpr(const CXXNoexceptExpr *E);
180   bool VisitCXXConstructExpr(const CXXConstructExpr *E);
181   bool VisitSourceLocExpr(const SourceLocExpr *E);
182   bool VisitOffsetOfExpr(const OffsetOfExpr *E);
183   bool VisitCXXScalarValueInitExpr(const CXXScalarValueInitExpr *E);
184   bool VisitSizeOfPackExpr(const SizeOfPackExpr *E);
185   bool VisitGenericSelectionExpr(const GenericSelectionExpr *E);
186   bool VisitChooseExpr(const ChooseExpr *E);
187   bool VisitEmbedExpr(const EmbedExpr *E);
188   bool VisitObjCBoolLiteralExpr(const ObjCBoolLiteralExpr *E);
189   bool VisitCXXInheritedCtorInitExpr(const CXXInheritedCtorInitExpr *E);
190   bool VisitExpressionTraitExpr(const ExpressionTraitExpr *E);
191   bool VisitCXXUuidofExpr(const CXXUuidofExpr *E);
192   bool VisitRequiresExpr(const RequiresExpr *E);
193   bool VisitConceptSpecializationExpr(const ConceptSpecializationExpr *E);
194   bool VisitCXXRewrittenBinaryOperator(const CXXRewrittenBinaryOperator *E);
195   bool VisitPseudoObjectExpr(const PseudoObjectExpr *E);
196   bool VisitPackIndexingExpr(const PackIndexingExpr *E);
197   bool VisitRecoveryExpr(const RecoveryExpr *E);
198   bool VisitAddrLabelExpr(const AddrLabelExpr *E);
199   bool VisitConvertVectorExpr(const ConvertVectorExpr *E);
200   bool VisitShuffleVectorExpr(const ShuffleVectorExpr *E);
201   bool VisitExtVectorElementExpr(const ExtVectorElementExpr *E);
202   bool VisitObjCBoxedExpr(const ObjCBoxedExpr *E);
203   bool VisitCXXStdInitializerListExpr(const CXXStdInitializerListExpr *E);
204   bool VisitStmtExpr(const StmtExpr *E);
205   bool VisitCXXNewExpr(const CXXNewExpr *E);
206   bool VisitCXXDeleteExpr(const CXXDeleteExpr *E);
207   bool VisitBlockExpr(const BlockExpr *E);
208 
209   // Statements.
210   bool visitCompoundStmt(const CompoundStmt *S);
211   bool visitDeclStmt(const DeclStmt *DS);
212   bool visitReturnStmt(const ReturnStmt *RS);
213   bool visitIfStmt(const IfStmt *IS);
214   bool visitWhileStmt(const WhileStmt *S);
215   bool visitDoStmt(const DoStmt *S);
216   bool visitForStmt(const ForStmt *S);
217   bool visitCXXForRangeStmt(const CXXForRangeStmt *S);
218   bool visitBreakStmt(const BreakStmt *S);
219   bool visitContinueStmt(const ContinueStmt *S);
220   bool visitSwitchStmt(const SwitchStmt *S);
221   bool visitCaseStmt(const CaseStmt *S);
222   bool visitDefaultStmt(const DefaultStmt *S);
223   bool visitAttributedStmt(const AttributedStmt *S);
224   bool visitCXXTryStmt(const CXXTryStmt *S);
225 
226 protected:
227   bool visitStmt(const Stmt *S);
228   bool visitExpr(const Expr *E, bool DestroyToplevelScope) override;
229   bool visitFunc(const FunctionDecl *F) override;
230 
231   bool visitDeclAndReturn(const VarDecl *VD, bool ConstantContext) override;
232 
233 protected:
234   /// Emits scope cleanup instructions.
235   void emitCleanup();
236 
237   /// Returns a record type from a record or pointer type.
238   const RecordType *getRecordTy(QualType Ty);
239 
240   /// Returns a record from a record or pointer type.
241   Record *getRecord(QualType Ty);
242   Record *getRecord(const RecordDecl *RD);
243 
244   /// Returns a function for the given FunctionDecl.
245   /// If the function does not exist yet, it is compiled.
246   const Function *getFunction(const FunctionDecl *FD);
247 
248   std::optional<PrimType> classify(const Expr *E) const {
249     return Ctx.classify(E);
250   }
251   std::optional<PrimType> classify(QualType Ty) const {
252     return Ctx.classify(Ty);
253   }
254 
255   /// Classifies a known primitive type.
256   PrimType classifyPrim(QualType Ty) const {
257     if (auto T = classify(Ty)) {
258       return *T;
259     }
260     llvm_unreachable("not a primitive type");
261   }
262   /// Classifies a known primitive expression.
263   PrimType classifyPrim(const Expr *E) const {
264     if (auto T = classify(E))
265       return *T;
266     llvm_unreachable("not a primitive type");
267   }
268 
269   /// Evaluates an expression and places the result on the stack. If the
270   /// expression is of composite type, a local variable will be created
271   /// and a pointer to said variable will be placed on the stack.
272   bool visit(const Expr *E);
273   /// Compiles an initializer. This is like visit() but it will never
274   /// create a variable and instead rely on a variable already having
275   /// been created. visitInitializer() then relies on a pointer to this
276   /// variable being on top of the stack.
277   bool visitInitializer(const Expr *E);
278   /// Evaluates an expression for side effects and discards the result.
279   bool discard(const Expr *E);
280   /// Just pass evaluation on to \p E. This leaves all the parsing flags
281   /// intact.
282   bool delegate(const Expr *E);
283   /// Creates and initializes a variable from the given decl.
284   VarCreationState visitVarDecl(const VarDecl *VD, bool Toplevel = false);
285   VarCreationState visitDecl(const VarDecl *VD);
286   /// Visit an APValue.
287   bool visitAPValue(const APValue &Val, PrimType ValType, const Expr *E);
288   bool visitAPValueInitializer(const APValue &Val, const Expr *E);
289   /// Visit the given decl as if we have a reference to it.
290   bool visitDeclRef(const ValueDecl *D, const Expr *E);
291 
292   /// Visits an expression and converts it to a boolean.
293   bool visitBool(const Expr *E);
294 
295   bool visitInitList(ArrayRef<const Expr *> Inits, const Expr *ArrayFiller,
296                      const Expr *E);
297   bool visitArrayElemInit(unsigned ElemIndex, const Expr *Init);
298 
299   /// Creates a local primitive value.
300   unsigned allocateLocalPrimitive(DeclTy &&Decl, PrimType Ty, bool IsConst,
301                                   bool IsExtended = false);
302 
303   /// Allocates a space storing a local given its type.
304   std::optional<unsigned>
305   allocateLocal(DeclTy &&Decl, QualType Ty = QualType(),
306                 const ValueDecl *ExtendingDecl = nullptr);
307   unsigned allocateTemporary(const Expr *E);
308 
309 private:
310   friend class VariableScope<Emitter>;
311   friend class LocalScope<Emitter>;
312   friend class DestructorScope<Emitter>;
313   friend class DeclScope<Emitter>;
314   friend class InitLinkScope<Emitter>;
315   friend class InitStackScope<Emitter>;
316   friend class OptionScope<Emitter>;
317   friend class ArrayIndexScope<Emitter>;
318   friend class SourceLocScope<Emitter>;
319   friend struct InitLink;
320   friend class LoopScope<Emitter>;
321   friend class LabelScope<Emitter>;
322   friend class SwitchScope<Emitter>;
323   friend class StmtExprScope<Emitter>;
324 
325   /// Emits a zero initializer.
326   bool visitZeroInitializer(PrimType T, QualType QT, const Expr *E);
327   bool visitZeroRecordInitializer(const Record *R, const Expr *E);
328   bool visitZeroArrayInitializer(QualType T, const Expr *E);
329 
330   /// Emits an APSInt constant.
331   bool emitConst(const llvm::APSInt &Value, PrimType Ty, const Expr *E);
332   bool emitConst(const llvm::APSInt &Value, const Expr *E);
333   bool emitConst(const llvm::APInt &Value, const Expr *E) {
334     return emitConst(static_cast<llvm::APSInt>(Value), E);
335   }
336 
337   /// Emits an integer constant.
338   template <typename T> bool emitConst(T Value, PrimType Ty, const Expr *E);
339   template <typename T> bool emitConst(T Value, const Expr *E);
340 
341   llvm::RoundingMode getRoundingMode(const Expr *E) const {
342     FPOptions FPO = E->getFPFeaturesInEffect(Ctx.getLangOpts());
343 
344     if (FPO.getRoundingMode() == llvm::RoundingMode::Dynamic)
345       return llvm::RoundingMode::NearestTiesToEven;
346 
347     return FPO.getRoundingMode();
348   }
349 
350   uint32_t getFPOptions(const Expr *E) const {
351     return E->getFPFeaturesInEffect(Ctx.getLangOpts()).getAsOpaqueInt();
352   }
353 
354   bool emitPrimCast(PrimType FromT, PrimType ToT, QualType ToQT, const Expr *E);
355   PrimType classifyComplexElementType(QualType T) const {
356     assert(T->isAnyComplexType());
357 
358     QualType ElemType = T->getAs<ComplexType>()->getElementType();
359 
360     return *this->classify(ElemType);
361   }
362 
363   PrimType classifyVectorElementType(QualType T) const {
364     assert(T->isVectorType());
365     return *this->classify(T->getAs<VectorType>()->getElementType());
366   }
367 
368   bool emitComplexReal(const Expr *SubExpr);
369   bool emitComplexBoolCast(const Expr *E);
370   bool emitComplexComparison(const Expr *LHS, const Expr *RHS,
371                              const BinaryOperator *E);
372   bool emitRecordDestruction(const Record *R, SourceInfo Loc);
373   bool emitDestruction(const Descriptor *Desc, SourceInfo Loc);
374   bool emitDummyPtr(const DeclTy &D, const Expr *E);
375   unsigned collectBaseOffset(const QualType BaseType,
376                              const QualType DerivedType);
377   bool emitLambdaStaticInvokerBody(const CXXMethodDecl *MD);
378   bool emitBuiltinBitCast(const CastExpr *E);
379   bool compileConstructor(const CXXConstructorDecl *Ctor);
380   bool compileDestructor(const CXXDestructorDecl *Dtor);
381 
382   bool checkLiteralType(const Expr *E);
383 
384 protected:
385   /// Variable to storage mapping.
386   llvm::DenseMap<const ValueDecl *, Scope::Local> Locals;
387 
388   /// OpaqueValueExpr to location mapping.
389   llvm::DenseMap<const OpaqueValueExpr *, unsigned> OpaqueExprs;
390 
391   /// Current scope.
392   VariableScope<Emitter> *VarScope = nullptr;
393 
394   /// Current argument index. Needed to emit ArrayInitIndexExpr.
395   std::optional<uint64_t> ArrayIndex;
396 
397   /// DefaultInit- or DefaultArgExpr, needed for SourceLocExpr.
398   const Expr *SourceLocDefaultExpr = nullptr;
399 
400   /// Flag indicating if return value is to be discarded.
401   bool DiscardResult = false;
402 
403   bool InStmtExpr = false;
404 
405   /// Flag inidicating if we're initializing an already created
406   /// variable. This is set in visitInitializer().
407   bool Initializing = false;
408   const ValueDecl *InitializingDecl = nullptr;
409 
410   llvm::SmallVector<InitLink> InitStack;
411   bool InitStackActive = false;
412 
413   /// Type of the expression returned by the function.
414   std::optional<PrimType> ReturnType;
415 
416   /// Switch case mapping.
417   CaseMap CaseLabels;
418 
419   /// Scope to cleanup until when we see a break statement.
420   VariableScope<Emitter> *BreakVarScope = nullptr;
421   /// Point to break to.
422   OptLabelTy BreakLabel;
423   /// Scope to cleanup until when we see a continue statement.
424   VariableScope<Emitter> *ContinueVarScope = nullptr;
425   /// Point to continue to.
426   OptLabelTy ContinueLabel;
427   /// Default case label.
428   OptLabelTy DefaultLabel;
429 };
430 
431 extern template class Compiler<ByteCodeEmitter>;
432 extern template class Compiler<EvalEmitter>;
433 
434 /// Scope chain managing the variable lifetimes.
435 template <class Emitter> class VariableScope {
436 public:
437   VariableScope(Compiler<Emitter> *Ctx, const ValueDecl *VD)
438       : Ctx(Ctx), Parent(Ctx->VarScope), ValDecl(VD) {
439     Ctx->VarScope = this;
440   }
441 
442   virtual ~VariableScope() { Ctx->VarScope = this->Parent; }
443 
444   void add(const Scope::Local &Local, bool IsExtended) {
445     if (IsExtended)
446       this->addExtended(Local);
447     else
448       this->addLocal(Local);
449   }
450 
451   virtual void addLocal(const Scope::Local &Local) {
452     if (this->Parent)
453       this->Parent->addLocal(Local);
454   }
455 
456   virtual void addExtended(const Scope::Local &Local) {
457     if (this->Parent)
458       this->Parent->addExtended(Local);
459   }
460 
461   void addExtended(const Scope::Local &Local, const ValueDecl *ExtendingDecl) {
462     // Walk up the chain of scopes until we find the one for ExtendingDecl.
463     // If there is no such scope, attach it to the parent one.
464     VariableScope *P = this;
465     while (P) {
466       if (P->ValDecl == ExtendingDecl) {
467         P->addLocal(Local);
468         return;
469       }
470       P = P->Parent;
471       if (!P)
472         break;
473     }
474 
475     // Use the parent scope.
476     if (this->Parent)
477       this->Parent->addLocal(Local);
478     else
479       this->addLocal(Local);
480   }
481 
482   virtual void emitDestruction() {}
483   virtual bool emitDestructors(const Expr *E = nullptr) { return true; }
484   virtual bool destroyLocals(const Expr *E = nullptr) { return true; }
485   VariableScope *getParent() const { return Parent; }
486 
487 protected:
488   /// Compiler instance.
489   Compiler<Emitter> *Ctx;
490   /// Link to the parent scope.
491   VariableScope *Parent;
492   const ValueDecl *ValDecl = nullptr;
493 };
494 
495 /// Generic scope for local variables.
496 template <class Emitter> class LocalScope : public VariableScope<Emitter> {
497 public:
498   LocalScope(Compiler<Emitter> *Ctx) : VariableScope<Emitter>(Ctx, nullptr) {}
499   LocalScope(Compiler<Emitter> *Ctx, const ValueDecl *VD)
500       : VariableScope<Emitter>(Ctx, VD) {}
501 
502   /// Emit a Destroy op for this scope.
503   ~LocalScope() override {
504     if (!Idx)
505       return;
506     this->Ctx->emitDestroy(*Idx, SourceInfo{});
507     removeStoredOpaqueValues();
508   }
509 
510   /// Overriden to support explicit destruction.
511   void emitDestruction() override {
512     if (!Idx)
513       return;
514 
515     this->emitDestructors();
516     this->Ctx->emitDestroy(*Idx, SourceInfo{});
517   }
518 
519   /// Explicit destruction of local variables.
520   bool destroyLocals(const Expr *E = nullptr) override {
521     if (!Idx)
522       return true;
523 
524     bool Success = this->emitDestructors(E);
525     this->Ctx->emitDestroy(*Idx, E);
526     this->Idx = std::nullopt;
527     return Success;
528   }
529 
530   void addLocal(const Scope::Local &Local) override {
531     if (!Idx) {
532       Idx = this->Ctx->Descriptors.size();
533       this->Ctx->Descriptors.emplace_back();
534       this->Ctx->emitInitScope(*Idx, {});
535     }
536 
537     this->Ctx->Descriptors[*Idx].emplace_back(Local);
538   }
539 
540   bool emitDestructors(const Expr *E = nullptr) override {
541     if (!Idx)
542       return true;
543     // Emit destructor calls for local variables of record
544     // type with a destructor.
545     for (Scope::Local &Local : llvm::reverse(this->Ctx->Descriptors[*Idx])) {
546       if (!Local.Desc->isPrimitive() && !Local.Desc->isPrimitiveArray()) {
547         if (!this->Ctx->emitGetPtrLocal(Local.Offset, E))
548           return false;
549 
550         if (!this->Ctx->emitDestruction(Local.Desc, Local.Desc->getLoc()))
551           return false;
552 
553         if (!this->Ctx->emitPopPtr(E))
554           return false;
555         removeIfStoredOpaqueValue(Local);
556       }
557     }
558     return true;
559   }
560 
561   void removeStoredOpaqueValues() {
562     if (!Idx)
563       return;
564 
565     for (const Scope::Local &Local : this->Ctx->Descriptors[*Idx]) {
566       removeIfStoredOpaqueValue(Local);
567     }
568   }
569 
570   void removeIfStoredOpaqueValue(const Scope::Local &Local) {
571     if (const auto *OVE =
572             llvm::dyn_cast_if_present<OpaqueValueExpr>(Local.Desc->asExpr())) {
573       if (auto It = this->Ctx->OpaqueExprs.find(OVE);
574           It != this->Ctx->OpaqueExprs.end())
575         this->Ctx->OpaqueExprs.erase(It);
576     };
577   }
578 
579   /// Index of the scope in the chain.
580   std::optional<unsigned> Idx;
581 };
582 
583 /// Scope for storage declared in a compound statement.
584 template <class Emitter> class BlockScope final : public LocalScope<Emitter> {
585 public:
586   BlockScope(Compiler<Emitter> *Ctx) : LocalScope<Emitter>(Ctx) {}
587 
588   void addExtended(const Scope::Local &Local) override {
589     // If we to this point, just add the variable as a normal local
590     // variable. It will be destroyed at the end of the block just
591     // like all others.
592     this->addLocal(Local);
593   }
594 };
595 
596 template <class Emitter> class ArrayIndexScope final {
597 public:
598   ArrayIndexScope(Compiler<Emitter> *Ctx, uint64_t Index) : Ctx(Ctx) {
599     OldArrayIndex = Ctx->ArrayIndex;
600     Ctx->ArrayIndex = Index;
601   }
602 
603   ~ArrayIndexScope() { Ctx->ArrayIndex = OldArrayIndex; }
604 
605 private:
606   Compiler<Emitter> *Ctx;
607   std::optional<uint64_t> OldArrayIndex;
608 };
609 
610 template <class Emitter> class SourceLocScope final {
611 public:
612   SourceLocScope(Compiler<Emitter> *Ctx, const Expr *DefaultExpr) : Ctx(Ctx) {
613     assert(DefaultExpr);
614     // We only switch if the current SourceLocDefaultExpr is null.
615     if (!Ctx->SourceLocDefaultExpr) {
616       Enabled = true;
617       Ctx->SourceLocDefaultExpr = DefaultExpr;
618     }
619   }
620 
621   ~SourceLocScope() {
622     if (Enabled)
623       Ctx->SourceLocDefaultExpr = nullptr;
624   }
625 
626 private:
627   Compiler<Emitter> *Ctx;
628   bool Enabled = false;
629 };
630 
631 template <class Emitter> class InitLinkScope final {
632 public:
633   InitLinkScope(Compiler<Emitter> *Ctx, InitLink &&Link) : Ctx(Ctx) {
634     Ctx->InitStack.push_back(std::move(Link));
635   }
636 
637   ~InitLinkScope() { this->Ctx->InitStack.pop_back(); }
638 
639 private:
640   Compiler<Emitter> *Ctx;
641 };
642 
643 template <class Emitter> class InitStackScope final {
644 public:
645   InitStackScope(Compiler<Emitter> *Ctx, bool Active)
646       : Ctx(Ctx), OldValue(Ctx->InitStackActive) {
647     Ctx->InitStackActive = Active;
648   }
649 
650   ~InitStackScope() { this->Ctx->InitStackActive = OldValue; }
651 
652 private:
653   Compiler<Emitter> *Ctx;
654   bool OldValue;
655 };
656 
657 } // namespace interp
658 } // namespace clang
659 
660 #endif
661