]> granicus.if.org Git - clang/commitdiff
Added support for do..while loops in CFG construction.
authorTed Kremenek <kremenek@apple.com>
Thu, 23 Aug 2007 17:15:32 +0000 (17:15 +0000)
committerTed Kremenek <kremenek@apple.com>
Thu, 23 Aug 2007 17:15:32 +0000 (17:15 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@41325 91177308-0d34-0410-b5e6-96231b3b80d8

AST/CFG.cpp

index d21d9c752d7e10558842a4025ab4dba2a55fbf47..162b34c4233f7178a962387d13f332812993062a 100644 (file)
@@ -441,6 +441,67 @@ public:
     return ConditionBlock;
   }
   
+  CFGBlock* VisitDoStmt(DoStmt* D) {
+    // "do...while" is a control-flow statement.  Thus we stop processing the
+    // current block.
+    
+    CFGBlock* LoopSuccessor = NULL;
+    
+    if (Block) {
+      FinishBlock(Block);
+      LoopSuccessor = Block;
+    }
+    else LoopSuccessor = Succ;
+    
+    // Create the condition block.
+    CFGBlock* ConditionBlock = createBlock(false);
+    ConditionBlock->setTerminator(D);
+    if (Stmt* C = D->getCond()) ConditionBlock->appendStmt(C);        
+    
+    // The condition block is the implicit successor for the loop body.
+    Succ = ConditionBlock;
+    
+    CFGBlock* BodyBlock = NULL;
+    // Process the loop body.
+    {
+      assert (D->getBody());
+      
+      // Save the current values for Block, Succ, and continue and break targets
+      SaveAndRestore<CFGBlock*> save_Block(Block), save_Succ(Succ),
+      save_continue(ContinueTargetBlock),
+      save_break(BreakTargetBlock);
+      
+      // All continues within this loop should go to the condition block
+      ContinueTargetBlock = ConditionBlock;
+      
+      // All breaks should go to the code following the loop.
+      BreakTargetBlock = LoopSuccessor;
+      
+      // NULL out Block to force lazy instantiation of blocks for the body.
+      Block = NULL;
+      
+      // Create the body.  The returned block is the entry to the loop body.
+      BodyBlock = Visit(D->getBody());
+      assert (BodyBlock);
+      FinishBlock(BodyBlock);
+      
+      // Add the loop body entry as a successor to the condition.
+      ConditionBlock->addSuccessor(BodyBlock);
+    }
+    
+    // Link up the condition block with the code that follows the loop.
+    // (the false branch).
+    ConditionBlock->addSuccessor(LoopSuccessor);
+    
+    // There can be no more statements in the condition block
+    // since we loop back to this block.  NULL out Block to force
+    // lazy creation of another block.
+    Block = NULL;
+    
+    // Return the loop body, which is the dominating block for the loop.
+    return BodyBlock;
+  }
+  
   CFGBlock* VisitContinueStmt(ContinueStmt* C) {
     // "continue" is a control-flow statement.  Thus we stop processing the
     // current block.
@@ -567,6 +628,12 @@ namespace {
       OS << "while " ;
       if (Stmt* C = W->getCond()) C->printPretty(OS);
       OS << "\n";
+    }
+    
+    void VisitDoStmt(DoStmt* D) {
+      OS << "do ... while ";
+      if (Stmt* C = D->getCond()) C->printPretty(OS);
+      OS << "\n";
     }                                                       
   };
 }