Author: Timm Baeder
Date: 2026-07-06T07:04:43+02:00
New Revision: aae9f9ed88eda733e46e308351ba5cd68091806f

URL: 
https://github.com/llvm/llvm-project/commit/aae9f9ed88eda733e46e308351ba5cd68091806f
DIFF: 
https://github.com/llvm/llvm-project/commit/aae9f9ed88eda733e46e308351ba5cd68091806f.diff

LOG: [clang][bytecode][NFC] Move Scope classes to source file (#207647)

Added: 
    

Modified: 
    clang/lib/AST/ByteCode/Compiler.cpp
    clang/lib/AST/ByteCode/Compiler.h

Removed: 
    


################################################################################
diff  --git a/clang/lib/AST/ByteCode/Compiler.cpp 
b/clang/lib/AST/ByteCode/Compiler.cpp
index 090bbf4596413..662944a9bd2ca 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -37,6 +37,240 @@ static std::optional<bool> getBoolValue(const Expr *E) {
   return std::nullopt;
 }
 
+/// Scope chain managing the variable lifetimes.
+template <class Emitter> class VariableScope {
+public:
+  VariableScope(Compiler<Emitter> *Ctx, ScopeKind Kind = ScopeKind::Block)
+      : Ctx(Ctx), Parent(Ctx->VarScope), Kind(Kind) {
+    if (Parent)
+      this->LocalsAlwaysEnabled = Parent->LocalsAlwaysEnabled;
+    Ctx->VarScope = this;
+  }
+
+  virtual ~VariableScope() { Ctx->VarScope = this->Parent; }
+
+  virtual void addLocal(Scope::Local Local) {
+    llvm_unreachable("Shouldn't be called");
+  }
+  /// Like addExtended, but adds to the nearest scope of the given kind.
+  void addForScopeKind(const Scope::Local &Local, ScopeKind Kind) {
+    VariableScope *P = this;
+    while (P) {
+      // We found the right scope kind.
+      if (P->Kind == Kind) {
+        P->addLocal(Local);
+        return;
+      }
+      // If we reached the root scope and we're looking for a Block scope,
+      // attach it to the root instead of the current scope.
+      if (!P->Parent && Kind == ScopeKind::Block) {
+        P->addLocal(Local);
+        return;
+      }
+      P = P->Parent;
+      if (!P)
+        break;
+    }
+
+    // Add to this scope.
+    this->addLocal(Local);
+  }
+
+  virtual bool emitDestructors(const Expr *E = nullptr) { return true; }
+  virtual bool destroyLocals(const Expr *E = nullptr) { return true; }
+  virtual void forceInit() {}
+  VariableScope *getParent() const { return Parent; }
+  ScopeKind getKind() const { return Kind; }
+
+  /// Whether locals added to this scope are enabled by default.
+  /// This is almost always true, except for the two branches
+  /// of a conditional operator.
+  bool LocalsAlwaysEnabled = true;
+
+protected:
+  /// Compiler instance.
+  Compiler<Emitter> *Ctx;
+  /// Link to the parent scope.
+  VariableScope *Parent;
+  ScopeKind Kind;
+};
+
+/// Generic scope for local variables.
+template <class Emitter> class LocalScope : public VariableScope<Emitter> {
+public:
+  LocalScope(Compiler<Emitter> *Ctx, ScopeKind Kind = ScopeKind::Block)
+      : VariableScope<Emitter>(Ctx, Kind) {}
+
+  /// Emit a Destroy op for this scope.
+  ~LocalScope() override {
+    if (!Idx)
+      return;
+    this->Ctx->emitDestroy(*Idx, SourceInfo{});
+    removeStoredOpaqueValues();
+  }
+  /// Explicit destruction of local variables.
+  bool destroyLocals(const Expr *E = nullptr) override {
+    if (!Idx)
+      return true;
+
+    // NB: We are *not* resetting Idx here as to allow multiple
+    // calls to destroyLocals().
+    bool Success = this->emitDestructors(E);
+    this->Ctx->emitDestroy(*Idx, E);
+    return Success;
+  }
+
+  void addLocal(Scope::Local Local) override {
+    if (!Idx) {
+      Idx = static_cast<unsigned>(this->Ctx->Descriptors.size());
+      this->Ctx->Descriptors.emplace_back();
+      this->Ctx->emitInitScope(*Idx, {});
+    }
+
+    Local.EnabledByDefault = this->LocalsAlwaysEnabled;
+    this->Ctx->Descriptors[*Idx].emplace_back(Local);
+  }
+
+  /// Force-initialize this scope. Usually, scopes are lazily initialized when
+  /// the first local variable is created, but in scenarios with conditonal
+  /// operators, we need to ensure scope is initialized just in case one of the
+  /// arms will create a local and the other won't. In such a case, the
+  /// InitScope() op would be part of the arm that created the local.
+  void forceInit() override {
+    if (!Idx) {
+      Idx = static_cast<unsigned>(this->Ctx->Descriptors.size());
+      this->Ctx->Descriptors.emplace_back();
+      this->Ctx->emitInitScope(*Idx, {});
+    }
+  }
+
+  bool emitDestructors(const Expr *E = nullptr) override {
+    if (!Idx)
+      return true;
+
+    // Emit destructor calls for local variables of record
+    // type with a destructor.
+    for (Scope::Local &Local : llvm::reverse(this->Ctx->Descriptors[*Idx])) {
+      if (Local.Desc->hasTrivialDtor())
+        continue;
+
+      if (!Local.EnabledByDefault) {
+        typename Emitter::LabelTy EndLabel = this->Ctx->getLabel();
+        if (!this->Ctx->emitGetLocalEnabled(Local.Offset, E))
+          return false;
+        if (!this->Ctx->jumpFalse(EndLabel, E))
+          return false;
+
+        if (!this->Ctx->emitGetPtrLocal(Local.Offset, E))
+          return false;
+
+        if (!this->Ctx->emitDestructionPop(Local.Desc, Local.Desc->getLoc()))
+          return false;
+
+        this->Ctx->fallthrough(EndLabel);
+        this->Ctx->emitLabel(EndLabel);
+      } else {
+        if (!this->Ctx->emitGetPtrLocal(Local.Offset, E))
+          return false;
+        if (!this->Ctx->emitDestructionPop(Local.Desc, Local.Desc->getLoc()))
+          return false;
+      }
+
+      removeIfStoredOpaqueValue(Local);
+    }
+    return true;
+  }
+
+  void removeStoredOpaqueValues() {
+    if (!Idx)
+      return;
+
+    for (const Scope::Local &Local : this->Ctx->Descriptors[*Idx]) {
+      removeIfStoredOpaqueValue(Local);
+    }
+  }
+
+  void removeIfStoredOpaqueValue(const Scope::Local &Local) {
+    if (const auto *OVE =
+            llvm::dyn_cast_if_present<OpaqueValueExpr>(Local.Desc->asExpr())) {
+      if (auto It = this->Ctx->OpaqueExprs.find(OVE);
+          It != this->Ctx->OpaqueExprs.end())
+        this->Ctx->OpaqueExprs.erase(It);
+    };
+  }
+
+  /// Index of the scope in the chain.
+  UnsignedOrNone Idx = std::nullopt;
+};
+
+template <class Emitter> class ArrayIndexScope final {
+public:
+  ArrayIndexScope(Compiler<Emitter> *Ctx, uint64_t Index) : Ctx(Ctx) {
+    OldArrayIndex = Ctx->ArrayIndex;
+    Ctx->ArrayIndex = Index;
+  }
+
+  ~ArrayIndexScope() { Ctx->ArrayIndex = OldArrayIndex; }
+
+private:
+  Compiler<Emitter> *Ctx;
+  std::optional<uint64_t> OldArrayIndex;
+};
+
+template <class Emitter> class SourceLocScope final {
+public:
+  SourceLocScope(Compiler<Emitter> *Ctx, const Expr *DefaultExpr) : Ctx(Ctx) {
+    assert(DefaultExpr);
+    // We only switch if the current SourceLocDefaultExpr is null.
+    if (!Ctx->SourceLocDefaultExpr) {
+      Enabled = true;
+      Ctx->SourceLocDefaultExpr = DefaultExpr;
+    }
+  }
+
+  ~SourceLocScope() {
+    if (Enabled)
+      Ctx->SourceLocDefaultExpr = nullptr;
+  }
+
+private:
+  Compiler<Emitter> *Ctx;
+  bool Enabled = false;
+};
+
+template <class Emitter> class InitLinkScope final {
+public:
+  InitLinkScope(Compiler<Emitter> *Ctx, InitLink &&Link) : Ctx(Ctx) {
+    Ctx->InitStack.push_back(std::move(Link));
+  }
+
+  ~InitLinkScope() { this->Ctx->InitStack.pop_back(); }
+
+public:
+  Compiler<Emitter> *Ctx;
+};
+
+template <class Emitter> class InitStackScope final {
+public:
+  InitStackScope(Compiler<Emitter> *Ctx, bool Active)
+      : Ctx(Ctx), OldValue(Ctx->InitStackActive), Active(Active) {
+    Ctx->InitStackActive = Active;
+    if (Active)
+      Ctx->InitStack.push_back(InitLink::DIE());
+  }
+
+  ~InitStackScope() {
+    this->Ctx->InitStackActive = OldValue;
+    if (Active)
+      Ctx->InitStack.pop_back();
+  }
+
+private:
+  Compiler<Emitter> *Ctx;
+  bool OldValue;
+  bool Active;
+};
+
 /// Scope used to handle temporaries in toplevel variable declarations.
 template <class Emitter> class DeclScope final : public LocalScope<Emitter> {
 public:

diff  --git a/clang/lib/AST/ByteCode/Compiler.h 
b/clang/lib/AST/ByteCode/Compiler.h
index 0a2e75887711d..a93fdd20b712f 100644
--- a/clang/lib/AST/ByteCode/Compiler.h
+++ b/clang/lib/AST/ByteCode/Compiler.h
@@ -509,240 +509,6 @@ class Compiler : public 
ConstStmtVisitor<Compiler<Emitter>, bool>,
 extern template class Compiler<ByteCodeEmitter>;
 extern template class Compiler<EvalEmitter>;
 
-/// Scope chain managing the variable lifetimes.
-template <class Emitter> class VariableScope {
-public:
-  VariableScope(Compiler<Emitter> *Ctx, ScopeKind Kind = ScopeKind::Block)
-      : Ctx(Ctx), Parent(Ctx->VarScope), Kind(Kind) {
-    if (Parent)
-      this->LocalsAlwaysEnabled = Parent->LocalsAlwaysEnabled;
-    Ctx->VarScope = this;
-  }
-
-  virtual ~VariableScope() { Ctx->VarScope = this->Parent; }
-
-  virtual void addLocal(Scope::Local Local) {
-    llvm_unreachable("Shouldn't be called");
-  }
-  /// Like addExtended, but adds to the nearest scope of the given kind.
-  void addForScopeKind(const Scope::Local &Local, ScopeKind Kind) {
-    VariableScope *P = this;
-    while (P) {
-      // We found the right scope kind.
-      if (P->Kind == Kind) {
-        P->addLocal(Local);
-        return;
-      }
-      // If we reached the root scope and we're looking for a Block scope,
-      // attach it to the root instead of the current scope.
-      if (!P->Parent && Kind == ScopeKind::Block) {
-        P->addLocal(Local);
-        return;
-      }
-      P = P->Parent;
-      if (!P)
-        break;
-    }
-
-    // Add to this scope.
-    this->addLocal(Local);
-  }
-
-  virtual bool emitDestructors(const Expr *E = nullptr) { return true; }
-  virtual bool destroyLocals(const Expr *E = nullptr) { return true; }
-  virtual void forceInit() {}
-  VariableScope *getParent() const { return Parent; }
-  ScopeKind getKind() const { return Kind; }
-
-  /// Whether locals added to this scope are enabled by default.
-  /// This is almost always true, except for the two branches
-  /// of a conditional operator.
-  bool LocalsAlwaysEnabled = true;
-
-protected:
-  /// Compiler instance.
-  Compiler<Emitter> *Ctx;
-  /// Link to the parent scope.
-  VariableScope *Parent;
-  ScopeKind Kind;
-};
-
-/// Generic scope for local variables.
-template <class Emitter> class LocalScope : public VariableScope<Emitter> {
-public:
-  LocalScope(Compiler<Emitter> *Ctx, ScopeKind Kind = ScopeKind::Block)
-      : VariableScope<Emitter>(Ctx, Kind) {}
-
-  /// Emit a Destroy op for this scope.
-  ~LocalScope() override {
-    if (!Idx)
-      return;
-    this->Ctx->emitDestroy(*Idx, SourceInfo{});
-    removeStoredOpaqueValues();
-  }
-  /// Explicit destruction of local variables.
-  bool destroyLocals(const Expr *E = nullptr) override {
-    if (!Idx)
-      return true;
-
-    // NB: We are *not* resetting Idx here as to allow multiple
-    // calls to destroyLocals().
-    bool Success = this->emitDestructors(E);
-    this->Ctx->emitDestroy(*Idx, E);
-    return Success;
-  }
-
-  void addLocal(Scope::Local Local) override {
-    if (!Idx) {
-      Idx = static_cast<unsigned>(this->Ctx->Descriptors.size());
-      this->Ctx->Descriptors.emplace_back();
-      this->Ctx->emitInitScope(*Idx, {});
-    }
-
-    Local.EnabledByDefault = this->LocalsAlwaysEnabled;
-    this->Ctx->Descriptors[*Idx].emplace_back(Local);
-  }
-
-  /// Force-initialize this scope. Usually, scopes are lazily initialized when
-  /// the first local variable is created, but in scenarios with conditonal
-  /// operators, we need to ensure scope is initialized just in case one of the
-  /// arms will create a local and the other won't. In such a case, the
-  /// InitScope() op would be part of the arm that created the local.
-  void forceInit() override {
-    if (!Idx) {
-      Idx = static_cast<unsigned>(this->Ctx->Descriptors.size());
-      this->Ctx->Descriptors.emplace_back();
-      this->Ctx->emitInitScope(*Idx, {});
-    }
-  }
-
-  bool emitDestructors(const Expr *E = nullptr) override {
-    if (!Idx)
-      return true;
-
-    // Emit destructor calls for local variables of record
-    // type with a destructor.
-    for (Scope::Local &Local : llvm::reverse(this->Ctx->Descriptors[*Idx])) {
-      if (Local.Desc->hasTrivialDtor())
-        continue;
-
-      if (!Local.EnabledByDefault) {
-        typename Emitter::LabelTy EndLabel = this->Ctx->getLabel();
-        if (!this->Ctx->emitGetLocalEnabled(Local.Offset, E))
-          return false;
-        if (!this->Ctx->jumpFalse(EndLabel, E))
-          return false;
-
-        if (!this->Ctx->emitGetPtrLocal(Local.Offset, E))
-          return false;
-
-        if (!this->Ctx->emitDestructionPop(Local.Desc, Local.Desc->getLoc()))
-          return false;
-
-        this->Ctx->fallthrough(EndLabel);
-        this->Ctx->emitLabel(EndLabel);
-      } else {
-        if (!this->Ctx->emitGetPtrLocal(Local.Offset, E))
-          return false;
-        if (!this->Ctx->emitDestructionPop(Local.Desc, Local.Desc->getLoc()))
-          return false;
-      }
-
-      removeIfStoredOpaqueValue(Local);
-    }
-    return true;
-  }
-
-  void removeStoredOpaqueValues() {
-    if (!Idx)
-      return;
-
-    for (const Scope::Local &Local : this->Ctx->Descriptors[*Idx]) {
-      removeIfStoredOpaqueValue(Local);
-    }
-  }
-
-  void removeIfStoredOpaqueValue(const Scope::Local &Local) {
-    if (const auto *OVE =
-            llvm::dyn_cast_if_present<OpaqueValueExpr>(Local.Desc->asExpr())) {
-      if (auto It = this->Ctx->OpaqueExprs.find(OVE);
-          It != this->Ctx->OpaqueExprs.end())
-        this->Ctx->OpaqueExprs.erase(It);
-    };
-  }
-
-  /// Index of the scope in the chain.
-  UnsignedOrNone Idx = std::nullopt;
-};
-
-template <class Emitter> class ArrayIndexScope final {
-public:
-  ArrayIndexScope(Compiler<Emitter> *Ctx, uint64_t Index) : Ctx(Ctx) {
-    OldArrayIndex = Ctx->ArrayIndex;
-    Ctx->ArrayIndex = Index;
-  }
-
-  ~ArrayIndexScope() { Ctx->ArrayIndex = OldArrayIndex; }
-
-private:
-  Compiler<Emitter> *Ctx;
-  std::optional<uint64_t> OldArrayIndex;
-};
-
-template <class Emitter> class SourceLocScope final {
-public:
-  SourceLocScope(Compiler<Emitter> *Ctx, const Expr *DefaultExpr) : Ctx(Ctx) {
-    assert(DefaultExpr);
-    // We only switch if the current SourceLocDefaultExpr is null.
-    if (!Ctx->SourceLocDefaultExpr) {
-      Enabled = true;
-      Ctx->SourceLocDefaultExpr = DefaultExpr;
-    }
-  }
-
-  ~SourceLocScope() {
-    if (Enabled)
-      Ctx->SourceLocDefaultExpr = nullptr;
-  }
-
-private:
-  Compiler<Emitter> *Ctx;
-  bool Enabled = false;
-};
-
-template <class Emitter> class InitLinkScope final {
-public:
-  InitLinkScope(Compiler<Emitter> *Ctx, InitLink &&Link) : Ctx(Ctx) {
-    Ctx->InitStack.push_back(std::move(Link));
-  }
-
-  ~InitLinkScope() { this->Ctx->InitStack.pop_back(); }
-
-public:
-  Compiler<Emitter> *Ctx;
-};
-
-template <class Emitter> class InitStackScope final {
-public:
-  InitStackScope(Compiler<Emitter> *Ctx, bool Active)
-      : Ctx(Ctx), OldValue(Ctx->InitStackActive), Active(Active) {
-    Ctx->InitStackActive = Active;
-    if (Active)
-      Ctx->InitStack.push_back(InitLink::DIE());
-  }
-
-  ~InitStackScope() {
-    this->Ctx->InitStackActive = OldValue;
-    if (Active)
-      Ctx->InitStack.pop_back();
-  }
-
-private:
-  Compiler<Emitter> *Ctx;
-  bool OldValue;
-  bool Active;
-};
-
 } // namespace interp
 } // namespace clang
 


        
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to