[clang] 60b3cc6 - [CodeGen] Fix cleanup attribute for C89 for-loop init variables (#156643)

via cfe-commits cfe-commits at lists.llvm.org
Tue Sep 23 20:35:46 PDT 2025


Author: Jongmyeong Choi
Date: 2025-09-23T20:35:43-07:00
New Revision: 60b3cc69af52fa4be05cdb1632efdca7266ed823

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

LOG: [CodeGen] Fix cleanup attribute for C89 for-loop init variables (#156643)

In C89, for-init variables have function scope, so cleanup should occur
at function exit, not loop exit. This implements deferred cleanup
registration for C89 mode while preserving C99+ behavior.

Fixes #154624

Added: 
    

Modified: 
    clang/lib/CodeGen/CGStmt.cpp
    clang/test/CodeGen/attr-cleanup.c

Removed: 
    


################################################################################
diff  --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp
index aeff73d525c10..440100650c43f 100644
--- a/clang/lib/CodeGen/CGStmt.cpp
+++ b/clang/lib/CodeGen/CGStmt.cpp
@@ -1291,7 +1291,9 @@ void CodeGenFunction::EmitForStmt(const ForStmt &S,
                                   ArrayRef<const Attr *> ForAttrs) {
   JumpDest LoopExit = getJumpDestInCurrentScope("for.end");
 
-  LexicalScope ForScope(*this, S.getSourceRange());
+  std::optional<LexicalScope> ForScope;
+  if (getLangOpts().C99 || getLangOpts().CPlusPlus)
+    ForScope.emplace(*this, S.getSourceRange());
 
   // Evaluate the first part before the loop.
   if (S.getInit())
@@ -1350,7 +1352,7 @@ void CodeGenFunction::EmitForStmt(const ForStmt &S,
     llvm::BasicBlock *ExitBlock = LoopExit.getBlock();
     // If there are any cleanups between here and the loop-exit scope,
     // create a block to stage a loop exit along.
-    if (ForScope.requiresCleanups())
+    if (ForScope && ForScope->requiresCleanups())
       ExitBlock = createBasicBlock("for.cond.cleanup");
 
     // As long as the condition is true, iterate the loop.
@@ -1419,7 +1421,8 @@ void CodeGenFunction::EmitForStmt(const ForStmt &S,
   EmitStopPoint(&S);
   EmitBranch(CondBlock);
 
-  ForScope.ForceCleanup();
+  if (ForScope)
+    ForScope->ForceCleanup();
 
   LoopStack.pop();
 

diff  --git a/clang/test/CodeGen/attr-cleanup.c b/clang/test/CodeGen/attr-cleanup.c
index 755ede86c1382..05723a8ab60ab 100644
--- a/clang/test/CodeGen/attr-cleanup.c
+++ b/clang/test/CodeGen/attr-cleanup.c
@@ -1,7 +1,27 @@
-// RUN: %clang_cc1 -emit-llvm %s -o %t
+// RUN: %clang_cc1 -std=c89 -emit-llvm %s -o - | FileCheck %s --check-prefix=C89
+// RUN: %clang_cc1 -std=c99 -emit-llvm %s -o - | FileCheck %s --check-prefix=C99
 
 void f(void* arg);
 void g(void) {
   __attribute__((cleanup(f))) void *g;
 }
 
+void cleaner(int *p);
+
+// C89-LABEL: define{{.*}} void @test_nested_for_loop_cleanup()
+// C99-LABEL: define{{.*}} void @test_nested_for_loop_cleanup()
+void test_nested_for_loop_cleanup(void) {
+  for (int i = 10; 0;) {
+    for (__attribute__((cleanup(cleaner))) int j = 20; 0;)
+      ;
+    i = 5; // Some operation after inner loop
+  }
+}
+
+// C89: for.end:
+// C89-NEXT: store i32 5, ptr %i, align 4
+// C89-NEXT: call void @cleaner(ptr noundef %j)
+
+// C99: for.cond.cleanup:
+// C99-NEXT: call void @cleaner(ptr noundef %j)
+// C99-NEXT: br label %for.end


        


More information about the cfe-commits mailing list