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

Ted Kremenek kremenek at apple.com
Tue Aug 28 11:14:37 PDT 2007


Author: kremenek
Date: Tue Aug 28 13:14:37 2007
New Revision: 41547

URL: http://llvm.org/viewvc/llvm-project?rev=41547&view=rev
Log:
Added support for comma expressions and DeclStmts which may have
arbitrarily complex control-flow in their subexpressions.

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=41547&r1=41546&r2=41547&view=diff

==============================================================================
--- cfe/trunk/AST/CFG.cpp (original)
+++ cfe/trunk/AST/CFG.cpp Tue Aug 28 13:14:37 2007
@@ -101,6 +101,7 @@
   CFGBlock* addStmt(Stmt* S);
   CFGBlock* WalkAST(Stmt* S, bool AlwaysAddStmt);
   CFGBlock* WalkAST_VisitChildren(Stmt* S);
+  CFGBlock* WalkAST_VisitVarDecl(VarDecl* D);
   void FinishBlock(CFGBlock* B);
   
 };
@@ -185,7 +186,8 @@
 }
 
 /// WalkAST - Used by addStmt to walk the subtree of a statement and
-///   add extra blocks for ternary operators, &&, and ||.
+///   add extra blocks for ternary operators, &&, and ||.  We also
+///   process "," and DeclStmts (which may contain nested control-flow).
 CFGBlock* CFGBuilder::WalkAST(Stmt* S, bool AlwaysAddStmt = false) {    
   switch (S->getStmtClass()) {
     case Stmt::ConditionalOperatorClass: {
@@ -210,6 +212,13 @@
       return addStmt(C->getCond());
     }
 
+    case Stmt::DeclStmtClass:      
+      if (VarDecl* V = dyn_cast<VarDecl>(cast<DeclStmt>(S)->getDecl())) {      
+        Block->appendStmt(S);
+        return WalkAST_VisitVarDecl(V);
+      }
+      else return Block;
+
     case Stmt::BinaryOperatorClass: {
       BinaryOperator* B = cast<BinaryOperator>(S);
 
@@ -232,6 +241,11 @@
         // Generate the blocks for evaluating the LHS.
         Block = LHSBlock;
         return addStmt(B->getLHS());                                    
+      }
+      else if (B->getOpcode() == BinaryOperator::Comma) { // ,
+        Block->appendStmt(B);
+        addStmt(B->getRHS());
+        return addStmt(B->getLHS());
       }    
 
       // Fall through to the default case.
@@ -243,6 +257,25 @@
   };
 }
 
+/// WalkAST_VisitVarDecl - Utility method to handle VarDecls contained in
+///  DeclStmts.  Because the initialization code for declarations can
+///  contain arbitrary expressions, we must linearize declarations
+///  to handle arbitrary control-flow induced by those expressions.
+CFGBlock* CFGBuilder::WalkAST_VisitVarDecl(VarDecl* V) {
+  // We actually must parse the LAST declaration in a chain of
+  // declarations first, because we are building the CFG in reverse
+  // order.
+  if (Decl* D = V->getNextDeclarator())
+    if (VarDecl* Next = cast<VarDecl>(D))
+      Block = WalkAST_VisitVarDecl(Next);
+    
+  if (Expr* E = V->getInit())
+    return addStmt(E);
+
+  assert (Block);
+  return Block;
+}
+
 /// WalkAST_VisitChildren - Utility method to call WalkAST on the
 ///  children of a Stmt.
 CFGBlock* CFGBuilder::WalkAST_VisitChildren(Stmt* S) {
@@ -365,9 +398,6 @@
   
   // The Exit block is the only successor.
   Block->addSuccessor(&cfg->getExit());
-
-  // Also add the return statement as the terminator.
-  Block->setTerminator(R);
     
   // Add the return statement to the block.  This may create new blocks
   // if R contains control-flow (short-circuit operations).





More information about the cfe-commits mailing list