aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen/CGStmt.cpp
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2009-11-25 01:51:31 +0000
committerDouglas Gregor <dgregor@apple.com>2009-11-25 01:51:31 +0000
commitd975206755e26a391f4a1cd8bf8f96a6a65b05e6 (patch)
treed65df4dcd98b71a273d9062976f768364540d1f8 /lib/CodeGen/CGStmt.cpp
parent772250ca0b15f9ba74e5cb97773815d3d3beffa4 (diff)
Implement proper cleanup semantics for condition variables in for
statements, e.g., for(; X x = X(); ) { ... } Daniel or Anders, please review! git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@89832 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CGStmt.cpp')
-rw-r--r--lib/CodeGen/CGStmt.cpp45
1 files changed, 34 insertions, 11 deletions
diff --git a/lib/CodeGen/CGStmt.cpp b/lib/CodeGen/CGStmt.cpp
index be571fac71..bbd5462618 100644
--- a/lib/CodeGen/CGStmt.cpp
+++ b/lib/CodeGen/CGStmt.cpp
@@ -488,27 +488,34 @@ void CodeGenFunction::EmitForStmt(const ForStmt &S) {
// Start the loop with a block that tests the condition.
llvm::BasicBlock *CondBlock = createBasicBlock("for.cond");
llvm::BasicBlock *AfterFor = createBasicBlock("for.end");
-
+ llvm::BasicBlock *IncBlock = 0;
+ llvm::BasicBlock *CondCleanup = 0;
+ llvm::BasicBlock *EffectiveExitBlock = AfterFor;
EmitBlock(CondBlock);
- // Create a cleanup scope
+ // Create a cleanup scope for the condition variable cleanups.
CleanupScope ConditionScope(*this);
- // Evaluate the condition if present. If not, treat it as a
- // non-zero-constant according to 6.8.5.3p2, aka, true.
+ llvm::Value *BoolCondVal = 0;
if (S.getCond()) {
// If the for statement has a condition scope, emit the local variable
// declaration.
- // FIXME: The cleanup points for this are all wrong.
- if (S.getConditionVariable())
+ if (S.getConditionVariable()) {
EmitLocalBlockVarDecl(*S.getConditionVariable());
+
+ if (ConditionScope.requiresCleanups()) {
+ CondCleanup = createBasicBlock("for.cond.cleanup");
+ EffectiveExitBlock = CondCleanup;
+ }
+ }
// As long as the condition is true, iterate the loop.
llvm::BasicBlock *ForBody = createBasicBlock("for.body");
// C99 6.8.5p2/p4: The first substatement is executed if the expression
// compares unequal to 0. The condition must be a scalar type.
- EmitBranchOnBoolExpr(S.getCond(), ForBody, AfterFor);
+ BoolCondVal = EvaluateExprAsBool(S.getCond());
+ Builder.CreateCondBr(BoolCondVal, ForBody, EffectiveExitBlock);
EmitBlock(ForBody);
} else {
@@ -520,7 +527,7 @@ void CodeGenFunction::EmitForStmt(const ForStmt &S) {
// condition as the continue block.
llvm::BasicBlock *ContinueBlock;
if (S.getInc())
- ContinueBlock = createBasicBlock("for.inc");
+ ContinueBlock = IncBlock = createBasicBlock("for.inc");
else
ContinueBlock = CondBlock;
@@ -533,18 +540,34 @@ void CodeGenFunction::EmitForStmt(const ForStmt &S) {
DI->setLocation(S.getSourceRange().getBegin());
DI->EmitRegionStart(CurFn, Builder);
}
- EmitStmt(S.getBody());
+
+ {
+ // Create a separate cleanup scope for the body, in case it is not
+ // a compound statement.
+ CleanupScope BodyScope(*this);
+ EmitStmt(S.getBody());
+ }
BreakContinueStack.pop_back();
// If there is an increment, emit it next.
if (S.getInc()) {
- EmitBlock(ContinueBlock);
+ EmitBlock(IncBlock);
EmitStmt(S.getInc());
}
// Finally, branch back up to the condition for the next iteration.
- EmitBranch(CondBlock);
+ if (CondCleanup) {
+ // Branch to the cleanup block.
+ EmitBranch(CondCleanup);
+
+ // Emit the cleanup block, which branches back to the loop body or
+ // outside of the for statement once it is done.
+ EmitBlock(CondCleanup);
+ ConditionScope.ForceCleanup();
+ Builder.CreateCondBr(BoolCondVal, CondBlock, AfterFor);
+ } else
+ EmitBranch(CondBlock);
if (DI) {
DI->setLocation(S.getSourceRange().getEnd());
DI->EmitRegionEnd(CurFn, Builder);