diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp index 031ef73214e76..74813761f93ca 100644 --- a/clang/lib/CodeGen/CGStmt.cpp +++ b/clang/lib/CodeGen/CGStmt.cpp @@ -1291,7 +1291,9 @@ void CodeGenFunction::EmitForStmt(const ForStmt &S, ArrayRef ForAttrs) { JumpDest LoopExit = getJumpDestInCurrentScope("for.end"); - LexicalScope ForScope(*this, S.getSourceRange()); + std::optional 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/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index 652fe672f15e3..d3455d13eb21b 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -405,6 +405,7 @@ void CodeGenFunction::FinishFunction(SourceLocation EndLoc) { // parameters. Do this in whatever block we're currently in; it's // important to do this before we enter the return block or return // edges will be *really* confused. + bool HasCleanups = EHStack.stable_begin() != PrologueCleanupDepth; bool HasOnlyNoopCleanups = HasCleanups && EHStack.containsOnlyNoopCleanups(PrologueCleanupDepth); diff --git a/clang/test/CodeGen/attr-cleanup.c b/clang/test/CodeGen/attr-cleanup.c index 755ede86c1382..19c8a9964145a 100644 --- a/clang/test/CodeGen/attr-cleanup.c +++ b/clang/test/CodeGen/attr-cleanup.c @@ -5,3 +5,26 @@ void g(void) { __attribute__((cleanup(f))) void *g; } +// Test for cleanup in for-loop initialization (PR #154624) +// 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 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