Enhance dataflow analyses to recognize branch statements in the CFG used as hooks for the initialization of condition variables.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@92119 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/Analysis/Visitors/CFGRecStmtVisitor.h b/include/clang/Analysis/Visitors/CFGRecStmtVisitor.h
index 83700a3..75a4ac6 100644
--- a/include/clang/Analysis/Visitors/CFGRecStmtVisitor.h
+++ b/include/clang/Analysis/Visitors/CFGRecStmtVisitor.h
@@ -25,6 +25,25 @@
   void VisitStmt(Stmt* S) {
     static_cast< ImplClass* >(this)->VisitChildren(S);
   }
+  
+  void VisitConditionVariableInit(Stmt *S) {
+    assert(S == this->getCurrentBlkStmt());
+    VarDecl *CondVar = 0;
+    switch (S->getStmtClass()) {
+#define CONDVAR_CASE(CLASS) \
+case Stmt::CLASS ## Class:\
+CondVar = cast<CLASS>(S)->getConditionVariable();\
+break;
+        CONDVAR_CASE(IfStmt)
+        CONDVAR_CASE(ForStmt)
+        CONDVAR_CASE(SwitchStmt)
+        CONDVAR_CASE(WhileStmt)
+#undef CONDVAR_CASE
+      default:
+        assert(false && "Infeasible");
+    }    
+    static_cast<ImplClass*>(this)->Visit(CondVar->getInit());
+  }
 
   // Defining operator() allows the visitor to be used as a C++ style functor.
   void operator()(Stmt* S) { static_cast<ImplClass*>(this)->BlockStmt_Visit(S);}
diff --git a/include/clang/Analysis/Visitors/CFGStmtVisitor.h b/include/clang/Analysis/Visitors/CFGStmtVisitor.h
index 426b9cc..8a85ec1 100644
--- a/include/clang/Analysis/Visitors/CFGStmtVisitor.h
+++ b/include/clang/Analysis/Visitors/CFGStmtVisitor.h
@@ -54,6 +54,13 @@
     else
       return RetTy();
   }
+  
+  /// VisitConditionVariableInit - Handle the initialization of condition
+  ///  variables at branches.  Valid statements include IfStmt, ForStmt,
+  ///  WhileStmt, and SwitchStmt.
+  RetTy VisitConditionVariableInit(Stmt *S) {
+    return RetTy();
+  }
 
   /// BlockVisit_XXX - Visitor methods for visiting the "root" statements in
   /// CFGBlocks.  Root statements are the statements that appear explicitly in
@@ -65,6 +72,11 @@
     NullifyStmt cleanup(CurrentBlkStmt);
 
     switch (S->getStmtClass()) {
+      case Stmt::IfStmtClass:
+      case Stmt::ForStmtClass:
+      case Stmt::WhileStmtClass:
+      case Stmt::SwitchStmtClass:
+        return static_cast<ImplClass*>(this)->VisitConditionVariableInit(S);
 
       DISPATCH_CASE(StmtExpr)
       DISPATCH_CASE(ConditionalOperator)
diff --git a/lib/Analysis/LiveVariables.cpp b/lib/Analysis/LiveVariables.cpp
index 84e268f..e6fd162 100644
--- a/lib/Analysis/LiveVariables.cpp
+++ b/lib/Analysis/LiveVariables.cpp
@@ -112,6 +112,11 @@
   void VisitUnaryOperator(UnaryOperator* U);
   void Visit(Stmt *S);
   void VisitTerminator(CFGBlock* B);
+  
+  /// VisitConditionVariableInit - Handle the initialization of condition
+  ///  variables at branches.  Valid statements include IfStmt, ForStmt,
+  ///  WhileStmt, and SwitchStmt.
+  void VisitConditionVariableInit(Stmt *S);
 
   void SetTopValue(LiveVariables::ValTy& V) {
     V = AD.AlwaysLive;
@@ -126,7 +131,9 @@
     if (AD.Observer)
       AD.Observer->ObserveStmt(S,AD,LiveState);
 
-    if (getCFG().isBlkExpr(S)) LiveState(S,AD) = Dead;
+    if (getCFG().isBlkExpr(S))
+      LiveState(S, AD) = Dead;
+
     StmtVisitor<TransferFuncs,void>::Visit(S);
   }
   else if (!getCFG().isBlkExpr(S)) {
@@ -142,6 +149,11 @@
     LiveState(S,AD) = Alive;
   }
 }
+  
+void TransferFuncs::VisitConditionVariableInit(Stmt *S) {
+  assert(!getCFG().isBlkExpr(S));
+  CFGRecStmtVisitor<TransferFuncs>::VisitConditionVariableInit(S);
+}
 
 void TransferFuncs::VisitTerminator(CFGBlock* B) {