Add CFG support for Objective-C 2.0 fast enumeration 'for' statement:

http://developer.apple.com/documentation/Cocoa/Conceptual/ObjectiveC/Articles/chapter_7_section_2.html#//apple_ref/doc/uid/TP30001163-CH18-SW3

Need to modify GRExprEngine, LiveVariables, and UninitializedValues to understand this construct.

llvm-svn: 59049
This commit is contained in:
Ted Kremenek 2008-11-11 17:10:00 +00:00
parent 90cf22e013
commit 9d56e64543
1 changed files with 77 additions and 13 deletions

View File

@ -103,22 +103,23 @@ public:
// Visitors to walk an AST and construct the CFG. Called by
// buildCFG. Do not call directly!
CFGBlock* VisitStmt(Stmt* Statement);
CFGBlock* VisitNullStmt(NullStmt* Statement);
CFGBlock* VisitCompoundStmt(CompoundStmt* C);
CFGBlock* VisitIfStmt(IfStmt* I);
CFGBlock* VisitReturnStmt(ReturnStmt* R);
CFGBlock* VisitLabelStmt(LabelStmt* L);
CFGBlock* VisitGotoStmt(GotoStmt* G);
CFGBlock* VisitForStmt(ForStmt* F);
CFGBlock* VisitWhileStmt(WhileStmt* W);
CFGBlock* VisitDoStmt(DoStmt* D);
CFGBlock* VisitContinueStmt(ContinueStmt* C);
CFGBlock* VisitBreakStmt(BreakStmt* B);
CFGBlock* VisitSwitchStmt(SwitchStmt* Terminator);
CFGBlock* VisitCaseStmt(CaseStmt* Terminator);
CFGBlock* VisitCompoundStmt(CompoundStmt* C);
CFGBlock* VisitContinueStmt(ContinueStmt* C);
CFGBlock* VisitDefaultStmt(DefaultStmt* D);
CFGBlock* VisitDoStmt(DoStmt* D);
CFGBlock* VisitForStmt(ForStmt* F);
CFGBlock* VisitGotoStmt(GotoStmt* G);
CFGBlock* VisitIfStmt(IfStmt* I);
CFGBlock* VisitIndirectGotoStmt(IndirectGotoStmt* I);
CFGBlock* VisitLabelStmt(LabelStmt* L);
CFGBlock* VisitNullStmt(NullStmt* Statement);
CFGBlock* VisitObjCForCollectionStmt(ObjCForCollectionStmt* S);
CFGBlock* VisitReturnStmt(ReturnStmt* R);
CFGBlock* VisitStmt(Stmt* Statement);
CFGBlock* VisitSwitchStmt(SwitchStmt* Terminator);
CFGBlock* VisitWhileStmt(WhileStmt* W);
// FIXME: Add support for ObjC-specific control-flow structures.
@ -128,7 +129,6 @@ public:
return Block;
}
CFGBlock* VisitObjCForCollectionStmt(ObjCForCollectionStmt* S){ return NYS();}
CFGBlock* VisitObjCAtTryStmt(ObjCAtTryStmt* S) { return NYS(); }
CFGBlock* VisitObjCAtCatchStmt(ObjCAtCatchStmt* S) { return NYS(); }
CFGBlock* VisitObjCAtFinallyStmt(ObjCAtFinallyStmt* S) { return NYS(); }
@ -798,6 +798,70 @@ CFGBlock* CFGBuilder::VisitForStmt(ForStmt* F) {
}
}
CFGBlock* CFGBuilder::VisitObjCForCollectionStmt(ObjCForCollectionStmt* S) {
// Objective-C fast enumeration 'for' statements:
// http://developer.apple.com/documentation/Cocoa/Conceptual/ObjectiveC
//
// for ( Type newVariable in collection_expression ) { statements }
//
// becomes:
//
// prologue:
// 1. collection_expression
// T. jump to loop_entry
// loop_entry:
// 1. ObjCForCollectionStmt [performs binding to newVariable]
// T. ObjCForCollectionStmt TB, FB [jumps to TB if newVariable != nil]
// TB:
// statements
// T. jump to loop_entry
// FB:
// what comes after
//
// and
//
// Type existingItem;
// for ( existingItem in expression ) { statements }
//
// becomes:
//
// the same with newVariable replaced with existingItem; the binding
// works the same except that for one ObjCForCollectionStmt::getElement()
// returns a DeclStmt and the other returns a DeclRefExpr.
//
CFGBlock* LoopSuccessor = 0;
if (Block) {
FinishBlock(Block);
LoopSuccessor = Block;
Block = 0;
}
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
// Now create the true branch.
Succ = ConditionBlock;
CFGBlock* BodyBlock = addStmt(S->getBody());
FinishBlock(BodyBlock);
// Connect up the condition block
ConditionBlock->addSuccessor(Block);
ConditionBlock->addSuccessor(LoopSuccessor);
// Now create a prologue block to contain the collection expression.
Block = 0;
Succ = ConditionBlock;
return addStmt(S->getCollection());
}
CFGBlock* CFGBuilder::VisitWhileStmt(WhileStmt* W) {
// "while" is a control-flow statement. Thus we stop processing the
// current block.