https://github.com/jongmyeong-choi updated https://github.com/llvm/llvm-project/pull/156643
>From 471273e66583dbec3f145c7f5723a4d5b524d15b Mon Sep 17 00:00:00 2001 From: Jongmyeong Choi <cheesec...@gmail.com> Date: Wed, 3 Sep 2025 18:41:46 +0900 Subject: [PATCH 1/4] [CodeGen] Fix cleanup attribute for C89 for-loop init variables 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 --- clang/lib/CodeGen/CGDecl.cpp | 32 ++++++++++++++++++++++++--- clang/lib/CodeGen/CodeGenFunction.cpp | 6 ++++- clang/lib/CodeGen/CodeGenFunction.h | 22 ++++++++++++++++++ clang/test/CodeGen/attr-cleanup.c | 25 +++++++++++++++++++++ 4 files changed, 81 insertions(+), 4 deletions(-) diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp index 8a1675848e13c..e4a691a161026 100644 --- a/clang/lib/CodeGen/CGDecl.cpp +++ b/clang/lib/CodeGen/CGDecl.cpp @@ -2230,9 +2230,16 @@ void CodeGenFunction::EmitAutoVarCleanups(const AutoVarEmission &emission) { llvm::Constant *F = CGM.GetAddrOfFunction(FD); assert(F && "Could not find function!"); - const CGFunctionInfo &Info = CGM.getTypes().arrangeFunctionDeclaration(FD); - EHStack.pushCleanup<CallCleanupFunction>(NormalAndEHCleanup, F, &Info, &D, - CA); + // Check if we're in C89 mode and should defer cleanup to function scope + bool isC89Mode = !getLangOpts().C99 && !getLangOpts().CPlusPlus; + if (isC89Mode) { + const CGFunctionInfo &Info = CGM.getTypes().arrangeFunctionDeclaration(FD); + addDeferredFunctionCleanup(F, &Info, &D, CA); + } else { + const CGFunctionInfo &Info = CGM.getTypes().arrangeFunctionDeclaration(FD); + EHStack.pushCleanup<CallCleanupFunction>(NormalAndEHCleanup, F, &Info, &D, + CA); + } } // If this is a block variable, call _Block_object_destroy @@ -2963,3 +2970,22 @@ CodeGenModule::getOMPAllocateAlignment(const VarDecl *VD) { } return std::nullopt; } + +void CodeGenFunction::addDeferredFunctionCleanup(llvm::Constant *F, + const CGFunctionInfo *Info, + const VarDecl *Var, + const CleanupAttr *Attribute) { + DeferredFunctionCleanups.emplace_back(F, Info, Var, Attribute); +} + +void CodeGenFunction::processDeferredFunctionCleanups() { + // Process all deferred cleanups at function exit + for (const auto &cleanup : DeferredFunctionCleanups) { + EHStack.pushCleanup<CallCleanupFunction>(NormalAndEHCleanup, + cleanup.CleanupFn, + cleanup.FnInfo, + cleanup.Var, + cleanup.Attribute); + } + DeferredFunctionCleanups.clear(); +} diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index 652fe672f15e3..0ea33af47343a 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -405,6 +405,10 @@ 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. + + // Process deferred function cleanups before checking for regular cleanups + processDeferredFunctionCleanups(); + bool HasCleanups = EHStack.stable_begin() != PrologueCleanupDepth; bool HasOnlyNoopCleanups = HasCleanups && EHStack.containsOnlyNoopCleanups(PrologueCleanupDepth); @@ -422,7 +426,7 @@ void CodeGenFunction::FinishFunction(SourceLocation EndLoc) { // fall back to an artificial location if needed. OAL = ApplyDebugLocation::CreateDefaultArtificial(*this, EndLoc); } - + PopCleanupBlocks(PrologueCleanupDepth); } diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index fc65199a0f154..19ea1e7e34052 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -392,6 +392,21 @@ class CodeGenFunction : public CodeGenTypeCache { /// cleanups associated with the parameters. EHScopeStack::stable_iterator PrologueCleanupDepth; + /// Structure for deferred function-level cleanups (e.g., C89 for-init cleanup variables) + struct DeferredCleanupInfo { + llvm::Constant *CleanupFn; + const CGFunctionInfo *FnInfo; + const VarDecl *Var; + const CleanupAttr *Attribute; + + DeferredCleanupInfo(llvm::Constant *F, const CGFunctionInfo *Info, + const VarDecl *V, const CleanupAttr *A) + : CleanupFn(F), FnInfo(Info), Var(V), Attribute(A) {} + }; + + /// List of cleanups that should be registered at function exit instead of current scope + SmallVector<DeferredCleanupInfo, 4> DeferredFunctionCleanups; + /// ReturnBlock - Unified return block. JumpDest ReturnBlock; @@ -3470,6 +3485,13 @@ class CodeGenFunction : public CodeGenTypeCache { void EmitAutoVarCleanups(const AutoVarEmission &emission); void emitAutoVarTypeCleanup(const AutoVarEmission &emission, QualType::DestructionKind dtorKind); + + /// Add a cleanup to be deferred until function exit (for C89 for-init variables) + void addDeferredFunctionCleanup(llvm::Constant *CleanupFn, const CGFunctionInfo *FnInfo, + const VarDecl *Var, const CleanupAttr *Attribute); + + /// Process all deferred function-level cleanups + void processDeferredFunctionCleanups(); void MaybeEmitDeferredVarDeclInit(const VarDecl *var); diff --git a/clang/test/CodeGen/attr-cleanup.c b/clang/test/CodeGen/attr-cleanup.c index 755ede86c1382..c723014973332 100644 --- a/clang/test/CodeGen/attr-cleanup.c +++ b/clang/test/CodeGen/attr-cleanup.c @@ -5,3 +5,28 @@ 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_for_loop_cleanup() +// C99-LABEL: define{{.*}} void @test_for_loop_cleanup() +void test_for_loop_cleanup(void) { + for (__attribute__((cleanup(cleaner))) int i = 42; 0;) + ; + +#ifndef __STDC_VERSION__ + if (i > 40) { + // do something + } +#endif +} + +// C89: if.end: +// C89-NEXT: call void @cleaner(ptr noundef %i) +// C89-NEXT: ret void + +// C99: for.cond.cleanup: +// C99-NEXT: call void @cleaner(ptr noundef %i) >From adb3506d9ed67ae9f04a4fadcfa8bfab77e74836 Mon Sep 17 00:00:00 2001 From: Jongmyeong Choi <cheesec...@gmail.com> Date: Wed, 3 Sep 2025 20:42:38 +0900 Subject: [PATCH 2/4] Apply clang-format to fix code style --- clang/lib/CodeGen/CGDecl.cpp | 14 +++++++------- clang/lib/CodeGen/CodeGenFunction.cpp | 6 +++--- clang/lib/CodeGen/CodeGenFunction.h | 27 ++++++++++++++++----------- 3 files changed, 26 insertions(+), 21 deletions(-) diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp index e4a691a161026..193d82d6b1486 100644 --- a/clang/lib/CodeGen/CGDecl.cpp +++ b/clang/lib/CodeGen/CGDecl.cpp @@ -2233,10 +2233,12 @@ void CodeGenFunction::EmitAutoVarCleanups(const AutoVarEmission &emission) { // Check if we're in C89 mode and should defer cleanup to function scope bool isC89Mode = !getLangOpts().C99 && !getLangOpts().CPlusPlus; if (isC89Mode) { - const CGFunctionInfo &Info = CGM.getTypes().arrangeFunctionDeclaration(FD); + const CGFunctionInfo &Info = + CGM.getTypes().arrangeFunctionDeclaration(FD); addDeferredFunctionCleanup(F, &Info, &D, CA); } else { - const CGFunctionInfo &Info = CGM.getTypes().arrangeFunctionDeclaration(FD); + const CGFunctionInfo &Info = + CGM.getTypes().arrangeFunctionDeclaration(FD); EHStack.pushCleanup<CallCleanupFunction>(NormalAndEHCleanup, F, &Info, &D, CA); } @@ -2981,11 +2983,9 @@ void CodeGenFunction::addDeferredFunctionCleanup(llvm::Constant *F, void CodeGenFunction::processDeferredFunctionCleanups() { // Process all deferred cleanups at function exit for (const auto &cleanup : DeferredFunctionCleanups) { - EHStack.pushCleanup<CallCleanupFunction>(NormalAndEHCleanup, - cleanup.CleanupFn, - cleanup.FnInfo, - cleanup.Var, - cleanup.Attribute); + EHStack.pushCleanup<CallCleanupFunction>(NormalAndEHCleanup, + cleanup.CleanupFn, cleanup.FnInfo, + cleanup.Var, cleanup.Attribute); } DeferredFunctionCleanups.clear(); } diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index 0ea33af47343a..0bb08e81a6be8 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -405,10 +405,10 @@ 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. - + // Process deferred function cleanups before checking for regular cleanups processDeferredFunctionCleanups(); - + bool HasCleanups = EHStack.stable_begin() != PrologueCleanupDepth; bool HasOnlyNoopCleanups = HasCleanups && EHStack.containsOnlyNoopCleanups(PrologueCleanupDepth); @@ -426,7 +426,7 @@ void CodeGenFunction::FinishFunction(SourceLocation EndLoc) { // fall back to an artificial location if needed. OAL = ApplyDebugLocation::CreateDefaultArtificial(*this, EndLoc); } - + PopCleanupBlocks(PrologueCleanupDepth); } diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 19ea1e7e34052..2fb7a44d3ae10 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -392,19 +392,21 @@ class CodeGenFunction : public CodeGenTypeCache { /// cleanups associated with the parameters. EHScopeStack::stable_iterator PrologueCleanupDepth; - /// Structure for deferred function-level cleanups (e.g., C89 for-init cleanup variables) + /// Structure for deferred function-level cleanups + /// (e.g., C89 for-init cleanup variables) struct DeferredCleanupInfo { llvm::Constant *CleanupFn; const CGFunctionInfo *FnInfo; const VarDecl *Var; const CleanupAttr *Attribute; - - DeferredCleanupInfo(llvm::Constant *F, const CGFunctionInfo *Info, + + DeferredCleanupInfo(llvm::Constant *F, const CGFunctionInfo *Info, const VarDecl *V, const CleanupAttr *A) - : CleanupFn(F), FnInfo(Info), Var(V), Attribute(A) {} + : CleanupFn(F), FnInfo(Info), Var(V), Attribute(A) {} }; - - /// List of cleanups that should be registered at function exit instead of current scope + + /// List of cleanups that should be registered at function exit instead of + /// current scope SmallVector<DeferredCleanupInfo, 4> DeferredFunctionCleanups; /// ReturnBlock - Unified return block. @@ -3485,11 +3487,14 @@ class CodeGenFunction : public CodeGenTypeCache { void EmitAutoVarCleanups(const AutoVarEmission &emission); void emitAutoVarTypeCleanup(const AutoVarEmission &emission, QualType::DestructionKind dtorKind); - - /// Add a cleanup to be deferred until function exit (for C89 for-init variables) - void addDeferredFunctionCleanup(llvm::Constant *CleanupFn, const CGFunctionInfo *FnInfo, - const VarDecl *Var, const CleanupAttr *Attribute); - + + /// Add a cleanup to be deferred until function exit + /// (for C89 for-init variables) + void addDeferredFunctionCleanup(llvm::Constant *CleanupFn, + const CGFunctionInfo *FnInfo, + const VarDecl *Var, + const CleanupAttr *Attribute); + /// Process all deferred function-level cleanups void processDeferredFunctionCleanups(); >From 6fa50708a12b2e5d63c7a0bef1225b9b3a9c48cf Mon Sep 17 00:00:00 2001 From: Jongmyeong Choi <cheesec...@gmail.com> Date: Sat, 6 Sep 2025 07:36:08 +0900 Subject: [PATCH 3/4] Fix cleanup attribute scope for C89 for-loop variables Move processDeferredFunctionCleanups() to EmitForStmt to ensure cleanup happens at correct scope boundary for C89 for-loop init variables. --- clang/lib/CodeGen/CGStmt.cpp | 3 +++ clang/lib/CodeGen/CodeGenFunction.cpp | 3 --- clang/test/CodeGen/attr-cleanup.c | 27 ++++++++++++++------------- 3 files changed, 17 insertions(+), 16 deletions(-) diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp index 031ef73214e76..f30d6601a58cb 100644 --- a/clang/lib/CodeGen/CGStmt.cpp +++ b/clang/lib/CodeGen/CGStmt.cpp @@ -1421,6 +1421,9 @@ void CodeGenFunction::EmitForStmt(const ForStmt &S, ForScope.ForceCleanup(); + // Process deferred function cleanups before checking for regular cleanups + processDeferredFunctionCleanups(); + LoopStack.pop(); // Emit the fall-through block. diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index 0bb08e81a6be8..d3455d13eb21b 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -406,9 +406,6 @@ void CodeGenFunction::FinishFunction(SourceLocation EndLoc) { // important to do this before we enter the return block or return // edges will be *really* confused. - // Process deferred function cleanups before checking for regular cleanups - processDeferredFunctionCleanups(); - 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 c723014973332..c0d9e97927446 100644 --- a/clang/test/CodeGen/attr-cleanup.c +++ b/clang/test/CodeGen/attr-cleanup.c @@ -11,22 +11,23 @@ void g(void) { void cleaner(int *p); -// C89-LABEL: define{{.*}} void @test_for_loop_cleanup() -// C99-LABEL: define{{.*}} void @test_for_loop_cleanup() -void test_for_loop_cleanup(void) { - for (__attribute__((cleanup(cleaner))) int i = 42; 0;) - ; - +// 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;) + ; + #ifndef __STDC_VERSION__ - if (i > 40) { - // do something - } + if (j > 15) { + // do something with inner variable + } #endif + } } // C89: if.end: -// C89-NEXT: call void @cleaner(ptr noundef %i) -// C89-NEXT: ret void +// C89-NEXT: call void @cleaner(ptr noundef %j) -// C99: for.cond.cleanup: -// C99-NEXT: call void @cleaner(ptr noundef %i) +// C99: for.cond.cleanup{{[0-9]*}}: +// C99-NEXT: call void @cleaner(ptr noundef %j) >From 2c821c58976903dadaf6fb84e74e8caf998e49f9 Mon Sep 17 00:00:00 2001 From: Jongmyeong Choi <cheesec...@gmail.com> Date: Mon, 8 Sep 2025 21:31:55 +0900 Subject: [PATCH 4/4] Skip creating ForScope for C89 for-loops Address review feedback: instead of special cleanup handling, conditionally create LexicalScope only for C99/C++ where for-init variables have loop scope. --- clang/lib/CodeGen/CGDecl.cpp | 31 +++-------------------------- clang/lib/CodeGen/CGStmt.cpp | 14 ++++++++----- clang/lib/CodeGen/CodeGenFunction.h | 25 ----------------------- clang/test/CodeGen/attr-cleanup.c | 13 +++++------- 4 files changed, 17 insertions(+), 66 deletions(-) diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp index 193d82d6b1486..d93417aa9e48e 100644 --- a/clang/lib/CodeGen/CGDecl.cpp +++ b/clang/lib/CodeGen/CGDecl.cpp @@ -2230,18 +2230,9 @@ void CodeGenFunction::EmitAutoVarCleanups(const AutoVarEmission &emission) { llvm::Constant *F = CGM.GetAddrOfFunction(FD); assert(F && "Could not find function!"); - // Check if we're in C89 mode and should defer cleanup to function scope - bool isC89Mode = !getLangOpts().C99 && !getLangOpts().CPlusPlus; - if (isC89Mode) { - const CGFunctionInfo &Info = - CGM.getTypes().arrangeFunctionDeclaration(FD); - addDeferredFunctionCleanup(F, &Info, &D, CA); - } else { - const CGFunctionInfo &Info = - CGM.getTypes().arrangeFunctionDeclaration(FD); - EHStack.pushCleanup<CallCleanupFunction>(NormalAndEHCleanup, F, &Info, &D, - CA); - } + const CGFunctionInfo &Info = CGM.getTypes().arrangeFunctionDeclaration(FD); + EHStack.pushCleanup<CallCleanupFunction>(NormalAndEHCleanup, F, &Info, &D, + CA); } // If this is a block variable, call _Block_object_destroy @@ -2973,19 +2964,3 @@ CodeGenModule::getOMPAllocateAlignment(const VarDecl *VD) { return std::nullopt; } -void CodeGenFunction::addDeferredFunctionCleanup(llvm::Constant *F, - const CGFunctionInfo *Info, - const VarDecl *Var, - const CleanupAttr *Attribute) { - DeferredFunctionCleanups.emplace_back(F, Info, Var, Attribute); -} - -void CodeGenFunction::processDeferredFunctionCleanups() { - // Process all deferred cleanups at function exit - for (const auto &cleanup : DeferredFunctionCleanups) { - EHStack.pushCleanup<CallCleanupFunction>(NormalAndEHCleanup, - cleanup.CleanupFn, cleanup.FnInfo, - cleanup.Var, cleanup.Attribute); - } - DeferredFunctionCleanups.clear(); -} diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp index f30d6601a58cb..dbceaf25ce82d 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(); // Process deferred function cleanups before checking for regular cleanups processDeferredFunctionCleanups(); @@ -1475,7 +1478,7 @@ CodeGenFunction::EmitCXXForRangeStmt(const CXXForRangeStmt &S, // If there are any cleanups between here and the loop-exit scope, // create a block to stage a loop exit along. llvm::BasicBlock *ExitBlock = LoopExit.getBlock(); - if (ForScope.requiresCleanups()) + if (ForScope && ForScope->requiresCleanups()) ExitBlock = createBasicBlock("for.cond.cleanup"); // The loop body, consisting of the specified body and the loop variable. @@ -1534,7 +1537,8 @@ CodeGenFunction::EmitCXXForRangeStmt(const CXXForRangeStmt &S, EmitBranch(CondBlock); - ForScope.ForceCleanup(); + if (ForScope) + ForScope->ForceCleanup(); LoopStack.pop(); diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 2fb7a44d3ae10..f6cc69b7cd065 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -392,22 +392,6 @@ class CodeGenFunction : public CodeGenTypeCache { /// cleanups associated with the parameters. EHScopeStack::stable_iterator PrologueCleanupDepth; - /// Structure for deferred function-level cleanups - /// (e.g., C89 for-init cleanup variables) - struct DeferredCleanupInfo { - llvm::Constant *CleanupFn; - const CGFunctionInfo *FnInfo; - const VarDecl *Var; - const CleanupAttr *Attribute; - - DeferredCleanupInfo(llvm::Constant *F, const CGFunctionInfo *Info, - const VarDecl *V, const CleanupAttr *A) - : CleanupFn(F), FnInfo(Info), Var(V), Attribute(A) {} - }; - - /// List of cleanups that should be registered at function exit instead of - /// current scope - SmallVector<DeferredCleanupInfo, 4> DeferredFunctionCleanups; /// ReturnBlock - Unified return block. JumpDest ReturnBlock; @@ -3488,15 +3472,6 @@ class CodeGenFunction : public CodeGenTypeCache { void emitAutoVarTypeCleanup(const AutoVarEmission &emission, QualType::DestructionKind dtorKind); - /// Add a cleanup to be deferred until function exit - /// (for C89 for-init variables) - void addDeferredFunctionCleanup(llvm::Constant *CleanupFn, - const CGFunctionInfo *FnInfo, - const VarDecl *Var, - const CleanupAttr *Attribute); - - /// Process all deferred function-level cleanups - void processDeferredFunctionCleanups(); void MaybeEmitDeferredVarDeclInit(const VarDecl *var); diff --git a/clang/test/CodeGen/attr-cleanup.c b/clang/test/CodeGen/attr-cleanup.c index c0d9e97927446..19c8a9964145a 100644 --- a/clang/test/CodeGen/attr-cleanup.c +++ b/clang/test/CodeGen/attr-cleanup.c @@ -17,17 +17,14 @@ void test_nested_for_loop_cleanup(void) { for (int i = 10; 0;) { for (__attribute__((cleanup(cleaner))) int j = 20; 0;) ; - -#ifndef __STDC_VERSION__ - if (j > 15) { - // do something with inner variable - } -#endif + i = 5; // Some operation after inner loop } } -// C89: if.end: +// C89: for.end: +// C89-NEXT: store i32 5, ptr %i, align 4 // C89-NEXT: call void @cleaner(ptr noundef %j) -// C99: for.cond.cleanup{{[0-9]*}}: +// C99: for.cond.cleanup: // C99-NEXT: call void @cleaner(ptr noundef %j) +// C99-NEXT: br label %for.end _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits