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 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
