[cfe-commits] r59049 - /cfe/trunk/lib/AST/CFG.cpp

Ted Kremenek kremenek at apple.com
Tue Nov 11 09:10:05 PST 2008


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.





More information about the cfe-commits mailing list