diff options
-rw-r--r-- | clang/include/clang/Analysis/Visitors/CFGRecStmtVisitor.h | 19 | ||||
-rw-r--r-- | clang/include/clang/Analysis/Visitors/CFGStmtVisitor.h | 12 | ||||
-rw-r--r-- | clang/lib/Analysis/LiveVariables.cpp | 14 |
3 files changed, 44 insertions, 1 deletions
diff --git a/clang/include/clang/Analysis/Visitors/CFGRecStmtVisitor.h b/clang/include/clang/Analysis/Visitors/CFGRecStmtVisitor.h index 83700a3a346..75a4ac66012 100644 --- a/clang/include/clang/Analysis/Visitors/CFGRecStmtVisitor.h +++ b/clang/include/clang/Analysis/Visitors/CFGRecStmtVisitor.h @@ -25,6 +25,25 @@ public: 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/clang/include/clang/Analysis/Visitors/CFGStmtVisitor.h b/clang/include/clang/Analysis/Visitors/CFGStmtVisitor.h index 426b9ccd8a2..8a85ec15cdc 100644 --- a/clang/include/clang/Analysis/Visitors/CFGStmtVisitor.h +++ b/clang/include/clang/Analysis/Visitors/CFGStmtVisitor.h @@ -54,6 +54,13 @@ public: 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 @@ public: 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/clang/lib/Analysis/LiveVariables.cpp b/clang/lib/Analysis/LiveVariables.cpp index 84e268f3fda..e6fd1627e2d 100644 --- a/clang/lib/Analysis/LiveVariables.cpp +++ b/clang/lib/Analysis/LiveVariables.cpp @@ -112,6 +112,11 @@ public: 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 @@ void TransferFuncs::Visit(Stmt *S) { 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 @@ void TransferFuncs::Visit(Stmt *S) { LiveState(S,AD) = Alive; } } + +void TransferFuncs::VisitConditionVariableInit(Stmt *S) { + assert(!getCFG().isBlkExpr(S)); + CFGRecStmtVisitor<TransferFuncs>::VisitConditionVariableInit(S); +} void TransferFuncs::VisitTerminator(CFGBlock* B) { |