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

Ted Kremenek kremenek at apple.com
Tue Aug 21 15:06:14 PDT 2007


Author: kremenek
Date: Tue Aug 21 17:06:14 2007
New Revision: 41254

URL: http://llvm.org/viewvc/llvm-project?rev=41254&view=rev
Log:
Converted CFGBuilder to use StmtVisitor instead of doing a switch
dispatch to walk the AST.

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=41254&r1=41253&r2=41254&view=diff

==============================================================================
--- cfe/trunk/AST/CFG.cpp (original)
+++ cfe/trunk/AST/CFG.cpp Tue Aug 21 17:06:14 2007
@@ -14,6 +14,7 @@
 
 #include "clang/AST/CFG.h"
 #include "clang/AST/Expr.h"
+#include "clang/AST/StmtVisitor.h"
 #include <iostream>
 #include <iomanip>
 #include <algorithm>
@@ -42,7 +43,13 @@
 ///     CFGBuilder builder;
 ///     CFG* cfg = builder.BuildAST(stmt1);
 ///
-class CFGBuilder {    
+///  CFG construction is done via a recursive walk of an AST.
+///  We actually parse the AST in reverse order so that the successor
+///  of a basic block is constructed prior to its predecessor.  This
+///  allows us to nicely capture implicit fall-throughs without extra
+///  basic blocks.
+///
+class CFGBuilder : public StmtVisitor<CFGBuilder,CFGBlock*> {    
   CFG* cfg;
   CFGBlock* Block;
   CFGBlock* Exit;
@@ -73,7 +80,7 @@
     Exit = Block;
     
     // Visit the statements and create the CFG.
-    if (CFGBlock* B = visitStmt(Statement)) {
+    if (CFGBlock* B = Visit(Statement)) {
       // Reverse the statements in the last constructed block.  Statements
       // are inserted into the blocks in reverse order.
       B->reverseStmts();
@@ -89,9 +96,7 @@
       return NULL;
     }
   }
-
-private:
-
+  
   // createBlock - Used to lazily create blocks that are connected
   //  to the current (global) succcessor.
   CFGBlock* createBlock( bool add_successor = true ) { 
@@ -99,169 +104,125 @@
     if (add_successor && Succ) B->addSuccessor(Succ);
     return B;
   }
+
+  /// 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;
+  }
   
-  // visitStmt - CFG construction is done via a recursive walk of an AST.
-  //   We actually parse the AST in reverse order so that the successor
-  //   of a basic block is constructed prior to its predecessor.  This
-  //   allows us to nicely capture implicit fall-throughs without extra
-  //   basic blocks.
-  //
-  //   The value returned from this function is the last created CFGBlock
-  //   that represents the "entry" point for the translated AST node.
-  CFGBlock* visitStmt(Stmt* Statement) {
-    assert (Statement && "visitStmt does not accept NULL Stmt*");
-  
-    switch (Statement->getStmtClass()) {    
-      default:
-        assert (false && "statement case for CFGBuilder not yet implemented");
-        return NULL;
-      
-      // Statements with no branching control flow.
-      case Stmt::NullStmtClass:
-      case Stmt::DeclStmtClass:
-      case Stmt::PreDefinedExprClass:
-      case Stmt::DeclRefExprClass:
-      case Stmt::IntegerLiteralClass:
-      case Stmt::FloatingLiteralClass:
-      case Stmt::StringLiteralClass:
-      case Stmt::CharacterLiteralClass:
-      case Stmt::ParenExprClass:
-      case Stmt::UnaryOperatorClass:
-      case Stmt::SizeOfAlignOfTypeExprClass:
-      case Stmt::ArraySubscriptExprClass:
-      case Stmt::CallExprClass:
-      case Stmt::BinaryOperatorClass:
-      case Stmt::ImplicitCastExprClass:
-      case Stmt::CompoundLiteralExprClass:
-      case Stmt::OCUVectorElementExprClass:
-        // 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);
-        break;
-        
-      case Stmt::CompoundStmtClass: {
-        // Iterate through the statements of the compound statement in reverse
-        // order.  Because this statement may contain statements that have
-        // complicated control flow, the value of "Block" may change at any
-        // time.  This means that statements in the compound statement will
-        // automatically be distributed across multiple basic blocks when
-        // necessary.
-        CompoundStmt* C = cast<CompoundStmt>(Statement);
-
-        for (CompoundStmt::reverse_body_iterator I = C->body_rbegin(),
-             E = C->body_rend(); I != E; ++I )
-          // Add the statement to the current block.
-          if (!visitStmt(*I)) return NULL;
+  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.
+    for (CompoundStmt::reverse_body_iterator I = C->body_rbegin(),
+          E = C->body_rend(); I != E; ++I )
+      // Add the statement to the current block.
+      if (!Visit(*I)) return NULL;
 
-        break;
-      }
+    return Block;
+  }
+  
+  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;
+      Block->reverseStmts();
+    }
+    
+    // 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);
       
-      case Stmt::IfStmtClass: {
-        IfStmt* I = cast<IfStmt>(Statement);
-        
-        // 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;
-          Block->reverseStmts();
-        }
-        
-        // Process the false branch.  NULL out Block so that the recursive
-        // call to visitStmt 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);
-          
-          // NULL out Block so that the recursive call to visitStmt will
-          // create a new basic block.          
-          Block = NULL;
-          ElseBlock = visitStmt(Else);          
-          if (!ElseBlock) return NULL;
-          ElseBlock->reverseStmts();        
-        }
-        
-        // Process the true branch.  NULL out Block so that the recursive
-        // call to visitStmt 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 = visitStmt(Then);        
-          if (!ThenBlock) return NULL;
-          ThenBlock->reverseStmts();
-        }
+      // 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;
+      ElseBlock->reverseStmts();        
+    }
+    
+    // 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;
+      ThenBlock->reverseStmts();
+    }
 
-        // 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);
+    // 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);
 
-        break;
-      }
+    return Block;
+  }
       
-      case Stmt::ReturnStmtClass: {
-        ReturnStmt* R = cast<ReturnStmt>(Statement);
+  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) Block->reverseStmts();        
 
-        // 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) Block->reverseStmts();        
-
-        // Create the new block.
-        Block = createBlock(false);
-        
-        // The Exit block is the only successor.
-        Block->addSuccessor(Exit);
-        
-        // Add the return expression to the block.
-        Block->appendStmt(R);
-        
-        // Add the return statement itself to the block.
-        if (R->getRetValue()) Block->appendStmt(R->getRetValue());
-        
-        break; 
-      }
-    } // end dispatch on statement class
+    // Create the new block.
+    Block = createBlock(false);
+    
+    // The Exit block is the only successor.
+    Block->addSuccessor(Exit);
+    
+    // Add the return expression to the block.
+    Block->appendStmt(R);
+    
+    // Add the return statement itself to the block.
+    if (R->getRetValue()) Block->appendStmt(R->getRetValue());
     
     return Block;
-  }
-  
+  }  
 };
 
 // BuildCFG - A helper function that builds CFGs from ASTS.
-CFG* CFG::BuildCFG( Stmt* Statement ) {
+CFG* CFG::BuildCFG(Stmt* Statement) {
   CFGBuilder Builder;
   return Builder.buildCFG(Statement);
 }





More information about the cfe-commits mailing list