[cfe-commits] r41337 - /cfe/trunk/AST/CFG.cpp

Ted Kremenek kremenek at apple.com
Thu Aug 23 14:42:29 PDT 2007


Author: kremenek
Date: Thu Aug 23 16:42:29 2007
New Revision: 41337

URL: http://llvm.org/viewvc/llvm-project?rev=41337&view=rev
Log:
No functionality change.  Moved visitor methods for CFGBuilder out-of-line
from the class declaration.  This enables a nice view of what visitor methods
have been implemented.

Modified:
    cfe/trunk/AST/CFG.cpp

Modified: cfe/trunk/AST/CFG.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/AST/CFG.cpp?rev=41337&r1=41336&r2=41337&view=diff

==============================================================================
--- cfe/trunk/AST/CFG.cpp (original)
+++ cfe/trunk/AST/CFG.cpp Thu Aug 23 16:42:29 2007
@@ -74,538 +74,564 @@
   }
   
   ~CFGBuilder() { delete cfg; }
+  
+  // buildCFG - Used by external clients to construct the CFG.
+  CFG* buildCFG(Stmt* Statement);
+  
+  // 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* S);
+  CFGBlock* VisitSwitchCase(SwitchCase* S);
+  
+private:
+  CFGBlock* createBlock(bool add_successor = true);
+  void FinishBlock(CFGBlock* B);
+  
+};
     
-  /// BuildCFG - Constructs a CFG from an AST (a Stmt*).  The AST can
-  ///  represent an arbitrary statement.  Examples include a single expression
-  ///  or a function body (compound statement).  The ownership of the returned
-  ///  CFG is transferred to the caller.  If CFG construction fails, this method
-  ///  returns NULL.
-  CFG* buildCFG(Stmt* Statement) {
-    if (!Statement) return NULL;
-  
-    // Create an empty block that will serve as the exit block for the CFG.
-    // Since this is the first block added to the CFG, it will be implicitly
-    // registered as the exit block.
-    Block = createBlock();
-    assert (Block == &cfg->getExit());
-    
-    // Visit the statements and create the CFG.
-    if (CFGBlock* B = Visit(Statement)) {
-      // Finalize the last constructed block.  This usually involves
-      // reversing the order of the statements in the block.
-      FinishBlock(B);
-      cfg->setEntry(B);
-      
-      // Backpatch the gotos whose label -> block mappings we didn't know
-      // when we encountered them.
-      for (BackpatchBlocksTy::iterator I = BackpatchBlocks.begin(), 
-           E = BackpatchBlocks.end(); I != E; ++I ) {
-       
-        CFGBlock* B = *I;
-        GotoStmt* G = cast<GotoStmt>(B->getTerminator());
-        LabelMapTy::iterator LI = LabelMap.find(G->getLabel());
-
-        // If there is no target for the goto, then we are looking at an
-        // incomplete AST.  Handle this by not registering a successor.
-        if (LI == LabelMap.end()) continue;
-        
-        B->addSuccessor(LI->second);                   
-      }                          
-      
-      // NULL out cfg so that repeated calls
-      CFG* t = cfg;
-      cfg = NULL;
-      return t;
-    }
-    else return NULL;
+/// BuildCFG - Constructs a CFG from an AST (a Stmt*).  The AST can
+///  represent an arbitrary statement.  Examples include a single expression
+///  or a function body (compound statement).  The ownership of the returned
+///  CFG is transferred to the caller.  If CFG construction fails, this method
+///  returns NULL.
+CFG* CFGBuilder::buildCFG(Stmt* Statement) {
+  if (!Statement) return NULL;
+
+  // Create an empty block that will serve as the exit block for the CFG.
+  // Since this is the first block added to the CFG, it will be implicitly
+  // registered as the exit block.
+  Block = createBlock();
+  assert (Block == &cfg->getExit());
+  
+  // Visit the statements and create the CFG.
+  if (CFGBlock* B = Visit(Statement)) {
+    // Finalize the last constructed block.  This usually involves
+    // reversing the order of the statements in the block.
+    FinishBlock(B);
+    cfg->setEntry(B);
+    
+    // Backpatch the gotos whose label -> block mappings we didn't know
+    // when we encountered them.
+    for (BackpatchBlocksTy::iterator I = BackpatchBlocks.begin(), 
+         E = BackpatchBlocks.end(); I != E; ++I ) {
+     
+      CFGBlock* B = *I;
+      GotoStmt* G = cast<GotoStmt>(B->getTerminator());
+      LabelMapTy::iterator LI = LabelMap.find(G->getLabel());
+
+      // If there is no target for the goto, then we are looking at an
+      // incomplete AST.  Handle this by not registering a successor.
+      if (LI == LabelMap.end()) continue;
+      
+      B->addSuccessor(LI->second);                   
+    }                          
+    
+    // NULL out cfg so that repeated calls
+    CFG* t = cfg;
+    cfg = NULL;
+    return t;
   }
+  else return NULL;
+}
   
-  // createBlock - Used to lazily create blocks that are connected
-  //  to the current (global) succcessor.
-  CFGBlock* createBlock( bool add_successor = true ) { 
-    CFGBlock* B = cfg->createBlock(NumBlocks++);
-    if (add_successor && Succ) B->addSuccessor(Succ);
-    return B;
-  }
-  
-  // FinishBlock - When the last statement has been added to the block,
-  //  usually we must reverse the statements because they have been inserted
-  //  in reverse order.  When processing labels, however, there are cases
-  //  in the recursion where we may have already reversed the statements
-  //  in a block.  This method safely tidies up a block: if the block
-  //  has a label at the front, it has already been reversed.  Otherwise,
-  //  we reverse it.
-  void FinishBlock(CFGBlock* B) {
-    assert (B);
-    CFGBlock::iterator I = B->begin();
-    if (I != B->end()) {
-      Stmt* S = *I;
-
-      if (isa<LabelStmt>(S) || isa<SwitchCase>(S))
-        return;
-        
-      B->reverseStmts();
-    }
-  }
+/// createBlock - Used to lazily create blocks that are connected
+///  to the current (global) succcessor.
+CFGBlock* CFGBuilder::createBlock(bool add_successor) { 
+  CFGBlock* B = cfg->createBlock(NumBlocks++);
+  if (add_successor && Succ) B->addSuccessor(Succ);
+  return B;
+}
+  
+/// FinishBlock - When the last statement has been added to the block,
+///  usually we must reverse the statements because they have been inserted
+///  in reverse order.  When processing labels, however, there are cases
+///  in the recursion where we may have already reversed the statements
+///  in a block.  This method safely tidies up a block: if the block
+///  has a label at the front, it has already been reversed.  Otherwise,
+///  we reverse it.
+void CFGBuilder::FinishBlock(CFGBlock* B) {
+  assert (B);
+  CFGBlock::iterator I = B->begin();
+  if (I != B->end()) {
+    Stmt* S = *I;
 
-  /// Here we handle statements with no branching control flow.
-  CFGBlock* VisitStmt(Stmt* Statement) {
-    // We cannot assume that we are in the middle of a basic block, since
-    // the CFG might only be constructed for this single statement.  If
-    // we have no current basic block, just create one lazily.
-    if (!Block) Block = createBlock();
-    
-    // Simply add the statement to the current block.  We actually
-    // insert statements in reverse order; this order is reversed later
-    // when processing the containing element in the AST.
-    Block->appendStmt(Statement);
-    
-    return Block;
+    if (isa<LabelStmt>(S) || isa<SwitchCase>(S))
+      return;
+      
+    B->reverseStmts();
   }
+}
+
+/// VisitStmt - Handle statements with no branching control flow.
+CFGBlock* CFGBuilder::VisitStmt(Stmt* Statement) {
+  // We cannot assume that we are in the middle of a basic block, since
+  // the CFG might only be constructed for this single statement.  If
+  // we have no current basic block, just create one lazily.
+  if (!Block) Block = createBlock();
+  
+  // Simply add the statement to the current block.  We actually
+  // insert statements in reverse order; this order is reversed later
+  // when processing the containing element in the AST.
+  Block->appendStmt(Statement);
   
-  CFGBlock* VisitNullStmt(NullStmt* Statement) {
-    return Block;
-  }
+  return Block;
+}
+
+CFGBlock* CFGBuilder::VisitNullStmt(NullStmt* Statement) {
+  return Block;
+}
+
+CFGBlock* CFGBuilder::VisitCompoundStmt(CompoundStmt* C) {
+  //   The value returned from this function is the last created CFGBlock
+  //   that represents the "entry" point for the translated AST node.
+  CFGBlock* LastBlock;
+  
+  for (CompoundStmt::reverse_body_iterator I = C->body_rbegin(),
+       E = C->body_rend(); I != E; ++I )
+    // Add the statement to the current block.
+    if (!(LastBlock=Visit(*I)))
+      return NULL;
+
+  return LastBlock;
+}
+
+CFGBlock* CFGBuilder::VisitIfStmt(IfStmt* I) {
+  // We may see an if statement in the middle of a basic block, or
+  // it may be the first statement we are processing.  In either case,
+  // we create a new basic block.  First, we create the blocks for
+  // the then...else statements, and then we create the block containing
+  // the if statement.  If we were in the middle of a block, we
+  // stop processing that block and reverse its statements.  That block
+  // is then the implicit successor for the "then" and "else" clauses.
+  
+  // The block we were proccessing is now finished.  Make it the
+  // successor block.
+  if (Block) { 
+    Succ = Block;
+    FinishBlock(Block);
+  }
+  
+  // Process the false branch.  NULL out Block so that the recursive
+  // call to Visit will create a new basic block.
+  // Null out Block so that all successor
+  CFGBlock* ElseBlock = Succ;
   
-  CFGBlock* VisitCompoundStmt(CompoundStmt* C) {
-    //   The value returned from this function is the last created CFGBlock
-    //   that represents the "entry" point for the translated AST node.
-    CFGBlock* LastBlock;
-    
-    for (CompoundStmt::reverse_body_iterator I = C->body_rbegin(),
-         E = C->body_rend(); I != E; ++I )
-      // Add the statement to the current block.
-      if (!(LastBlock=Visit(*I)))
-        return NULL;
-
-    return LastBlock;
-  }
-  
-  CFGBlock* VisitIfStmt(IfStmt* I) {
-  
-    // We may see an if statement in the middle of a basic block, or
-    // it may be the first statement we are processing.  In either case,
-    // we create a new basic block.  First, we create the blocks for
-    // the then...else statements, and then we create the block containing
-    // the if statement.  If we were in the middle of a block, we
-    // stop processing that block and reverse its statements.  That block
-    // is then the implicit successor for the "then" and "else" clauses.
-    
-    // The block we were proccessing is now finished.  Make it the
-    // successor block.
-    if (Block) { 
-      Succ = Block;
-      FinishBlock(Block);
-    }
-    
-    // Process the false branch.  NULL out Block so that the recursive
-    // call to Visit will create a new basic block.
-    // Null out Block so that all successor
-    CFGBlock* ElseBlock = Succ;
+  if (Stmt* Else = I->getElse()) {
+    SaveAndRestore<CFGBlock*> sv(Succ);
     
-    if (Stmt* Else = I->getElse()) {
-      SaveAndRestore<CFGBlock*> sv(Succ);
-      
-      // NULL out Block so that the recursive call to Visit will
-      // create a new basic block.          
-      Block = NULL;
-      ElseBlock = Visit(Else);          
-      if (!ElseBlock) return NULL;
-      FinishBlock(ElseBlock);
-    }
+    // NULL out Block so that the recursive call to Visit will
+    // create a new basic block.          
+    Block = NULL;
+    ElseBlock = Visit(Else);          
+    if (!ElseBlock) return NULL;
+    FinishBlock(ElseBlock);
+  }
+  
+  // Process the true branch.  NULL out Block so that the recursive
+  // call to Visit will create a new basic block.
+  // Null out Block so that all successor
+  CFGBlock* ThenBlock;
+  {
+    Stmt* Then = I->getThen();
+    assert (Then);
+    SaveAndRestore<CFGBlock*> sv(Succ);
+    Block = NULL;        
+    ThenBlock = Visit(Then);        
+    if (!ThenBlock) return NULL;
+    FinishBlock(ThenBlock);
+  }
+
+  // Now create a new block containing the if statement.        
+  Block = createBlock(false);
+
+  // Add the condition as the last statement in the new block.
+  Block->appendStmt(I->getCond());
+  
+  // Set the terminator of the new block to the If statement.
+  Block->setTerminator(I);
+  
+  // Now add the successors.
+  Block->addSuccessor(ThenBlock);
+  Block->addSuccessor(ElseBlock);
+
+  return Block;
+}
     
-    // Process the true branch.  NULL out Block so that the recursive
-    // call to Visit will create a new basic block.
-    // Null out Block so that all successor
-    CFGBlock* ThenBlock;
-    {
-      Stmt* Then = I->getThen();
-      assert (Then);
-      SaveAndRestore<CFGBlock*> sv(Succ);
-      Block = NULL;        
-      ThenBlock = Visit(Then);        
-      if (!ThenBlock) return NULL;
-      FinishBlock(ThenBlock);
-    }
+CFGBlock* CFGBuilder::VisitReturnStmt(ReturnStmt* R) {
+  // If we were in the middle of a block we stop processing that block
+  // and reverse its statements.
+  //
+  // NOTE: If a "return" appears in the middle of a block, this means
+  //       that the code afterwards is DEAD (unreachable).  We still
+  //       keep a basic block for that code; a simple "mark-and-sweep"
+  //       from the entry block will be able to report such dead
+  //       blocks.
+  if (Block) FinishBlock(Block);
+
+  // Create the new block.
+  Block = createBlock(false);
+  
+  // The Exit block is the only successor.
+  Block->addSuccessor(&cfg->getExit());
+  
+  // Add the return statement to the block.
+  Block->appendStmt(R);
+  
+  // Also add the return statement as the terminator.
+  Block->setTerminator(R);
+  
+  return Block;
+}
 
-    // Now create a new block containing the if statement.        
-    Block = createBlock(false);
+CFGBlock* CFGBuilder::VisitLabelStmt(LabelStmt* L) {
+  // Get the block of the labeled statement.  Add it to our map.
+  CFGBlock* LabelBlock = Visit(L->getSubStmt());
+  assert (LabelBlock);    
+
+  assert (LabelMap.find(L) == LabelMap.end() && "label already in map");
+  LabelMap[ L ] = LabelBlock;
+  
+  // Labels partition blocks, so this is the end of the basic block
+  // we were processing (the label is the first statement).    
+  LabelBlock->appendStmt(L);
+  FinishBlock(LabelBlock);
+  
+  // We set Block to NULL to allow lazy creation of a new block
+  // (if necessary);
+  Block = NULL;
   
-    // Add the condition as the last statement in the new block.
-    Block->appendStmt(I->getCond());
-    
-    // Set the terminator of the new block to the If statement.
-    Block->setTerminator(I);
-    
-    // Now add the successors.
-    Block->addSuccessor(ThenBlock);
-    Block->addSuccessor(ElseBlock);
+  // This block is now the implicit successor of other blocks.
+  Succ = LabelBlock;
+  
+  return LabelBlock;
+}
 
-    return Block;
+CFGBlock* CFGBuilder::VisitGotoStmt(GotoStmt* G) {
+  // Goto is a control-flow statement.  Thus we stop processing the
+  // current block and create a new one.
+  if (Block) FinishBlock(Block);
+  Block = createBlock(false);
+  Block->setTerminator(G);
+  
+  // If we already know the mapping to the label block add the
+  // successor now.
+  LabelMapTy::iterator I = LabelMap.find(G->getLabel());
+  
+  if (I == LabelMap.end())
+    // We will need to backpatch this block later.
+    BackpatchBlocks.push_back(Block);
+  else
+    Block->addSuccessor(I->second);
+
+  return Block;            
+}
+
+CFGBlock* CFGBuilder::VisitForStmt(ForStmt* F) {
+  // "for" is a control-flow statement.  Thus we stop processing the
+  // current block.
+  
+  CFGBlock* LoopSuccessor = NULL;
+  
+  if (Block) {
+    FinishBlock(Block);
+    LoopSuccessor = Block;
   }
-      
-  CFGBlock* VisitReturnStmt(ReturnStmt* R) {
-    // If we were in the middle of a block we stop processing that block
-    // and reverse its statements.
-    //
-    // NOTE: If a "return" appears in the middle of a block, this means
-    //       that the code afterwards is DEAD (unreachable).  We still
-    //       keep a basic block for that code; a simple "mark-and-sweep"
-    //       from the entry block will be able to report such dead
-    //       blocks.
-    if (Block) FinishBlock(Block);
-
-    // Create the new block.
-    Block = createBlock(false);
+  else LoopSuccessor = Succ;
+  
+  // Create the condition block.
+  CFGBlock* ConditionBlock = createBlock(false);
+  ConditionBlock->setTerminator(F);
+  if (Stmt* C = F->getCond()) ConditionBlock->appendStmt(C);
+
+  // The condition block is the implicit successor for the loop body as
+  // well as any code above the loop.
+  Succ = ConditionBlock;
+  
+  // Now create the loop body.
+  {
+    assert (F->getBody());
     
-    // The Exit block is the only successor.
-    Block->addSuccessor(&cfg->getExit());
+    // 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;
     
-    // Add the return statement to the block.
-    Block->appendStmt(R);
+    // All breaks should go to the code following the loop.
+    BreakTargetBlock = LoopSuccessor;
+    
+    // Create a new block to contain the (bottom) of the loop body.      
+    Block = createBlock();
     
-    // Also add the return statement as the terminator.
-    Block->setTerminator(R);
+    // If we have increment code, insert it at the end of the body block.
+    if (Stmt* I = F->getInc()) Block->appendStmt(I);
     
+    // Now populate the body block, and in the process create new blocks
+    // as we walk the body of the loop.
+    CFGBlock* BodyBlock = Visit(F->getBody());      
+    assert (BodyBlock);      
+    FinishBlock(BodyBlock);
+    
+    // This new body block is a successor to our condition block.
+    ConditionBlock->addSuccessor(BodyBlock);
+  }
+  
+  // Link up the condition block with the code that follows the loop.
+  // (the false branch).
+  ConditionBlock->addSuccessor(LoopSuccessor);
+
+  // If the loop contains initialization, create a new block for those
+  // statements.  This block can also contain statements that precede
+  // the loop.
+  if (Stmt* I = F->getInit()) {
+    Block = createBlock();
+    Block->appendStmt(I);
     return Block;
   }
-  
-  CFGBlock* VisitLabelStmt(LabelStmt* L) {
-    // Get the block of the labeled statement.  Add it to our map.
-    CFGBlock* LabelBlock = Visit(L->getSubStmt());
-    assert (LabelBlock);    
-
-    assert (LabelMap.find(L) == LabelMap.end() && "label already in map");
-    LabelMap[ L ] = LabelBlock;
-    
-    // Labels partition blocks, so this is the end of the basic block
-    // we were processing (the label is the first statement).    
-    LabelBlock->appendStmt(L);
-    FinishBlock(LabelBlock);
-    
-    // We set Block to NULL to allow lazy creation of a new block
-    // (if necessary);
+  else {
+    // There is no loop initialization.   We are thus basically a while 
+    // loop.  NULL out Block to force lazy block construction.
     Block = NULL;
-    
-    // This block is now the implicit successor of other blocks.
-    Succ = LabelBlock;
-    
-    return LabelBlock;
+    return ConditionBlock;    
   }
-  
-  CFGBlock* VisitGotoStmt(GotoStmt* G) {
-    // Goto is a control-flow statement.  Thus we stop processing the
-    // current block and create a new one.
-    if (Block) FinishBlock(Block);
-    Block = createBlock(false);
-    Block->setTerminator(G);
-    
-    // If we already know the mapping to the label block add the
-    // successor now.
-    LabelMapTy::iterator I = LabelMap.find(G->getLabel());
-    
-    if (I == LabelMap.end())
-      // We will need to backpatch this block later.
-      BackpatchBlocks.push_back(Block);
-    else
-      Block->addSuccessor(I->second);
+}
 
-    return Block;            
-  }
-  
-  CFGBlock* VisitForStmt(ForStmt* F) {
-    // "for" is a control-flow statement.  Thus we stop processing the
-    // current block.
+CFGBlock* CFGBuilder::VisitWhileStmt(WhileStmt* W) {
+  // "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(W);
+  if (Stmt* C = W->getCond()) ConditionBlock->appendStmt(C);        
+  
+  // The condition block is the implicit successor for the loop body as
+  // well as any code above the loop.
+  Succ = ConditionBlock;
+  
+  // Process the loop body.
+  {
+    assert (W->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;
     
-    CFGBlock* LoopSuccessor = NULL;
+    // All breaks should go to the code following the loop.
+    BreakTargetBlock = LoopSuccessor;
     
-    if (Block) {
-      FinishBlock(Block);
-      LoopSuccessor = Block;
-    }
-    else LoopSuccessor = Succ;
+    // NULL out Block to force lazy instantiation of blocks for the body.
+    Block = NULL;
     
-    // Create the condition block.
-    CFGBlock* ConditionBlock = createBlock(false);
-    ConditionBlock->setTerminator(F);
-    if (Stmt* C = F->getCond()) ConditionBlock->appendStmt(C);
-
-    // The condition block is the implicit successor for the loop body as
-    // well as any code above the loop.
-    Succ = ConditionBlock;
-    
-    // Now create the loop body.
-    {
-      assert (F->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);      
+    // Create the body.  The returned block is the entry to the loop body.
+    CFGBlock* BodyBlock = Visit(W->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 condition block, which is the dominating block for the loop.
+  return ConditionBlock;
+}
 
-      // 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;
-      
-      // Create a new block to contain the (bottom) of the loop body.      
-      Block = createBlock();
-      
-      // If we have increment code, insert it at the end of the body block.
-      if (Stmt* I = F->getInc()) Block->appendStmt(I);
-      
-      // Now populate the body block, and in the process create new blocks
-      // as we walk the body of the loop.
-      CFGBlock* BodyBlock = Visit(F->getBody());      
-      assert (BodyBlock);      
-      FinishBlock(BodyBlock);
-      
-      // This new body block is a successor to our condition block.
-      ConditionBlock->addSuccessor(BodyBlock);
-    }
-    
-    // Link up the condition block with the code that follows the loop.
-    // (the false branch).
-    ConditionBlock->addSuccessor(LoopSuccessor);
-
-    // If the loop contains initialization, create a new block for those
-    // statements.  This block can also contain statements that precede
-    // the loop.
-    if (Stmt* I = F->getInit()) {
-      Block = createBlock();
-      Block->appendStmt(I);
-      return Block;
-    }
-    else {
-      // There is no loop initialization.   We are thus basically a while 
-      // loop.  NULL out Block to force lazy block construction.
-      Block = NULL;
-      return ConditionBlock;    
-    }
-  }
+CFGBlock* CFGBuilder::VisitDoStmt(DoStmt* D) {
+  // "do...while" is a control-flow statement.  Thus we stop processing the
+  // current block.
   
-  CFGBlock* VisitWhileStmt(WhileStmt* W) {
-    // "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(W);
-    if (Stmt* C = W->getCond()) ConditionBlock->appendStmt(C);        
-    
-    // The condition block is the implicit successor for the loop body as
-    // well as any code above the loop.
-    Succ = ConditionBlock;
-    
-    // Process the loop body.
-    {
-      assert (W->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.
-      CFGBlock* BodyBlock = Visit(W->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 condition block, which is the dominating block for the loop.
-    return ConditionBlock;
+  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* VisitDoStmt(DoStmt* D) {
-    // "do...while" is a control-flow statement.  Thus we stop processing the
-    // current block.
+  CFGBlock* BodyBlock = NULL;
+  // Process the loop body.
+  {
+    assert (D->getBody());
     
-    CFGBlock* LoopSuccessor = NULL;
+    // 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);
     
-    if (Block) {
-      FinishBlock(Block);
-      LoopSuccessor = Block;
-    }
-    else LoopSuccessor = Succ;
+    // All continues within this loop should go to the condition block
+    ContinueTargetBlock = ConditionBlock;
     
-    // 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);
-    }
+    // All breaks should go to the code following the loop.
+    BreakTargetBlock = LoopSuccessor;
     
-    // 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.
+    // NULL out Block to force lazy instantiation of blocks for the body.
     Block = NULL;
     
-    // Return the loop body, which is the dominating block for the loop.
-    return BodyBlock;
-  }
+    // 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;
   
-  CFGBlock* VisitContinueStmt(ContinueStmt* C) {
-    // "continue" is a control-flow statement.  Thus we stop processing the
-    // current block.
-    if (Block) FinishBlock(Block);
-    
-    // Now create a new block that ends with the continue statement.
-    Block = createBlock(false);
-    Block->setTerminator(C);
-    
-    // If there is no target for the continue, then we are looking at an
-    // incomplete AST.  Handle this by not registering a successor.
-    if (ContinueTargetBlock) Block->addSuccessor(ContinueTargetBlock);
-    
-    return Block;
+  // Return the loop body, which is the dominating block for the loop.
+  return BodyBlock;
+}
+
+CFGBlock* CFGBuilder::VisitContinueStmt(ContinueStmt* C) {
+  // "continue" is a control-flow statement.  Thus we stop processing the
+  // current block.
+  if (Block) FinishBlock(Block);
+  
+  // Now create a new block that ends with the continue statement.
+  Block = createBlock(false);
+  Block->setTerminator(C);
+  
+  // If there is no target for the continue, then we are looking at an
+  // incomplete AST.  Handle this by not registering a successor.
+  if (ContinueTargetBlock) Block->addSuccessor(ContinueTargetBlock);
+  
+  return Block;
+}
+
+CFGBlock* CFGBuilder::VisitBreakStmt(BreakStmt* B) {
+  // "break" is a control-flow statement.  Thus we stop processing the
+  // current block.
+  if (Block) FinishBlock(Block);
+  
+  // Now create a new block that ends with the continue statement.
+  Block = createBlock(false);
+  Block->setTerminator(B);
+  
+  // If there is no target for the break, then we are looking at an
+  // incomplete AST.  Handle this by not registering a successor.
+  if (BreakTargetBlock) Block->addSuccessor(BreakTargetBlock);
+
+  return Block;  
+}
+
+CFGBlock* CFGBuilder::VisitSwitchStmt(SwitchStmt* S) {
+  // "switch" is a control-flow statement.  Thus we stop processing the
+  // current block.    
+  CFGBlock* SwitchSuccessor = NULL;
+  
+  if (Block) {
+    FinishBlock(Block);
+    SwitchSuccessor = Block;
   }
+  else SwitchSuccessor = Succ;
+
+  // Save the current "switch" context.
+  SaveAndRestore<CFGBlock*> save_switch(SwitchTerminatedBlock),
+                            save_break(BreakTargetBlock);
   
-  CFGBlock* VisitBreakStmt(BreakStmt* B) {
-    // "break" is a control-flow statement.  Thus we stop processing the
-    // current block.
-    if (Block) FinishBlock(Block);
-    
-    // Now create a new block that ends with the continue statement.
-    Block = createBlock(false);
-    Block->setTerminator(B);
-    
-    // If there is no target for the break, then we are looking at an
-    // incomplete AST.  Handle this by not registering a successor.
-    if (BreakTargetBlock) Block->addSuccessor(BreakTargetBlock);
-
-    return Block;  
-  }
-  
-  CFGBlock* VisitSwitchStmt(SwitchStmt* S) {
-    // "switch" is a control-flow statement.  Thus we stop processing the
-    // current block.    
-    CFGBlock* SwitchSuccessor = NULL;
-    
-    if (Block) {
-      FinishBlock(Block);
-      SwitchSuccessor = Block;
-    }
-    else SwitchSuccessor = Succ;
+  // Create a new block that will contain the switch statement.
+  SwitchTerminatedBlock = createBlock(false);
   
-    // Save the current "switch" context.
-    SaveAndRestore<CFGBlock*> save_switch(SwitchTerminatedBlock),
-                              save_break(BreakTargetBlock);
-    
-    // Create a new block that will contain the switch statement.
-    SwitchTerminatedBlock = createBlock(false);
-    
-    // Add the terminator and condition in the switch block.
-    assert (S->getCond() && "switch condition must be non-NULL");
-    SwitchTerminatedBlock->appendStmt(S->getCond());
-    SwitchTerminatedBlock->setTerminator(S);
-    
-    
-    // Now process the switch body.  The code after the switch is the implicit
-    // successor.
-    Succ = SwitchSuccessor;
-    BreakTargetBlock = SwitchSuccessor;
+  // Add the terminator and condition in the switch block.
+  assert (S->getCond() && "switch condition must be non-NULL");
+  SwitchTerminatedBlock->appendStmt(S->getCond());
+  SwitchTerminatedBlock->setTerminator(S);
+  
+  
+  // Now process the switch body.  The code after the switch is the implicit
+  // successor.
+  Succ = SwitchSuccessor;
+  BreakTargetBlock = SwitchSuccessor;
+
+  assert (S->getBody() && "switch must contain a non-NULL body");
+  Block = NULL;
+  
+  // When visiting the body, the case statements should automatically get
+  // linked up to the switch.  We also don't keep a pointer to the body,
+  // since all control-flow from the switch goes to case/default statements.
+  Visit(S->getBody());
+  
+  Block = SwitchTerminatedBlock;
+  return SwitchTerminatedBlock;
+}
+
+CFGBlock* CFGBuilder::VisitSwitchCase(SwitchCase* S) {
+  // A SwitchCase is either a "default" or "case" statement.  We handle
+  // both in the same way.  They are essentially labels, so they are the
+  // first statement in a block.      
+  CFGBlock* CaseBlock = Visit(S->getSubStmt());
+  assert (CaseBlock);
+  
+  // Cases/Default statements parition block, so this is the top of
+  // the basic block we were processing (the case/default is the first stmt).
+  CaseBlock->appendStmt(S);
+  FinishBlock(CaseBlock);
+  
+  // Add this block to the list of successors for the block with the
+  // switch statement.
+  if (SwitchTerminatedBlock) SwitchTerminatedBlock->addSuccessor(CaseBlock);
+  
+  // We set Block to NULL to allow lazy creation of a new block (if necessary)
+  Block = NULL;
+  
+  // This block is now the implicit successor of other blocks.
+  Succ = CaseBlock;
+  
+  return CaseBlock;    
+}
 
-    assert (S->getBody() && "switch must contain a non-NULL body");
-    Block = NULL;
-    
-    // When visiting the body, the case statements should automatically get
-    // linked up to the switch.  We also don't keep a pointer to the body,
-    // since all control-flow from the switch goes to case/default statements.
-    Visit(S->getBody());
-    
-    Block = SwitchTerminatedBlock;
-    return SwitchTerminatedBlock;
-  }
-  
-  CFGBlock* VisitSwitchCase(SwitchCase* S) {
-    // A SwitchCase is either a "default" or "case" statement.  We handle
-    // both in the same way.  They are essentially labels, so they are the
-    // first statement in a block.      
-    CFGBlock* CaseBlock = Visit(S->getSubStmt());
-    assert (CaseBlock);
-    
-    // Cases/Default statements parition block, so this is the top of
-    // the basic block we were processing (the case/default is the first stmt).
-    CaseBlock->appendStmt(S);
-    FinishBlock(CaseBlock);
-    
-    // Add this block to the list of successors for the block with the
-    // switch statement.
-    if (SwitchTerminatedBlock) SwitchTerminatedBlock->addSuccessor(CaseBlock);
-    
-    // We set Block to NULL to allow lazy creation of a new block (if necessary)
-    Block = NULL;
-    
-    // This block is now the implicit successor of other blocks.
-    Succ = CaseBlock;
-    
-    return CaseBlock;    
-  }
 
-};
 } // end anonymous namespace
 
 /// createBlock - Constructs and adds a new CFGBlock to the CFG.  The
@@ -640,7 +666,6 @@
 
 /// print - A simple pretty printer of a CFG that outputs to an ostream.
 void CFG::print(std::ostream& OS) {
-
   // Print the Entry block.
   if (begin() != end()) {
     CFGBlock& Entry = getEntry();
@@ -656,58 +681,58 @@
     OS << "\n  [ B" << I->getBlockID() << " ]\n";    
     I->print(OS);
   }
-  
+
   // Print the Exit Block.  
   if (begin() != end()) {
     CFGBlock& Exit = getExit();
     OS << "\n [ B" << Exit.getBlockID() << " (EXIT) ]\n";
     Exit.print(OS);
   }    
-  
+
   OS << "\n";
 }
 
 
 namespace {
 
-  class CFGBlockTerminatorPrint : public StmtVisitor<CFGBlockTerminatorPrint,
-                                                     void > {
-    std::ostream& OS;
-  public:
-    CFGBlockTerminatorPrint(std::ostream& os) : OS(os) {}
-    
-    void VisitIfStmt(IfStmt* I) {
-      OS << "if ";
-      I->getCond()->printPretty(std::cerr);
-      OS << "\n";
-    }
-    
-    // Default case.
-    void VisitStmt(Stmt* S) { S->printPretty(OS); }
-    
-    void VisitForStmt(ForStmt* F) {
-      OS << "for (" ;
-      if (Stmt* I = F->getInit()) I->printPretty(OS);
-      OS << " ; ";
-      if (Stmt* C = F->getCond()) C->printPretty(OS);
-      OS << " ; ";
-      if (Stmt* I = F->getInc()) I->printPretty(OS);
-      OS << ")\n";                                                       
-    }
-    
-    void VisitWhileStmt(WhileStmt* W) {
-      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";
-    }                                                       
-  };
-}
+class CFGBlockTerminatorPrint : public StmtVisitor<CFGBlockTerminatorPrint,
+                                                   void > {
+  std::ostream& OS;
+public:
+  CFGBlockTerminatorPrint(std::ostream& os) : OS(os) {}
+  
+  void VisitIfStmt(IfStmt* I) {
+    OS << "if ";
+    I->getCond()->printPretty(std::cerr);
+    OS << "\n";
+  }
+  
+  // Default case.
+  void VisitStmt(Stmt* S) { S->printPretty(OS); }
+  
+  void VisitForStmt(ForStmt* F) {
+    OS << "for (" ;
+    if (Stmt* I = F->getInit()) I->printPretty(OS);
+    OS << " ; ";
+    if (Stmt* C = F->getCond()) C->printPretty(OS);
+    OS << " ; ";
+    if (Stmt* I = F->getInc()) I->printPretty(OS);
+    OS << ")\n";                                                       
+  }
+  
+  void VisitWhileStmt(WhileStmt* W) {
+    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";
+  }                                                       
+};
+} // end anonymous namespace
 
 /// dump - A simply pretty printer of a CFGBlock that outputs to stderr.
 void CFGBlock::dump() { print(std::cerr); }





More information about the cfe-commits mailing list