[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