aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/Analysis/Visitors/CFGRecStmtVisitor.h19
-rw-r--r--include/clang/Analysis/Visitors/CFGStmtVisitor.h12
-rw-r--r--lib/Analysis/LiveVariables.cpp14
3 files changed, 44 insertions, 1 deletions
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<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 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<ImplClass*>(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<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) {