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

Ted Kremenek kremenek at apple.com
Mon Aug 27 14:27:45 PDT 2007


Author: kremenek
Date: Mon Aug 27 16:27:44 2007
New Revision: 41514

URL: http://llvm.org/viewvc/llvm-project?rev=41514&view=rev
Log:
Implemented support for ternary "?" operators in source-level CFGs.

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=41514&r1=41513&r2=41514&view=diff

==============================================================================
--- cfe/trunk/AST/CFG.cpp (original)
+++ cfe/trunk/AST/CFG.cpp Mon Aug 27 16:27:44 2007
@@ -83,6 +83,7 @@
   
   CFGBlock* VisitStmt(Stmt* Statement);
   CFGBlock* VisitNullStmt(NullStmt* Statement);
+  CFGBlock* VisitParenExpr(ParenExpr* Statement);
   CFGBlock* VisitCompoundStmt(CompoundStmt* C);
   CFGBlock* VisitIfStmt(IfStmt* I);
   CFGBlock* VisitReturnStmt(ReturnStmt* R);
@@ -98,7 +99,9 @@
   
 private:
   CFGBlock* createBlock(bool add_successor = true);
-  CFGBlock* addStmt(Stmt* S) { Block->appendStmt(S); return Block; }
+  CFGBlock* addStmt(Stmt* S);
+  CFGBlock* WalkAST(Stmt* S, bool AlwaysAddStmt);
+  CFGBlock* WalkAST_VisitChildren(Stmt* S);
   void FinishBlock(CFGBlock* B);
   
 };
@@ -171,6 +174,60 @@
   B->reverseStmts();
 }
 
+/// addStmt - Used to add statements/expressions to the current CFGBlock 
+///  "Block".  This method calls WalkAST on the passed statement to see if it
+///  contains any short-circuit expressions.  If so, it recursively creates
+///  the necessary blocks for such expressions.  It returns the "topmost" block
+///  of the created blocks, or the original value of "Block" when this method
+///  was called if no additional blocks are created.
+CFGBlock* CFGBuilder::addStmt(Stmt* S) {
+  assert (Block);
+  return WalkAST(S,true);
+}
+
+/// WalkAST - Used by addStmt to walk the subtree of a statement and
+///   add extra blocks for ternary operators, &&, and ||.
+CFGBlock* CFGBuilder::WalkAST(Stmt* S, bool AlwaysAddStmt = false) {    
+  switch (S->getStmtClass()) {
+    case Stmt::ConditionalOperatorClass: {
+      ConditionalOperator* C = cast<ConditionalOperator>(S);
+      
+      CFGBlock* ConfluenceBlock = (Block) ? Block : createBlock();  
+      ConfluenceBlock->appendStmt(C);
+      FinishBlock(ConfluenceBlock);
+      
+      Succ = ConfluenceBlock;
+      Block = NULL;
+      CFGBlock* LHSBlock = Visit(C->getLHS());
+      
+      Succ = ConfluenceBlock;
+      Block = NULL;
+      CFGBlock* RHSBlock = Visit(C->getRHS());
+      
+      Block = createBlock(false);
+      Block->addSuccessor(LHSBlock);
+      Block->addSuccessor(RHSBlock);
+      Block->setTerminator(C);
+      return addStmt(C->getCond());
+    }
+    default:
+      if (AlwaysAddStmt) Block->appendStmt(S);
+      return WalkAST_VisitChildren(S);
+  };
+}
+
+/// WalkAST_VisitChildren - Utility method to call WalkAST on the
+///  children of a Stmt.
+CFGBlock* CFGBuilder::WalkAST_VisitChildren(Stmt* S)
+{
+  CFGBlock* B = Block;
+  for (Stmt::child_iterator I = S->child_begin(), E = S->child_end() ;
+       I != E; ++I)
+    B = WalkAST(*I);
+  
+  return B;
+}
+
 /// 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
@@ -190,6 +247,11 @@
   return Block;
 }
 
+CFGBlock* CFGBuilder::VisitParenExpr(ParenExpr* Statement) {
+  return Visit(Statement->getSubExpr());
+}
+  
+
 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.
@@ -762,8 +824,20 @@
   void VisitDoStmt(DoStmt* D) {
     OS << "do ... while ";
     if (Stmt* C = D->getCond()) C->printPretty(OS);
-    OS << "\n";
-  }                                                       
+    OS << '\n';
+  }
+                                                       
+  void VisitSwitchStmt(SwitchStmt* S) {
+    OS << "switch ";
+    S->getCond()->printPretty(OS);
+    OS << '\n';
+  }
+  
+  void VisitConditionalOperator(ConditionalOperator* C) {
+    C->printPretty(OS);
+    OS << '\n';
+  }
+                                                     
 };
 } // end anonymous namespace
 





More information about the cfe-commits mailing list