[clang] [CodeGen] Fix cleanup attribute for C89 for-loop init variables (PR #156643)
Jongmyeong Choi via cfe-commits
cfe-commits at lists.llvm.org
Mon Sep 8 05:34:54 PDT 2025
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 <cheesechoi at 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 <cheesechoi at 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 <cheesechoi at 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 <cheesechoi at 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
More information about the cfe-commits
mailing list