]> granicus.if.org Git - clang/commitdiff
Updated CFGStmtVisitor and CFGRecStmtVisitor to have a notion of
authorTed Kremenek <kremenek@apple.com>
Tue, 20 Nov 2007 03:01:58 +0000 (03:01 +0000)
committerTed Kremenek <kremenek@apple.com>
Tue, 20 Nov 2007 03:01:58 +0000 (03:01 +0000)
"block-expressions" when visiting arbitrary expressions (via calls to
"Visit()").  This results in a refactoring where a dataflow analysis no
longer needs to always special case when handling block-expressions versus
non-block expressions.

Updated LiveVariables and UninitializedValues to conform to the slightly
altered interface of these visitor classes.

Thanks to Nuno Lopes for providing a test case that illustrated some
fundamental problems in the current design of the CFGXXXStmtVisitor classes
and how they were used.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@44246 91177308-0d34-0410-b5e6-96231b3b80d8

Analysis/LiveVariables.cpp
Analysis/UninitializedValues.cpp
include/clang/Analysis/Visitors/CFGRecStmtVisitor.h
include/clang/Analysis/Visitors/CFGStmtVisitor.h

index 3118a30d1faf9849a3546435f9a849fbcf0593c4..eba1a77941f5244ef1683f49cbe2ab25545765c5 100644 (file)
@@ -35,6 +35,7 @@ class RegisterDecls : public CFGRecStmtDeclVisitor<RegisterDecls> {
 public:
   RegisterDecls(LiveVariables::AnalysisDataTy& ad) : AD(ad) {}  
   void VisitVarDecl(VarDecl* VD) { AD.Register(VD); }
+  CFG& getCFG() { return AD.getCFG(); }
 };
 } // end anonymous namespace
 
@@ -52,34 +53,25 @@ namespace {
 static const bool Alive = true;
 static const bool Dead = false;  
 
-class TransferFuncs : public CFGStmtVisitor<TransferFuncs> {
+class TransferFuncs : public CFGRecStmtVisitor<TransferFuncs> {
   LiveVariables::AnalysisDataTy& AD;
   LiveVariables::ValTy LiveState;
 public:
   TransferFuncs(LiveVariables::AnalysisDataTy& ad) : AD(ad) {}
 
   LiveVariables::ValTy& getVal() { return LiveState; }
+  CFG& getCFG() { return AD.getCFG(); }
   
   void VisitDeclRefExpr(DeclRefExpr* DR);
   void VisitBinaryOperator(BinaryOperator* B);
   void VisitAssign(BinaryOperator* B);
   void VisitDeclStmt(DeclStmt* DS);
   void VisitUnaryOperator(UnaryOperator* U);
-  void VisitStmt(Stmt* S);
-  void VisitExpr(Expr* E);
-  void BlockStmt_VisitExpr(Expr *E);    
   void Visit(Stmt *S);
   
   DeclRefExpr* FindDeclRef(Stmt *S);
 };
-
-void TransferFuncs::VisitExpr(Expr * E) {
-  if (AD.getCFG().isBlkExpr(E)) return;
-  else VisitStmt(E);
-}
       
-void TransferFuncs::VisitStmt(Stmt* S) { VisitChildren(S); }
-
 void TransferFuncs::Visit(Stmt *S) {
   if (AD.Observer)
     AD.Observer->ObserveStmt(S,AD,LiveState);
@@ -160,11 +152,6 @@ void TransferFuncs::VisitDeclStmt(DeclStmt* DS) {
     LiveState(D,AD) = Dead;
 }
   
-void TransferFuncs::BlockStmt_VisitExpr(Expr* E) {
-  assert (AD.getCFG().isBlkExpr(E));
-  VisitChildren(E);
-}
-  
 } // end anonymous namespace
 
 //===----------------------------------------------------------------------===//
index 6f24872cd236db748543750e01477cdde1407833..0a496595f63f9136f8ccaf409c7f6fe4f0754bc6 100644 (file)
@@ -34,6 +34,7 @@ public:
   RegisterDecls(UninitializedValues::AnalysisDataTy& ad) :  AD(ad) {}
   
   void VisitBlockVarDecl(BlockVarDecl* VD) { AD.Register(VD); }
+  CFG& getCFG() { return AD.getCFG(); }
 };
   
 } // end anonymous namespace
@@ -58,6 +59,7 @@ public:
   }
   
   UninitializedValues::ValTy& getVal() { return V; }
+  CFG& getCFG() { return AD.getCFG(); }
   
   bool VisitDeclRefExpr(DeclRefExpr* DR);
   bool VisitBinaryOperator(BinaryOperator* B);
index 002c2f0546ab030896f0aa7d2be77d8d83b21bcf..bfe998bf9d3d90b6618acafee6ad98d6f8431383 100644 (file)
@@ -22,18 +22,10 @@ template <typename ImplClass>
 class CFGRecStmtVisitor : public CFGStmtVisitor<ImplClass,void> {
 public:  
 
-  void Visit(Stmt* S) {
-    static_cast< CFGStmtVisitor<ImplClass>* >(this)->Visit(S);
+  void VisitStmt(Stmt* S) {
     static_cast< ImplClass* >(this)->VisitChildren(S);
   }
-  
-  void BlockStmt_Visit(Stmt* S) {
-    assert (S);
-    
-    static_cast< CFGStmtVisitor<ImplClass>* >(this)->BlockStmt_Visit(S);
-    static_cast< ImplClass* >(this)->VisitChildren(S);
-  }
-  
+      
   // Defining operator() allows the visitor to be used as a C++ style functor.
   void operator()(Stmt* S) { static_cast<ImplClass*>(this)->BlockStmt_Visit(S);}
 };
index afc987309370842b12de321f9210ce034889e504..8ece7d0acb499e1550c7450253c78ae7c4241cf7 100644 (file)
@@ -33,14 +33,36 @@ static_cast<ImplClass*>(this)->BlockStmt_Visit ## CLASS(static_cast<CLASS*>(S));
 
 template <typename ImplClass, typename RetTy=void>
 class CFGStmtVisitor : public StmtVisitor<ImplClass,RetTy> {
-public:
+  Stmt* CurrentBlkExpr;
+
+  struct NullifyStmt {
+    Stmt*& S;  
+    
+    NullifyStmt(Stmt*& s) : S(s) {}
+    ~NullifyStmt() { S = NULL; }
+  };
+  
+public:  
+  CFGStmtVisitor() : CurrentBlkExpr(NULL) {}  
+  
+  RetTy Visit(Stmt* S) {
+    if (S == CurrentBlkExpr || 
+        !static_cast<ImplClass*>(this)->getCFG().isBlkExpr(S))
+      return StmtVisitor<ImplClass,RetTy>::Visit(S);
+    else
+      return RetTy();
+  }
+  
   /// BlockVisit_XXX - Visitor methods for visiting the "root" statements in
   /// CFGBlocks.  Root statements are the statements that appear explicitly in 
   /// the list of statements in a CFGBlock.  For substatements, or when there
   /// is no implementation provided for a BlockStmt_XXX method, we default
   /// to using StmtVisitor's Visit method.
   RetTy BlockStmt_Visit(Stmt* S) {
-    switch (S->getStmtClass()) {    
+    CurrentBlkExpr = S;
+    NullifyStmt cleanup(CurrentBlkExpr);
+    
+    switch (S->getStmtClass()) {
       DISPATCH_CASE(CallExpr)
       DISPATCH_CASE(StmtExpr)
       DISPATCH_CASE(ConditionalOperator)