From: Ted Kremenek Date: Thu, 24 Dec 2009 02:40:30 +0000 (+0000) Subject: Enhance dataflow analyses to recognize branch statements in the CFG used as hooks... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=bfbcefb7e99905218b3f0a895b7bc1992203123b;p=clang 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 83700a3a34..75a4ac6601 100644 --- a/include/clang/Analysis/Visitors/CFGRecStmtVisitor.h +++ b/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(S)->getConditionVariable();\ +break; + CONDVAR_CASE(IfStmt) + CONDVAR_CASE(ForStmt) + CONDVAR_CASE(SwitchStmt) + CONDVAR_CASE(WhileStmt) +#undef CONDVAR_CASE + default: + assert(false && "Infeasible"); + } + static_cast(this)->Visit(CondVar->getInit()); + } // Defining operator() allows the visitor to be used as a C++ style functor. void operator()(Stmt* S) { static_cast(this)->BlockStmt_Visit(S);} diff --git a/include/clang/Analysis/Visitors/CFGStmtVisitor.h b/include/clang/Analysis/Visitors/CFGStmtVisitor.h index 426b9ccd8a..8a85ec15cd 100644 --- a/include/clang/Analysis/Visitors/CFGStmtVisitor.h +++ b/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(this)->VisitConditionVariableInit(S); DISPATCH_CASE(StmtExpr) DISPATCH_CASE(ConditionalOperator) diff --git a/lib/Analysis/LiveVariables.cpp b/lib/Analysis/LiveVariables.cpp index 84e268f3fd..e6fd1627e2 100644 --- a/lib/Analysis/LiveVariables.cpp +++ b/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::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::VisitConditionVariableInit(S); +} void TransferFuncs::VisitTerminator(CFGBlock* B) {