Author: kremenek Date: Tue Nov 11 11:10:00 2008 New Revision: 59049 URL: http://llvm.org/viewvc/llvm-project?rev=59049&view=rev Log: 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. 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=59049&r1=59048&r2=59049&view=diff ============================================================================== --- cfe/trunk/lib/AST/CFG.cpp (original) +++ cfe/trunk/lib/AST/CFG.cpp Tue Nov 11 11:10:00 2008 @@ -103,22 +103,23 @@ // 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 @@ 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::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. _______________________________________________ cfe-commits mailing list cfe-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits