[clang] [clang][bytecode] Fix a variable scope problem with continue/break jumps (PR #107738)

via cfe-commits cfe-commits at lists.llvm.org
Sun Sep 8 00:12:52 PDT 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Timm Baeder (tbaederr)

<details>
<summary>Changes</summary>

Cleaning up _all_ the scopes is a little too much. Only clean up until the point here we started the scope relevant for the break/continue statement.

---
Full diff: https://github.com/llvm/llvm-project/pull/107738.diff


3 Files Affected:

- (modified) clang/lib/AST/ByteCode/Compiler.cpp (+14-4) 
- (modified) clang/lib/AST/ByteCode/Compiler.h (+2) 
- (modified) clang/test/AST/ByteCode/new-delete.cpp (+19-13) 


``````````diff
diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp
index 46f9c98d59befc..cd25ccdd930237 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -114,7 +114,8 @@ template <class Emitter> class LoopScope final : public LabelScope<Emitter> {
 
   LoopScope(Compiler<Emitter> *Ctx, LabelTy BreakLabel, LabelTy ContinueLabel)
       : LabelScope<Emitter>(Ctx), OldBreakLabel(Ctx->BreakLabel),
-        OldContinueLabel(Ctx->ContinueLabel) {
+        OldContinueLabel(Ctx->ContinueLabel),
+        OldLabelVarScope(Ctx->LabelVarScope) {
     this->Ctx->BreakLabel = BreakLabel;
     this->Ctx->ContinueLabel = ContinueLabel;
   }
@@ -122,11 +123,13 @@ template <class Emitter> class LoopScope final : public LabelScope<Emitter> {
   ~LoopScope() {
     this->Ctx->BreakLabel = OldBreakLabel;
     this->Ctx->ContinueLabel = OldContinueLabel;
+    this->Ctx->LabelVarScope = OldLabelVarScope;
   }
 
 private:
   OptLabelTy OldBreakLabel;
   OptLabelTy OldContinueLabel;
+  VariableScope<Emitter> *OldLabelVarScope;
 };
 
 // Sets the context for a switch scope, mapping labels.
@@ -140,7 +143,8 @@ template <class Emitter> class SwitchScope final : public LabelScope<Emitter> {
               OptLabelTy DefaultLabel)
       : LabelScope<Emitter>(Ctx), OldBreakLabel(Ctx->BreakLabel),
         OldDefaultLabel(this->Ctx->DefaultLabel),
-        OldCaseLabels(std::move(this->Ctx->CaseLabels)) {
+        OldCaseLabels(std::move(this->Ctx->CaseLabels)),
+        OldLabelVarScope(Ctx->LabelVarScope) {
     this->Ctx->BreakLabel = BreakLabel;
     this->Ctx->DefaultLabel = DefaultLabel;
     this->Ctx->CaseLabels = std::move(CaseLabels);
@@ -150,12 +154,14 @@ template <class Emitter> class SwitchScope final : public LabelScope<Emitter> {
     this->Ctx->BreakLabel = OldBreakLabel;
     this->Ctx->DefaultLabel = OldDefaultLabel;
     this->Ctx->CaseLabels = std::move(OldCaseLabels);
+    this->Ctx->LabelVarScope = OldLabelVarScope;
   }
 
 private:
   OptLabelTy OldBreakLabel;
   OptLabelTy OldDefaultLabel;
   CaseMap OldCaseLabels;
+  VariableScope<Emitter> *OldLabelVarScope;
 };
 
 template <class Emitter> class StmtExprScope final {
@@ -4734,7 +4740,9 @@ bool Compiler<Emitter>::visitBreakStmt(const BreakStmt *S) {
   if (!BreakLabel)
     return false;
 
-  this->emitCleanup();
+  for (VariableScope<Emitter> *C = VarScope; C != LabelVarScope;
+       C = C->getParent())
+    C->emitDestruction();
   return this->jump(*BreakLabel);
 }
 
@@ -4743,7 +4751,9 @@ bool Compiler<Emitter>::visitContinueStmt(const ContinueStmt *S) {
   if (!ContinueLabel)
     return false;
 
-  this->emitCleanup();
+  for (VariableScope<Emitter> *C = VarScope; C != LabelVarScope;
+       C = C->getParent())
+    C->emitDestruction();
   return this->jump(*ContinueLabel);
 }
 
diff --git a/clang/lib/AST/ByteCode/Compiler.h b/clang/lib/AST/ByteCode/Compiler.h
index 39c0736cb4e27e..ac4c08c4d0ffb6 100644
--- a/clang/lib/AST/ByteCode/Compiler.h
+++ b/clang/lib/AST/ByteCode/Compiler.h
@@ -409,6 +409,8 @@ class Compiler : public ConstStmtVisitor<Compiler<Emitter>, bool>,
   /// Switch case mapping.
   CaseMap CaseLabels;
 
+  /// Scope to cleanup until when chumping to one of the labels.
+  VariableScope<Emitter> *LabelVarScope = nullptr;
   /// Point to break to.
   OptLabelTy BreakLabel;
   /// Point to continue to.
diff --git a/clang/test/AST/ByteCode/new-delete.cpp b/clang/test/AST/ByteCode/new-delete.cpp
index 902ab4aab10fb5..76858aa94bb37d 100644
--- a/clang/test/AST/ByteCode/new-delete.cpp
+++ b/clang/test/AST/ByteCode/new-delete.cpp
@@ -618,22 +618,28 @@ namespace OperatorNewDelete {
 
   constexpr bool mismatched(int alloc_kind, int dealloc_kind) {
     int *p;
-
-    if (alloc_kind == 0)
-      p = new int; // both-note {{allocation performed here}}
-    else if (alloc_kind == 1)
-      p = new int[1]; // both-note {{allocation performed here}}
-    else if (alloc_kind == 2)
+    switch (alloc_kind) {
+    case 0:
+      p = new int; // both-note {{heap allocation performed here}}
+      break;
+    case 1:
+      p = new int[1]; // both-note {{heap allocation performed here}}
+      break;
+    case 2:
       p = std::allocator<int>().allocate(1);
-
-
-    if (dealloc_kind == 0)
+      break;
+    }
+    switch (dealloc_kind) {
+    case 0:
       delete p; // both-note {{'delete' used to delete pointer to object allocated with 'std::allocator<...>::allocate'}}
-    else if (dealloc_kind == 1)
+      break;
+    case 1:
       delete[] p; // both-note {{'delete' used to delete pointer to object allocated with 'std::allocator<...>::allocate'}}
-    else if (dealloc_kind == 2)
-      std::allocator<int>().deallocate(p); // both-note 2{{in call to}}
-
+      break;
+    case 2:
+      std::allocator<int>().deallocate(p); // both-note 2{{in call}}
+      break;
+    }
     return true;
   }
   static_assert(mismatched(0, 2)); // both-error {{constant expression}} \

``````````

</details>


https://github.com/llvm/llvm-project/pull/107738


More information about the cfe-commits mailing list