[cfe-commits] r59289 - /cfe/trunk/lib/AST/CFG.cpp
Ted Kremenek
kremenek at apple.com
Thu Nov 13 17:57:41 PST 2008
Author: kremenek
Date: Thu Nov 13 19:57:41 2008
New Revision: 59289
URL: http://llvm.org/viewvc/llvm-project?rev=59289&view=rev
Log:
Fix CFG construction for ObjCForCollectionStmt: 'element' expression can be anything that evaluates to an lvalue
Modified:
cfe/trunk/lib/AST/CFG.cpp
Modified: cfe/trunk/lib/AST/CFG.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/CFG.cpp?rev=59289&r1=59288&r2=59289&view=diff
==============================================================================
--- cfe/trunk/lib/AST/CFG.cpp (original)
+++ cfe/trunk/lib/AST/CFG.cpp Thu Nov 13 19:57:41 2008
@@ -802,6 +802,7 @@
// 1. collection_expression
// T. jump to loop_entry
// loop_entry:
+ // 1. side-effects of element expression
// 1. ObjCForCollectionStmt [performs binding to newVariable]
// T. ObjCForCollectionStmt TB, FB [jumps to TB if newVariable != nil]
// TB:
@@ -831,32 +832,55 @@
}
else LoopSuccessor = Succ;
- // Build the condition block. The condition has no short-circuit evaluation,
- // so we don't need multiple blocks like other control-flow structures with
- // conditions.
- CFGBlock* ConditionBlock = createBlock(false);
- ConditionBlock->appendStmt(S);
- ConditionBlock->setTerminator(S); // No need to call FinishBlock; 1 stmt
+ // Build the condition blocks.
+ CFGBlock* ExitConditionBlock = createBlock(false);
+ CFGBlock* EntryConditionBlock = ExitConditionBlock;
+
+ // Set the terminator for the "exit" condition block.
+ ExitConditionBlock->setTerminator(S);
+
+ // The last statement in the block should be the ObjCForCollectionStmt,
+ // which performs the actual binding to 'element' and determines if there
+ // are any more items in the collection.
+ ExitConditionBlock->appendStmt(S);
+ Block = ExitConditionBlock;
+
+ // Walk the 'element' expression to see if there are any side-effects. We
+ // generate new blocks as necesary. We DON'T add the statement by default
+ // to the CFG unless it contains control-flow.
+ EntryConditionBlock = WalkAST(S->getElement(), false);
+ if (Block) { FinishBlock(EntryConditionBlock); Block = 0; }
+
+ // The condition block is the implicit successor for the loop body as
+ // well as any code above the loop.
+ Succ = EntryConditionBlock;
// Now create the true branch.
- // Save the current values for the continue and break targets
- SaveAndRestore<CFGBlock*> save_continue(ContinueTargetBlock),
- save_break(BreakTargetBlock);
-
- BreakTargetBlock = LoopSuccessor;
- ContinueTargetBlock = ConditionBlock;
- Succ = ConditionBlock;
-
- CFGBlock* BodyBlock = Visit(S->getBody());
- FinishBlock(BodyBlock);
-
- // Connect up the condition block
- ConditionBlock->addSuccessor(BodyBlock);
- ConditionBlock->addSuccessor(LoopSuccessor);
+ {
+ // Save the current values for Succ, continue and break targets.
+ SaveAndRestore<CFGBlock*> save_Succ(Succ),
+ save_continue(ContinueTargetBlock), save_break(BreakTargetBlock);
+
+ BreakTargetBlock = LoopSuccessor;
+ ContinueTargetBlock = EntryConditionBlock;
+
+ CFGBlock* BodyBlock = Visit(S->getBody());
+
+ if (!BodyBlock)
+ BodyBlock = EntryConditionBlock; // can happen for "for (X in Y) ;"
+ else if (Block)
+ FinishBlock(BodyBlock);
+
+ // This new body block is a successor to our "exit" condition block.
+ ExitConditionBlock->addSuccessor(BodyBlock);
+ }
+ // Link up the condition block with the code that follows the loop.
+ // (the false branch).
+ ExitConditionBlock->addSuccessor(LoopSuccessor);
+
// Now create a prologue block to contain the collection expression.
- Block = 0;
- Succ = ConditionBlock;
+ Block = createBlock();
return addStmt(S->getCollection());
}
More information about the cfe-commits
mailing list