[cfe-commits] r42293 - in /cfe/trunk: Analysis/DataflowSolver.h Analysis/DeadStores.cpp Analysis/LiveVariables.cpp Driver/ASTStreamers.cpp include/clang/Analysis/DataflowValues.h include/clang/Analysis/LiveVariables.h include/clang/Analysis/LocalCheckers.h include/clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h

Ted Kremenek kremenek at apple.com
Mon Sep 24 21:31:27 PDT 2007


Author: kremenek
Date: Mon Sep 24 23:31:27 2007
New Revision: 42293

URL: http://llvm.org/viewvc/llvm-project?rev=42293&view=rev
Log:
Further refactored DataflowSolver.  Now most code for the solver is shared
between forward and backward analyses, with trait classes being used
to implement the key differences in operations/functionality.

Converted the LiveVariables analysis to use the generic DataflowSolver.  This,
along with removing some extra functionality that was not needed, reduced
the code for LiveVariables by over half.

Modified Driver code to handle the updated interface to LiveVariables.

Modified the DeadStores checker to handle the update interface to
LiveVariables.

Updated DataflowValues (generic ADT to store dataflow values) to also
store values for blocks.  This is used by DeadStores.  Updated some comments.

Modified:
    cfe/trunk/Analysis/DataflowSolver.h
    cfe/trunk/Analysis/DeadStores.cpp
    cfe/trunk/Analysis/LiveVariables.cpp
    cfe/trunk/Driver/ASTStreamers.cpp
    cfe/trunk/include/clang/Analysis/DataflowValues.h
    cfe/trunk/include/clang/Analysis/LiveVariables.h
    cfe/trunk/include/clang/Analysis/LocalCheckers.h
    cfe/trunk/include/clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h

Modified: cfe/trunk/Analysis/DataflowSolver.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Analysis/DataflowSolver.h?rev=42293&r1=42292&r2=42293&view=diff

==============================================================================
--- cfe/trunk/Analysis/DataflowSolver.h (original)
+++ cfe/trunk/Analysis/DataflowSolver.h Mon Sep 24 23:31:27 2007
@@ -45,6 +45,61 @@
 };
 
 //===----------------------------------------------------------------------===//
+// BlockItrTraits - Traits classes that allow transparent iteration over
+//  successors/predecessors of a block depending on the direction of our
+//  dataflow analysis.
+
+namespace dataflow {
+template<typename Tag> struct ItrTraits {};
+
+template <> struct ItrTraits<forward_analysis_tag> {
+  typedef CFGBlock::const_pred_iterator PrevBItr;
+  typedef CFGBlock::const_succ_iterator NextBItr;
+  typedef CFGBlock::const_iterator      StmtItr;
+  
+  static PrevBItr PrevBegin(const CFGBlock* B) { return B->pred_begin(); }
+  static PrevBItr PrevEnd(const CFGBlock* B) { return B->pred_end(); }
+  
+  static NextBItr NextBegin(const CFGBlock* B) { return B->succ_begin(); }    
+  static NextBItr NextEnd(const CFGBlock* B) { return B->succ_end(); }
+  
+  static StmtItr StmtBegin(const CFGBlock* B) { return B->begin(); }
+  static StmtItr StmtEnd(const CFGBlock* B) { return B->end(); }
+  
+  static CFG::Edge PrevEdge(const CFGBlock* B, const CFGBlock* PrevBlk) {
+    return CFG::Edge(PrevBlk,B);
+  }
+  
+  static CFG::Edge NextEdge(const CFGBlock* B, const CFGBlock* NextBlk) {
+    return CFG::Edge(B,NextBlk);
+  }
+};
+
+template <> struct ItrTraits<backward_analysis_tag> {
+  typedef CFGBlock::const_succ_iterator    PrevBItr;
+  typedef CFGBlock::const_pred_iterator    NextBItr;
+  typedef CFGBlock::const_reverse_iterator StmtItr;
+  
+  static PrevBItr PrevBegin(const CFGBlock* B) { return B->succ_begin(); }    
+  static PrevBItr PrevEnd(const CFGBlock* B) { return B->succ_end(); }
+  
+  static NextBItr NextBegin(const CFGBlock* B) { return B->pred_begin(); }    
+  static NextBItr NextEnd(const CFGBlock* B) { return B->pred_end(); }
+  
+  static StmtItr StmtBegin(const CFGBlock* B) { return B->rbegin(); }
+  static StmtItr StmtEnd(const CFGBlock* B) { return B->rend(); }    
+  
+  static CFG::Edge PrevEdge(const CFGBlock* B, const CFGBlock* PrevBlk) {
+    return CFG::Edge(B,PrevBlk);
+  }
+  
+  static CFG::Edge NextEdge(const CFGBlock* B, const CFGBlock* NextBlk) {
+    return CFG::Edge(NextBlk,B);
+  }
+};
+} // end namespace dataflow
+
+//===----------------------------------------------------------------------===//
 /// DataflowSolverTy - Generic dataflow solver.
 template <typename _DFValuesTy,      // Usually a subclass of DataflowValues
           typename _TransferFuncsTy,
@@ -57,14 +112,20 @@
   //===--------------------------------------------------------------------===//
 
 public:
-  typedef _DFValuesTy                            DFValuesTy;
-  typedef _TransferFuncsTy                       TransferFuncsTy;
-  typedef _MergeOperatorTy                       MergeOperatorTy;
-
-  typedef typename _DFValuesTy::AnalysisDirTag   AnalysisDirTag;
-  typedef typename _DFValuesTy::ValTy            ValTy;
-  typedef typename _DFValuesTy::EdgeDataMapTy    EdgeDataMapTy;
-
+  typedef _DFValuesTy                              DFValuesTy;
+  typedef _TransferFuncsTy                         TransferFuncsTy;
+  typedef _MergeOperatorTy                         MergeOperatorTy;
+  
+  typedef typename _DFValuesTy::AnalysisDirTag     AnalysisDirTag;
+  typedef typename _DFValuesTy::ValTy              ValTy;
+  typedef typename _DFValuesTy::EdgeDataMapTy      EdgeDataMapTy;
+  typedef typename _DFValuesTy::BlockDataMapTy     BlockDataMapTy;
+
+  typedef dataflow::ItrTraits<AnalysisDirTag>      ItrTraits;
+  typedef typename ItrTraits::NextBItr             NextBItr;
+  typedef typename ItrTraits::PrevBItr             PrevBItr;
+  typedef typename ItrTraits::StmtItr              StmtItr;
+  
   //===--------------------------------------------------------------------===//
   // External interface: constructing and running the solver.
   //===--------------------------------------------------------------------===//
@@ -88,13 +149,18 @@
   ///  only be used for querying the dataflow values within a block with
   ///  and Observer object.
   void runOnBlock(const CFGBlock* B) {
-    if (hasData(B,AnalysisDirTag()))
-      ProcessBlock(B,AnalysisDirTag());
+    BlockDataMapTy& M = D.getBlockDataMap();
+    typename BlockDataMapTy::iterator I = M.find(B);
+
+    if (I != M.end()) {
+      TF.getVal().copyValues(I->second);
+      ProcessBlock(B);
+    }
   }
   
   void runOnBlock(const CFGBlock& B) { runOnBlock(&B); }
-  void runOnBlock(CFG::iterator &I) { runOnBlock(*I); }
-  void runOnBlock(CFG::const_iterator &I) { runOnBlock(*I); }
+  void runOnBlock(CFG::iterator& I) { runOnBlock(*I); }
+  void runOnBlock(CFG::const_iterator& I) { runOnBlock(*I); }
 
   void runOnAllBlocks(const CFG& cfg) {
     for (CFG::const_iterator I=cfg.begin(), E=cfg.end(); I!=E; ++I)
@@ -110,17 +176,13 @@
   /// SolveDataflowEquations - Perform the actual
   ///  worklist algorithm to compute dataflow values.  
   void SolveDataflowEquations(const CFG& cfg) {
-
     EnqueueFirstBlock(cfg,AnalysisDirTag());
     
-    // Process the worklist until it is empty.    
     while (!WorkList.isEmpty()) {
       const CFGBlock* B = WorkList.dequeue();
-      // If the dataflow values at the block's entry have changed,
-      // enqueue all predecessor blocks onto the worklist to have
-      // their values updated.
-      ProcessBlock(B,AnalysisDirTag());
-      UpdateEdges(B,TF.getVal(),AnalysisDirTag());
+      ProcessMerge(B);
+      ProcessBlock(B);
+      UpdateEdges(B,TF.getVal());
     }
   }
   
@@ -131,42 +193,8 @@
   void EnqueueFirstBlock(const CFG& cfg, dataflow::backward_analysis_tag) {
     WorkList.enqueue(&cfg.getExit());
   }  
-  
-  /// ProcessBlock (FORWARD ANALYSIS) - Process the transfer functions
-  ///  for a given block based on a forward analysis.
-  void ProcessBlock(const CFGBlock* B, dataflow::forward_analysis_tag) {
-      
-    // Merge dataflow values from all predecessors of this block.
-    ValTy& V = TF.getVal();
-    V.resetValues(D.getAnalysisData());
-    MergeOperatorTy Merge;
-  
-    EdgeDataMapTy& M = D.getEdgeDataMap();
-    bool firstMerge = true;
-  
-    for (CFGBlock::const_pred_iterator I=B->pred_begin(), 
-                                      E=B->pred_end(); I!=E; ++I) {
-      typename EdgeDataMapTy::iterator BI = M.find(CFG::Edge(*I,B));
-      if (BI != M.end()) {
-        if (firstMerge) {
-          firstMerge = false;
-          V.copyValues(BI->second);
-        }
-        else
-          Merge(V,BI->second);
-      }
-    }
 
-    // Process the statements in the block in the forward direction.
-    for (CFGBlock::const_iterator I=B->begin(), E=B->end(); I!=E; ++I)
-      TF.BlockStmt_Visit(const_cast<Stmt*>(*I));      
-  }
-  
-  /// ProcessBlock (BACKWARD ANALYSIS) - Process the transfer functions
-  ///  for a given block based on a forward analysis.
-  void ProcessBlock(const CFGBlock* B, TransferFuncsTy& TF,
-                    dataflow::backward_analysis_tag) {
-        
+  void ProcessMerge(const CFGBlock* B) {
     // Merge dataflow values from all predecessors of this block.
     ValTy& V = TF.getVal();
     V.resetValues(D.getAnalysisData());
@@ -174,59 +202,47 @@
     
     EdgeDataMapTy& M = D.getEdgeDataMap();
     bool firstMerge = true;
+    
+    for (PrevBItr I=ItrTraits::PrevBegin(B),E=ItrTraits::PrevEnd(B); I!=E; ++I){
 
-    for (CFGBlock::const_succ_iterator I=B->succ_begin(), 
-                                       E=B->succ_end(); I!=E; ++I) {
-      typename EdgeDataMapTy::iterator BI = M.find(CFG::Edge(B,*I));
-      if (BI != M.end()) {
+      typename EdgeDataMapTy::iterator EI = M.find(ItrTraits::PrevEdge(B,*I));
+
+      if (EI != M.end()) {
         if (firstMerge) {
           firstMerge = false;
-          V.copyValues(BI->second);
+          V.copyValues(EI->second);
         }
-        else
-          Merge(V,BI->second);
+        else Merge(V,EI->second);
       }
     }
     
-    // Process the statements in the block in the forward direction.
-    for (CFGBlock::const_reverse_iterator I=B->begin(), E=B->end(); I!=E; ++I)
-      TF.BlockStmt_Visit(const_cast<Stmt*>(*I));    
+    // Set the data for the block.
+    D.getBlockDataMap()[B].copyValues(V);
   }
+  
 
-  /// UpdateEdges (FORWARD ANALYSIS) - After processing the transfer
-  ///   functions for a block, update the dataflow value associated with the
-  ///   block's outgoing edges.  Enqueue any successor blocks for an
-  ///   outgoing edge whose value has changed.  
-  void UpdateEdges(const CFGBlock* B, ValTy& V,dataflow::forward_analysis_tag) {    
-    for (CFGBlock::const_succ_iterator I=B->succ_begin(), E=B->succ_end();
-          I!=E; ++I) {
-                    
-      CFG::Edge Edg(B,*I);
-      UpdateEdgeValue(Edg,V,*I);
-    }
+  /// ProcessBlock - Process the transfer functions for a given block.
+  void ProcessBlock(const CFGBlock* B) {
+    for (StmtItr I=ItrTraits::StmtBegin(B), E=ItrTraits::StmtEnd(B); I!=E; ++I)
+      TF.BlockStmt_Visit(const_cast<Stmt*>(*I));
   }
-  
-  /// UpdateEdges (BACKWARD ANALYSIS) - After processing the transfer
+
+  /// UpdateEdges - After processing the transfer
   ///   functions for a block, update the dataflow value associated with the
-  ///   block's incoming edges.  Enqueue any predecessor blocks for an
-  ///   outgoing edge whose value has changed.  
-  void UpdateEdges(const CFGBlock* B, ValTy& V,dataflow::backward_analysis_tag){      
-    for (CFGBlock::const_pred_iterator I=B->succ_begin(), E=B->succ_end();
-         I!=E; ++I) {
-      
-      CFG::Edge Edg(*I,B);
-      UpdateEdgeValue(Edg,V,*I);
-    }
+  ///   block's outgoing/incoming edges (depending on whether we do a 
+  //    forward/backward analysis respectively)
+  void UpdateEdges(const CFGBlock* B, ValTy& V) {
+    for (NextBItr I=ItrTraits::NextBegin(B), E=ItrTraits::NextEnd(B); I!=E; ++I)
+      UpdateEdgeValue(ItrTraits::NextEdge(B,*I),V,*I);
   }
-  
+    
   /// UpdateEdgeValue - Update the value associated with a given edge.
-  void UpdateEdgeValue(CFG::Edge& E, ValTy& V, const CFGBlock* TargetBlock) {
+  void UpdateEdgeValue(CFG::Edge E, ValTy& V, const CFGBlock* TargetBlock) {
   
     EdgeDataMapTy& M = D.getEdgeDataMap();
     typename EdgeDataMapTy::iterator I = M.find(E);
       
-    if (I == M.end()) {
-      // First value for this edge.
+    if (I == M.end()) {  // First computed value for this edge?
       M[E].copyValues(V);
       WorkList.enqueue(TargetBlock);
     }
@@ -235,33 +251,7 @@
       WorkList.enqueue(TargetBlock);
     }
   }
-  
-  /// hasData (FORWARD ANALYSIS) - Is there any dataflow values associated
-  ///  with the incoming edges of a block?
-  bool hasData(const CFGBlock* B, dataflow::forward_analysis_tag) {  
-    EdgeDataMapTy& M = D.getEdgeDataMap();
-
-    for (CFGBlock::const_pred_iterator I=B->pred_begin(), E=B->pred_end();
-         I!=E; ++I)
-      if (M.find(CFG::Edge(*I,B)) != M.end())
-        return true;
-        
-    return false;
-  }
-  
-  /// hasData (BACKWARD ANALYSIS) - Is there any dataflow values associated
-  ///  with the outgoing edges of a block?
-  bool hasData(const CFGBlock* B, dataflow::backward_analysis_tag) {  
-    EdgeDataMapTy& M = D.getEdgeDataMap();
     
-    for (CFGBlock::const_succ_iterator I=B->succ_begin(), E=B->succ_end();
-         I!=E; ++I)
-      if (M.find(CFG::Edge(B,*I)) != M.end())
-        return true;
-    
-    return false;
-  }
-
 private:
   DFValuesTy& D;
   DataflowWorkListTy WorkList;

Modified: cfe/trunk/Analysis/DeadStores.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Analysis/DeadStores.cpp?rev=42293&r1=42292&r2=42293&view=diff

==============================================================================
--- cfe/trunk/Analysis/DeadStores.cpp (original)
+++ cfe/trunk/Analysis/DeadStores.cpp Mon Sep 24 23:31:27 2007
@@ -12,50 +12,57 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "clang/AST/Expr.h"
 #include "clang/Analysis/LocalCheckers.h"
 #include "clang/Analysis/LiveVariables.h"
-#include "clang/AST/CFG.h"
+#include "clang/Analysis/Visitors/CFGRecStmtVisitor.h"
 #include "clang/Basic/Diagnostic.h"
 #include "clang/AST/ASTContext.h"
+#include "llvm/ADT/SmallPtrSet.h"
 
 using namespace clang;
 
 namespace {
 
-class DeadStoreObserver : public LiveVariablesObserver {
+class EverKilled : public LiveVariables::ObserverTy {
+  llvm::SmallPtrSet<const VarDecl*, 10> Killed;
+public:
+  virtual void ObserveKill(DeclRefExpr* DR) {
+    Killed.insert(cast<VarDecl>(DR->getDecl()));
+  }    
+  
+  bool hasKill(const VarDecl* V) { return Killed.count(V) != 0; }
+};
+  
+class DeadStoreObs : public LiveVariables::ObserverTy {
   ASTContext &Ctx;
   Diagnostic &Diags;
+  EverKilled EK;
 public:
-  DeadStoreObserver(ASTContext &ctx, Diagnostic &diags)
-    : Ctx(ctx), Diags(diags) {
-  }
+  DeadStoreObs(ASTContext &ctx,Diagnostic &diags) : Ctx(ctx), Diags(diags){}    
+  virtual ~DeadStoreObs() {}
+  
+  virtual void ObserveStmt(Stmt* S,
+                           const LiveVariables::AnalysisDataTy& AD,
+                           const LiveVariables::ValTy& Live) {
     
-  virtual ~DeadStoreObserver() {}
-
-  virtual void ObserveStmt(Stmt* S, LiveVariables& L, llvm::BitVector& Live) {                                 
     if (BinaryOperator* B = dyn_cast<BinaryOperator>(S)) {    
-      // Is this an assignment?
-      if (!B->isAssignmentOp())
-        return;
+      if (!B->isAssignmentOp()) return; // Skip non-assignments.
       
-      // Is this an assignment to a variable?
       if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(B->getLHS()))
-        // Is the variable live?
-        if (!L.isLive(Live,cast<VarDecl>(DR->getDecl()))) {
+        // Is the variable NOT live?  If so, flag a dead store.
+        if (!Live(AD,DR->getDecl())) {
           SourceRange R = B->getRHS()->getSourceRange();
           Diags.Report(DR->getSourceRange().Begin(), diag::warn_dead_store,
-                       0, 0, &R, 1);
-                                                                        
+                       0, 0, &R, 1);                                                                        
         }
     }
-    else if(DeclStmt* DS = dyn_cast<DeclStmt>(S)) {
-      // Iterate through the decls.  Warn if any of them (which have
-      // initializers) are not live.
+    else if(DeclStmt* DS = dyn_cast<DeclStmt>(S))
+      // Iterate through the decls.  Warn if any initializers are complex
+      // expressions that are not live (never used).
       for (VarDecl* V = cast<VarDecl>(DS->getDecl()); V != NULL ; 
-                    V = cast_or_null<VarDecl>(V->getNextDeclarator()))
-        if (Expr* E = V->getInit())
-          if (!L.isLive(Live,V))
+                    V = cast_or_null<VarDecl>(V->getNextDeclarator())) {
+        if (Expr* E = V->getInit()) {
+          if (!Live(AD,DS->getDecl())) {
             // Special case: check for initializations with constants.
             //
             //  e.g. : int x = 0;
@@ -63,14 +70,15 @@
             // If x is EVER assigned a new value later, don't issue
             // a warning.  This is because such initialization can be
             // due to defensive programming.
-            if (!E->isConstantExpr(Ctx,NULL) || 
-                L.getVarInfo(V).Kills.size() == 0) {
+            if (!E->isConstantExpr(Ctx,NULL)) {
               // Flag a warning.
               SourceRange R = E->getSourceRange();
               Diags.Report(V->getLocation(), diag::warn_dead_store, 0, 0,
                            &R,1);
             }
-    }
+          }
+        }
+      }
   }
 };
   
@@ -78,18 +86,11 @@
 
 namespace clang {
 
-void CheckDeadStores(CFG& cfg, LiveVariables& L,
-                     ASTContext &Ctx, Diagnostic &Diags) {
-  DeadStoreObserver A(Ctx, Diags);
-  
-  for (CFG::iterator I = cfg.begin(), E = cfg.end(); I != E; ++I)
-    L.runOnBlock(&(*I),&A);
-}
-
 void CheckDeadStores(CFG& cfg, ASTContext &Ctx, Diagnostic &Diags) {
   LiveVariables L;
   L.runOnCFG(cfg);
-  CheckDeadStores(cfg,L, Ctx, Diags);
+  DeadStoreObs A(Ctx, Diags);
+  L.runOnAllBlocks(cfg,A);
 }
 
 } // end namespace clang

Modified: cfe/trunk/Analysis/LiveVariables.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Analysis/LiveVariables.cpp?rev=42293&r1=42292&r2=42293&view=diff

==============================================================================
--- cfe/trunk/Analysis/LiveVariables.cpp (original)
+++ cfe/trunk/Analysis/LiveVariables.cpp Mon Sep 24 23:31:27 2007
@@ -3,7 +3,8 @@
 //                     The LLVM Compiler Infrastructure
 //
 // This file was developed by Ted Kremenek and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// the University of Illinois Open Source License. See LICENSE.TXT for
+// details.
 //
 //===----------------------------------------------------------------------===//
 //
@@ -15,7 +16,8 @@
 #include "clang/Basic/SourceManager.h"
 #include "clang/AST/Expr.h"
 #include "clang/AST/CFG.h"
-#include "clang/Analysis/Visitors/DataflowStmtVisitor.h"
+#include "clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h"
+#include "DataflowSolver.h"
 #include "clang/Lex/IdentifierTable.h"
 #include "llvm/ADT/SmallPtrSet.h"
 
@@ -25,326 +27,136 @@
 using namespace clang;
 
 //===----------------------------------------------------------------------===//
-// RegisterDecls - Utility class to create VarInfo objects for all
-//                 Decls referenced in a function.
-//
+// Dataflow initialization logic.
+//===----------------------------------------------------------------------===//      
 
 namespace {
+struct RegisterDecls : public CFGRecStmtDeclVisitor<RegisterDecls> {
+  LiveVariables::AnalysisDataTy& AD;
+  void VisitVarDecl(VarDecl* VD) { AD.RegisterDecl(VD); }
 
-class RegisterDecls : public StmtVisitor<RegisterDecls,void> {
-  LiveVariables& L;
-  const CFG& cfg;
-public:  
-  RegisterDecls(LiveVariables& l, const CFG& c)
-    : L(l), cfg(c) {}
-    
-  void VisitStmt(Stmt* S);
-  void VisitDeclRefExpr(DeclRefExpr* DR);
-  void VisitDeclStmt(DeclStmt* DS);
-  void Register(ScopedDecl* D);
-  void RegisterDeclChain(ScopedDecl* D);
-  void RegisterUsedDecls();
-};
-
-void RegisterDecls::VisitStmt(Stmt* S) {
-  for (Stmt::child_iterator I = S->child_begin(),E = S->child_end(); I != E;++I)
-    Visit(*I);
-}
-
-void RegisterDecls::VisitDeclRefExpr(DeclRefExpr* DR) {
-  RegisterDeclChain(DR->getDecl());
-}
-
-void RegisterDecls::VisitDeclStmt(DeclStmt* DS) {
-  RegisterDeclChain(DS->getDecl());
-}
-
-void RegisterDecls::RegisterDeclChain(ScopedDecl* D) {
-  for (; D != NULL ; D = D->getNextDeclarator())
-    Register(D);
-}
-
-void RegisterDecls::Register(ScopedDecl* D) {
-  if (VarDecl* V = dyn_cast<VarDecl>(D)) {
-    LiveVariables::VPair& VP = L.getVarInfoMap()[V];
-
-    VP.V.AliveBlocks.resize(cfg.getNumBlockIDs());
-    VP.Idx = L.getNumDecls()++;
-  }
-}
+  RegisterDecls(LiveVariables::AnalysisDataTy& ad) : AD(ad) {}
+};  
+} // end anonymous namespace
 
-void RegisterDecls::RegisterUsedDecls() {
-  for (CFG::const_iterator BI = cfg.begin(), BE = cfg.end(); BI != BE; ++BI)
-    for (CFGBlock::const_iterator SI=BI->begin(),SE = BI->end();SI != SE;++SI)
-      Visit(const_cast<Stmt*>(*SI));
+void LiveVariables::InitializeValues(const CFG& cfg) {
+  RegisterDecls R(getAnalysisData());
+  cfg.VisitBlockStmts(R);
 }
-  
-  
-} // end anonymous namespace
 
 //===----------------------------------------------------------------------===//
-// WorkList - Data structure representing the liveness algorithm worklist.
-//
+// Transfer functions.
+//===----------------------------------------------------------------------===//      
 
 namespace {
-
-class WorkListTy {
-  typedef llvm::SmallPtrSet<const CFGBlock*,20> BlockSet;
-  BlockSet wlist;
+class TransferFuncs : public CFGStmtVisitor<TransferFuncs> {
+  LiveVariables::AnalysisDataTy& AD;
+  LiveVariables::ValTy Live;
 public:
-  void enqueue(const CFGBlock* B) { wlist.insert(B); }
-      
-  const CFGBlock* dequeue() {
-    assert (!wlist.empty());
-    const CFGBlock* B = *wlist.begin();
-    wlist.erase(B);
-    return B;          
-  }
-  
-  bool isEmpty() const { return wlist.empty(); }
-};
+  TransferFuncs(LiveVariables::AnalysisDataTy& ad) : AD(ad) {}
 
-} // end anonymous namespace
-
-//===----------------------------------------------------------------------===//
-// TFuncs
-//
-
-namespace {
-
-class LivenessTFuncs : public DataflowStmtVisitor<LivenessTFuncs,
-                                              dataflow::backward_analysis_tag> {
-  LiveVariables& L;
-  llvm::BitVector Live;
-  llvm::BitVector KilledAtLeastOnce;
-  Stmt* CurrentStmt;
-  const CFGBlock* CurrentBlock;
-  bool blockPreviouslyProcessed;
-  LiveVariablesObserver* Observer;
-
-public:
-  LivenessTFuncs(LiveVariables& l, LiveVariablesObserver* A = NULL)
-    : L(l), CurrentStmt(NULL), CurrentBlock(NULL),
-      blockPreviouslyProcessed(false), Observer(A) {
-    Live.resize(l.getNumDecls());
-    KilledAtLeastOnce.resize(l.getNumDecls());
-  }
+  LiveVariables::ValTy& getVal() { return Live; }
   
   void VisitDeclRefExpr(DeclRefExpr* DR);
   void VisitBinaryOperator(BinaryOperator* B);
   void VisitAssign(BinaryOperator* B);
   void VisitDeclStmt(DeclStmt* DS);
   void VisitUnaryOperator(UnaryOperator* U);
-  void ObserveStmt(Stmt* S);
-
-  unsigned getIdx(const VarDecl* D) {
-    LiveVariables::VarInfoMap& V = L.getVarInfoMap();
-    LiveVariables::VarInfoMap::iterator I = V.find(D);
-    assert (I != V.end());
-    return I->second.Idx;
+  void VisitStmt(Stmt* S) { VisitChildren(S); }
+  void Visit(Stmt *S) {
+    if (AD.Observer) AD.Observer->ObserveStmt(S,AD,Live);
+    static_cast<CFGStmtVisitor<TransferFuncs>*>(this)->Visit(S);
   }
-  
-  bool ProcessBlock(const CFGBlock* B);
-  llvm::BitVector* getBlockEntryLiveness(const CFGBlock* B);
-  LiveVariables::VarInfo& KillVar(VarDecl* D);
 };
 
-void LivenessTFuncs::ObserveStmt(Stmt* S) { 
-  if (Observer) Observer->ObserveStmt(S,L,Live); 
-}
-
-void LivenessTFuncs::VisitDeclRefExpr(DeclRefExpr* DR) {
-  // Register a use of the variable.
-  if (VarDecl* V = dyn_cast<VarDecl>(DR->getDecl()))
-    Live.set(getIdx(V));
+void TransferFuncs::VisitDeclRefExpr(DeclRefExpr* DR) {
+  if (VarDecl* V = dyn_cast<VarDecl>(DR->getDecl())) 
+    Live.set(AD[V]);   // Register a use of the variable.
 }
   
-void LivenessTFuncs::VisitBinaryOperator(BinaryOperator* B) {     
+void TransferFuncs::VisitBinaryOperator(BinaryOperator* B) {     
   if (B->isAssignmentOp()) VisitAssign(B);
   else VisitStmt(B);
 }
 
-void LivenessTFuncs::VisitUnaryOperator(UnaryOperator* U) {
+void TransferFuncs::VisitUnaryOperator(UnaryOperator* U) {
   switch (U->getOpcode()) {
-    case UnaryOperator::PostInc:
-    case UnaryOperator::PostDec:
-    case UnaryOperator::PreInc:
-    case UnaryOperator::PreDec:
-    case UnaryOperator::AddrOf:
-      // Walk through the subexpressions, blasting through ParenExprs until
-      // we either find a DeclRefExpr or some non-DeclRefExpr expression.
-      for (Stmt* S = U->getSubExpr() ; ; ) {
-        if (ParenExpr* P = dyn_cast<ParenExpr>(S)) {
-          S = P->getSubExpr();
-          continue;
-        }
-        else if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(S)) {
-          // Treat the --/++/& operator as a kill.
-          LiveVariables::VarInfo& V = 
-            KillVar(cast<VarDecl>(DR->getDecl()));
-
-          if (!blockPreviouslyProcessed)
-            V.AddKill(CurrentStmt,DR); 
-        
-          VisitDeclRefExpr(DR);          
-        }
-        else Visit(S);
-          
-        break;                  
-      }        
-      break;      
-    
-    default:
-      Visit(U->getSubExpr());
-      break;
+  case UnaryOperator::PostInc:
+  case UnaryOperator::PostDec:
+  case UnaryOperator::PreInc:
+  case UnaryOperator::PreDec:
+  case UnaryOperator::AddrOf:
+    // Walk through the subexpressions, blasting through ParenExprs
+    // until we either find a DeclRefExpr or some non-DeclRefExpr
+    // expression.
+    for (Stmt* S = U->getSubExpr() ;;) {
+      if (ParenExpr* P = dyn_cast<ParenExpr>(S)) { S=P->getSubExpr(); continue;} 
+      else if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(S)) {
+        // Treat the --/++/& operator as a kill.
+        Live.reset(AD[DR->getDecl()]);
+        if (AD.Observer) AD.Observer->ObserverKill(DR);
+        VisitDeclRefExpr(DR);          
+      }
+      else Visit(S);
+
+      break;   
+    }        
+    break;
+  
+  default:
+    Visit(U->getSubExpr());
+    break;
   }
 }
 
-LiveVariables::VarInfo& LivenessTFuncs::KillVar(VarDecl* D) {
-  LiveVariables::VarInfoMap::iterator I =  L.getVarInfoMap().find(D);
-  
-  assert (I != L.getVarInfoMap().end() && 
-          "Declaration not managed by variable map in LiveVariables");
-  
-  // Mark the variable dead, and remove the current block from
-  // the set of blocks where the variable may be alive the entire time.
-  Live.reset(I->second.Idx);
-  I->second.V.AliveBlocks.reset(CurrentBlock->getBlockID());
-  
-  return I->second.V;
-}  
-
-void LivenessTFuncs::VisitAssign(BinaryOperator* B) {    
-  // Check if we are assigning to a variable.
+void TransferFuncs::VisitAssign(BinaryOperator* B) {    
   Stmt* LHS = B->getLHS();
-  
-  if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(LHS)) {
-    LiveVariables::VarInfo& V = KillVar(cast<VarDecl>(DR->getDecl()));
-    
-    // We only need to register kills once, so we check if this block
-    // has been previously processed.
-    if (!blockPreviouslyProcessed)
-      V.AddKill(CurrentStmt,DR);
-      
-    if (B->getOpcode() != BinaryOperator::Assign)
-      Visit(LHS);
+
+  if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(LHS)) { // Assigning to a var?    
+    Live.reset(AD[DR->getDecl()]);
+    if (AD.Observer) AD.Observer->ObserverKill(DR);
+    // Handle things like +=, etc., which also generate "uses"
+    // of a variable.  Do this just by visiting the subexpression.
+    if (B->getOpcode() != BinaryOperator::Assign) Visit(LHS);
   }
-  else
+  else // Not assigning to a variable.  Process LHS as usual.
     Visit(LHS);
   
-  Visit(B->getRHS());    
+  Visit(B->getRHS());
 }
 
-void LivenessTFuncs::VisitDeclStmt(DeclStmt* DS) {
-  // Declarations effectively "kill" a variable since they cannot possibly
-  // be live before they are declared.  Declarations, however, are not kills
-  // in the sense that the value is obliterated, so we do not register
-  // DeclStmts as a "kill site" for a variable.
+void TransferFuncs::VisitDeclStmt(DeclStmt* DS) {
+  // Declarations effectively "kill" a variable since they cannot
+  // possibly be live before they are declared.
   for (ScopedDecl* D = DS->getDecl(); D != NULL ; D = D->getNextDeclarator())
-    KillVar(cast<VarDecl>(D));
-}
-
-llvm::BitVector* LivenessTFuncs::getBlockEntryLiveness(const CFGBlock* B) {
-  LiveVariables::BlockLivenessMap& BMap = L.getLiveAtBlockEntryMap();
-
-  LiveVariables::BlockLivenessMap::iterator I = BMap.find(B);
-  return (I == BMap.end()) ? NULL : &(I->second);  
+    Live.reset(AD[D]);
 }
+} // end anonymous namespace
 
-  
-bool LivenessTFuncs::ProcessBlock(const CFGBlock* B) {
-
-  CurrentBlock = B;
-  Live.reset();
-  KilledAtLeastOnce.reset();
-  
-  // Check if this block has been previously processed.
-  LiveVariables::BlockLivenessMap& BMap = L.getLiveAtBlockEntryMap();
-  LiveVariables::BlockLivenessMap::iterator BI = BMap.find(B);
-    
-  blockPreviouslyProcessed = BI != BMap.end();
-  
-  // Merge liveness information from all predecessors.
-  for (CFGBlock::const_succ_iterator I=B->succ_begin(),E=B->succ_end();I!=E;++I)
-    if (llvm::BitVector* V = getBlockEntryLiveness(*I))    
-      Live |= *V;
-
-  if (Observer)
-    Observer->ObserveBlockExit(B,L,Live);    
-      
-  // Tentatively mark all variables alive at the end of the current block
-  // as being alive during the whole block.  We then cull these out as
-  // we process the statements of this block.
-  for (LiveVariables::VarInfoMap::iterator
-         I=L.getVarInfoMap().begin(), E=L.getVarInfoMap().end(); I != E; ++I)
-    if (Live[I->second.Idx])
-      I->second.V.AliveBlocks.set(B->getBlockID());                              
-
-  // Visit the statements in reverse order;
-  VisitBlock(B);
-  
-  // Compare the computed "Live" values with what we already have
-  // for the entry to this block.
-  bool hasChanged = false;
-  
-  if (!blockPreviouslyProcessed) {
-    // We have not previously calculated liveness information for this block.
-    // Lazily instantiate a bitvector, and copy the bits from Live.
-    hasChanged = true;
-    llvm::BitVector& V = BMap[B];
-    V.resize(L.getNumDecls());
-    V = Live;
-  }
-  else if (BI->second != Live) {
-    hasChanged = true;
-    BI->second = Live;
+namespace {
+struct Merge {
+  void operator()(LiveVariables::ValTy& Dst, LiveVariables::ValTy& Src) {
+    Src |= Dst;
   }
-  
-  return hasChanged;
-}
-
+};
 } // end anonymous namespace
 
-//===----------------------------------------------------------------------===//
-// runOnCFG - Method to run the actual liveness computation.
-//
-
-void LiveVariables::runOnCFG(const CFG& cfg, LiveVariablesObserver* Observer) {
-  // Scan a CFG for DeclRefStmts.  For each one, create a VarInfo object.
-  {
-    RegisterDecls R(*this,cfg);
-    R.RegisterUsedDecls();
-  }
-  
-  // Create the worklist and enqueue the exit block.
-  WorkListTy WorkList;
-  WorkList.enqueue(&cfg.getExit());
-  
-  // Create the state for transfer functions.
-  LivenessTFuncs TF(*this,Observer);
-  
-  // Process the worklist until it is empty.
-  
-  while (!WorkList.isEmpty()) {
-    const CFGBlock* B = WorkList.dequeue();
-    if (TF.ProcessBlock(B))
-      for (CFGBlock::const_pred_iterator I = B->pred_begin(), E = B->pred_end();
-           I != E; ++I)
-        WorkList.enqueue(*I);    
-  }
-  
-  // Go through each block and reserve a bitvector.  This is needed if
-  // a block was never visited by the worklist algorithm.
-  for (CFG::const_iterator I = cfg.begin(), E = cfg.end(); I != E; ++I)
-    LiveAtBlockEntryMap[&(*I)].resize(NumDecls);        
+namespace {
+typedef DataflowSolver<LiveVariables,TransferFuncs,Merge> Solver;
 }
 
+void LiveVariables::runOnCFG(const CFG& cfg) {
+  Solver S(*this);
+  S.runOnCFG(cfg);
+}
 
-void LiveVariables::runOnBlock(const CFGBlock* B,
-                               LiveVariablesObserver* Observer)
-{
-  LivenessTFuncs TF(*this,Observer);
-  TF.ProcessBlock(B);
+void LiveVariables::runOnAllBlocks(const CFG& cfg,
+                                   LiveVariables::ObserverTy& Obs) {
+  Solver S(*this);
+  ObserverTy* OldObserver = getAnalysisData().Observer;
+  getAnalysisData().Observer = &Obs;
+  S.runOnAllBlocks(cfg);
+  getAnalysisData().Observer = OldObserver;
 }
 
 //===----------------------------------------------------------------------===//
@@ -352,81 +164,36 @@
 //
 
 bool LiveVariables::isLive(const CFGBlock* B, const VarDecl* D) const {
-  BlockLivenessMap::const_iterator I = LiveAtBlockEntryMap.find(B);
-  assert (I != LiveAtBlockEntryMap.end());
-  
-  VarInfoMap::const_iterator VI = VarInfos.find(D);
-  assert (VI != VarInfos.end());
-  
-  return I->second[VI->second.Idx];
+  return getBlockData(B)[ getAnalysisData()[D] ];
 }
 
-bool LiveVariables::isLive(llvm::BitVector& Live, const VarDecl* D) const {
-  VarInfoMap::const_iterator VI = VarInfos.find(D);
-  assert (VI != VarInfos.end());
-  return Live[VI->second.Idx];
-}
-
-bool LiveVariables::KillsVar(const Stmt* S, const VarDecl* D) const {
-  VarInfoMap::const_iterator VI = VarInfos.find(D);
-  assert (VI != VarInfos.end());
-  
-  for (VarInfo::KillsSet::const_iterator
-         I = VI->second.V.Kills.begin(), E = VI->second.V.Kills.end(); I!=E;++I)
-    if (I->first == S)
-      return true;
-      
-  return false;        
-}
-
-LiveVariables::VarInfo& LiveVariables::getVarInfo(const VarDecl* D) {
-  VarInfoMap::iterator VI = VarInfos.find(D);
-  assert (VI != VarInfos.end());
-  return VI->second.V;
-}
-
-const LiveVariables::VarInfo& LiveVariables::getVarInfo(const VarDecl* D) const{
-  return const_cast<LiveVariables*>(this)->getVarInfo(D);
+bool LiveVariables::isLive(const ValTy& Live, const VarDecl* D) const {
+  return Live[ getAnalysisData()[D] ];
 }
 
 //===----------------------------------------------------------------------===//
-// Defaults for LiveVariablesObserver
-
-void LiveVariablesObserver::ObserveStmt(Stmt* S, LiveVariables& L,
-                                        llvm::BitVector& V) {}
-
-void LiveVariablesObserver::ObserveBlockExit(const CFGBlock* B,
-                                             LiveVariables& L,
-                                             llvm::BitVector& V) {}
-                            
-//===----------------------------------------------------------------------===//
 // printing liveness state for debugging
 //
 
-void LiveVariables::dumpLiveness(const llvm::BitVector& V,
-                                 SourceManager& SM) const {
-
-  for (VarInfoMap::iterator I = VarInfos.begin(), E=VarInfos.end(); I!=E; ++I) {
-    if (V[I->second.Idx]) {
-      
+void LiveVariables::dumpLiveness(const ValTy& V, SourceManager& SM) const {
+  const AnalysisDataTy& AD = getAnalysisData();
+  
+  for (AnalysisDataTy::iterator I = AD.begin(), E = AD.end(); I!=E; ++I)
+    if (V[I->second]) {      
       SourceLocation PhysLoc = SM.getPhysicalLoc(I->first->getLocation());
-
+    
       fprintf(stderr, "  %s <%s:%u:%u>\n", 
               I->first->getIdentifier()->getName(),
               SM.getSourceName(PhysLoc),
               SM.getLineNumber(PhysLoc),
               SM.getColumnNumber(PhysLoc));
     }
-  }  
 }                                  
 
 void LiveVariables::dumpBlockLiveness(SourceManager& M) const {
-  for (BlockLivenessMap::iterator I = LiveAtBlockEntryMap.begin(),
-                                  E = LiveAtBlockEntryMap.end();
-       I != E; ++I) {
-
-    fprintf(stderr,
-            "\n[ B%d (live variables at block entry) ]\n",
+  for (BlockDataMapTy::iterator I = getBlockDataMap().begin(),
+       E = getBlockDataMap().end(); I!=E; ++I) {
+    fprintf(stderr, "\n[ B%d (live variables at block exit) ]\n",
             I->first->getBlockID());
             
     dumpLiveness(I->second,M);
@@ -434,41 +201,3 @@
 
   fprintf(stderr,"\n");
 }
-
-void LiveVariables::dumpVarLiveness(SourceManager& SM) const {
-  
-  for (VarInfoMap::iterator I = VarInfos.begin(), E=VarInfos.end(); I!=E; ++I) {      
-      SourceLocation PhysLoc = SM.getPhysicalLoc(I->first->getLocation());
-      
-    fprintf(stderr, "[ %s <%s:%u:%u> ]\n", 
-            I->first->getIdentifier()->getName(),
-            SM.getSourceName(PhysLoc),
-            SM.getLineNumber(PhysLoc),
-            SM.getColumnNumber(PhysLoc));
-            
-    I->second.V.Dump(SM);
-  } 
-}                                  
-
-void LiveVariables::VarInfo::Dump(SourceManager& SM) const {
-  fprintf(stderr,"  Blocks Alive:");
-  for (unsigned i = 0; i < AliveBlocks.size(); ++i) {
-    if (i % 5 == 0)
-      fprintf(stderr,"\n    ");
-
-    fprintf(stderr," B%d", i);
-  }
-  
-  fprintf(stderr,"\n  Kill Sites:\n");
-  for (KillsSet::const_iterator I = Kills.begin(), E = Kills.end(); I!=E; ++I) {
-    SourceLocation PhysLoc = 
-      SM.getPhysicalLoc(I->second->getSourceRange().Begin());
-      
-    fprintf(stderr, "    <%s:%u:%u>\n",
-            SM.getSourceName(PhysLoc),
-            SM.getLineNumber(PhysLoc),
-            SM.getColumnNumber(PhysLoc));
-  }
-  
-  fprintf(stderr,"\n");
-}

Modified: cfe/trunk/Driver/ASTStreamers.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Driver/ASTStreamers.cpp?rev=42293&r1=42292&r2=42293&view=diff

==============================================================================
--- cfe/trunk/Driver/ASTStreamers.cpp (original)
+++ cfe/trunk/Driver/ASTStreamers.cpp Mon Sep 24 23:31:27 2007
@@ -224,8 +224,7 @@
     virtual void VisitCFG(CFG& C) {
       LiveVariables L;
       L.runOnCFG(C);
-      L.dumpBlockLiveness(*SM);    
-      L.dumpVarLiveness(*SM);
+      L.dumpBlockLiveness(*SM);
     }
   };
 } // end anonymous namespace

Modified: cfe/trunk/include/clang/Analysis/DataflowValues.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/DataflowValues.h?rev=42293&r1=42292&r2=42293&view=diff

==============================================================================
--- cfe/trunk/include/clang/Analysis/DataflowValues.h (original)
+++ cfe/trunk/include/clang/Analysis/DataflowValues.h Mon Sep 24 23:31:27 2007
@@ -64,7 +64,6 @@
   struct forward_analysis_tag {};
   struct backward_analysis_tag {};
 } // end namespace dataflow
-    
 
 //===----------------------------------------------------------------------===//
 /// DataflowValues.  Container class to store dataflow values for a CFG.
@@ -83,6 +82,7 @@
   typedef typename ValueTypes::AnalysisDataTy      AnalysisDataTy;  
   typedef _AnalysisDirTag                          AnalysisDirTag;
   typedef llvm::DenseMap<CFG::Edge, ValTy>         EdgeDataMapTy;
+  typedef llvm::DenseMap<const CFGBlock*, ValTy>   BlockDataMapTy;
 
   //===--------------------------------------------------------------------===//
   // Predicates.
@@ -110,10 +110,9 @@
   ///  dataflow analysis.  This method is usually specialized by subclasses.
   void InitializeValues(const CFG& cfg) {};  
 
-  /// getEdgeData - Retrieves the dataflow values associated with a 
-  ///  specified CFGBlock.  If the dataflow analysis is a forward analysis,
-  ///  this data is associated with the END of the block.  If the analysis
-  ///  is a backwards analysis, it is associated with the ENTRY of the block.
+
+  /// getEdgeData - Retrieves the dataflow values associated with a
+  ///  CFG edge.
   ValTy& getEdgeData(const CFG::Edge& E) {
     typename EdgeDataMapTy::iterator I = EdgeDataMap.find(E);
     assert (I != EdgeDataMap.end() && "No data associated with Edge.");
@@ -123,13 +122,35 @@
   const ValTy& getEdgeData(const CFG::Edge& E) const {
     return reinterpret_cast<DataflowValues*>(this)->getEdgeData(E);
   }  
+
+  /// getBlockData - Retrieves the dataflow values associated with a 
+  ///  specified CFGBlock.  If the dataflow analysis is a forward analysis,
+  ///  this data is associated with the END of the block.  If the analysis
+  ///  is a backwards analysis, it is associated with the ENTRY of the block.  
+  ValTy& getBlockData(const CFGBlock* B) {
+    typename BlockDataMapTy::iterator I = BlockDataMap.find(B);
+    assert (I != BlockDataMap.end() && "No data associated with block.");
+    return I->second;
+  }
   
-  /// getEdgeDataMap - Retrieves the internal map between CFGBlocks and
+  const ValTy& getBlockData(const CFGBlock* B) const {
+    return const_cast<DataflowValues*>(this)->getBlockData(B);
+  }  
+  
+  /// getEdgeDataMap - Retrieves the internal map between CFG edges and
   ///  dataflow values.  Usually used by a dataflow solver to compute
   ///  values for blocks.
   EdgeDataMapTy& getEdgeDataMap() { return EdgeDataMap; }
   const EdgeDataMapTy& getEdgeDataMap() const { return EdgeDataMap; }
 
+  /// getBlockDataMap - Retrieves the internal map between CFGBlocks and
+  /// dataflow values.  If the dataflow analysis operates in the forward
+  /// direction, the values correspond to the dataflow values at the start
+  /// of the block.  Otherwise, for a backward analysis, the values correpsond
+  /// to the dataflow values at the end of the block.
+  BlockDataMapTy& getBlockDataMap() { return BlockDataMap; }
+  const BlockDataMapTy& getBlockDataMap() const { return BlockDataMap; }
+
   /// getAnalysisData - Retrieves the meta data associated with a 
   ///  dataflow analysis for analyzing a particular CFG.  
   ///  This is typically consumed by transfer function code (via the solver).
@@ -143,6 +164,7 @@
   
 protected:
   EdgeDataMapTy      EdgeDataMap;
+  BlockDataMapTy     BlockDataMap;
   AnalysisDataTy     AnalysisData;
 };          
 

Modified: cfe/trunk/include/clang/Analysis/LiveVariables.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/LiveVariables.h?rev=42293&r1=42292&r2=42293&view=diff

==============================================================================
--- cfe/trunk/include/clang/Analysis/LiveVariables.h (original)
+++ cfe/trunk/include/clang/Analysis/LiveVariables.h Mon Sep 24 23:31:27 2007
@@ -14,139 +14,137 @@
 #ifndef LLVM_CLANG_LIVEVARIABLES_H
 #define LLVM_CLANG_LIVEVARIABLES_H
 
+#include "clang/AST/Decl.h"
+#include "clang/Analysis/DataflowValues.h"
 #include "llvm/ADT/BitVector.h"
 #include "llvm/ADT/DenseMap.h"
-#include <vector>
 
 namespace clang {
 
-  class Stmt;
-  class DeclRefExpr;
-  class VarDecl;
-  class CFG;
-  class CFGBlock;
-  class SourceManager;
-  class LiveVariables;
-  
-class LiveVariablesObserver {
-public:
-  virtual ~LiveVariablesObserver() {}
+class Stmt;
+class DeclRefExpr;
+class SourceManager;
+  
+struct LiveVariables_ValueTypes {
+  //===-----------------------------------------------------===//
+  // AnalysisDataTy - Whole-function analysis meta data.
+  //===-----------------------------------------------------===//
+
+  class ObserverTy;
+  
+  class AnalysisDataTy {
+    typedef llvm::DenseMap<const VarDecl*, unsigned> VMapTy;
+    VMapTy M;
+    unsigned NDecls;
+   public:
+    ObserverTy* Observer;
+    
+    AnalysisDataTy() : NDecls(0), Observer(NULL) {}
+    
+    bool Tracked(const VarDecl* VD) const { return M.find(VD) != M.end(); }
+    void RegisterDecl(const VarDecl* VD) { if (!Tracked(VD)) M[VD] = NDecls++; }
 
-  /// ObserveStmt - A callback invoked right before invoking the liveness
-  ///  transfer function on the given statement.  If the liveness information
-  ///  has been previously calculated by running LiveVariables::runOnCFG,
-  ///  then V contains the liveness information after the execution of
-  ///  the given statement.
-  virtual void ObserveStmt(Stmt* S, LiveVariables& L, llvm::BitVector& V);
-
-  /// ObserveBlockExit - A callback invoked right before invoking the liveness
-  ///  transfer function on the given block.  If the liveness information
-  ///  has been previously calculated by running LiveVariables::runOnCFG,
-  ///  then V contains the liveness information after the execution of
-  ///  the given block.
-  virtual void ObserveBlockExit(const CFGBlock* B, LiveVariables& L,
-                                llvm::BitVector& V);
-};
+    unsigned operator[](const VarDecl* VD) const {
+      VMapTy::const_iterator I = M.find(VD);
+      assert (I != M.end());
+      return I->second;
+    }
+    
+    unsigned operator[](const ScopedDecl* S) const {
+      return (*this)[cast<VarDecl>(S)];
+    }
 
-class LiveVariables {
-public:
+    unsigned getNumDecls() const { return NDecls; }
+    
+    typedef VMapTy::const_iterator iterator;
+    iterator begin() const { return M.begin(); }
+    iterator end() const { return M.end(); }
+  };
+  
+  //===-----------------------------------------------------===//
+  // ValTy - Dataflow value.
+  //===-----------------------------------------------------===//
+  class ValTy {
+    llvm::BitVector V;
+  public:
+    void copyValues(const ValTy& RHS) { V = RHS.V; }
 
-  struct VarInfo {
-    /// AliveBlocks - Set of blocks of which this value is alive completely
-    /// through.  This is a bit set which uses the basic block number as an
-    /// index.
-    llvm::BitVector AliveBlocks;
-    
-    /// Kills - List of statements which are the last use of a variable
-    ///  (kill it) in their basic block.  The first pointer in the pair
-    ///  is the statement in the list of statements of a basic block where
-    ///  this occurs, while the DeclRefExpr is the subexpression of this
-    ///  statement where the actual last reference takes place.
-    typedef std::vector< std::pair<const Stmt*,const DeclRefExpr*> > KillsSet;
-    KillsSet Kills;
-    
-    // AddKill - Adds a kill site to the list of places where a
-    //  a variable is killed.
-    void AddKill(Stmt* S, DeclRefExpr* DR) {
-      Kills.push_back(std::make_pair(const_cast<const Stmt*>(S),
-                                     const_cast<const DeclRefExpr*>(DR)));
+    bool operator==(const ValTy& RHS) const { return V == RHS.V; }
+    
+    void resetValues(const AnalysisDataTy& AD) {
+      V.resize(AD.getNumDecls());
+      V.reset();
     }
+          
+    llvm::BitVector::reference operator[](unsigned i) {
+      assert (i < V.size() && "Liveness bitvector access is out-of-bounds.");
+      return V[i];
+    }
+    
+    const llvm::BitVector::reference operator[](unsigned i) const {
+      return const_cast<ValTy&>(*this)[i];
+    }
+    
+    bool operator()(const AnalysisDataTy& AD, const ScopedDecl* D) const {
+      return (*this)[AD[D]];
+    }
+    
+    ValTy& operator|=(ValTy& RHS) { V |= RHS.V; return *this; }
     
-    // Dump - prints VarInfo data to stderr.
-    void Dump(SourceManager& M) const;
+    void set(unsigned i) { V.set(i); }
+    void reset(unsigned i) { V.reset(i); }
   };
   
-  struct VPair {
-    VarInfo V;
-    unsigned Idx;
+  //===-----------------------------------------------------===//
+  // ObserverTy - Observer for uninitialized values queries.
+  //===-----------------------------------------------------===//
+  class ObserverTy {
+  public:
+    virtual ~ObserverTy() {}
+    
+    /// ObserveStmt - A callback invoked right before invoking the
+    ///  liveness transfer function on the given statement.
+    virtual void ObserveStmt(Stmt* S, const AnalysisDataTy& AD, 
+                             const ValTy& V) {}
+    
+    virtual void ObserverKill(DeclRefExpr* DR) {}
   };
-  
-  typedef llvm::DenseMap<const VarDecl*, VPair > VarInfoMap;
-  typedef llvm::DenseMap<const CFGBlock*, llvm::BitVector > BlockLivenessMap;
+};
 
+class LiveVariables : public DataflowValues<LiveVariables_ValueTypes,
+                                            dataflow::backward_analysis_tag> {
 public:
-
-  LiveVariables() : NumDecls(0) {}
-
-  /// runOnCFG - Computes live variable information for a given CFG.
-  void runOnCFG(const CFG& cfg, LiveVariablesObserver* A = NULL);
-  
-  /// runOnBlock - Computes live variable information for a given block.
-  ///  This should usually be invoked only after previously computing
-  ///  live variable information using runOnCFG, and is intended to
-  ///  only be used for auditing the liveness within a block.
-  void runOnBlock(const CFGBlock* B, LiveVariablesObserver* A);
-  
-  /// KillsVar - Return true if the specified statement kills the
-  ///  specified variable.
-  bool KillsVar(const Stmt* S, const VarDecl* D) const;
+  typedef LiveVariables_ValueTypes::ObserverTy ObserverTy;
+    
+  LiveVariables() {}
   
-  /// IsLive - Return true if a variable is live at beginning of a specified
-  //    block.
+  /// IsLive - Return true if a variable is live at beginning of a
+  /// specified block.
   bool isLive(const CFGBlock* B, const VarDecl* D) const;
   
-  /// IsLive - Return true if a variable is live according to the provided
-  ///  livness bitvector.  This is typically used by classes that subclass
-  ///  LiveVariablesObserver.
-  bool isLive(llvm::BitVector& V, const VarDecl* D) const;
-  
-  /// getVarInfo - Return the liveness information associated with a given
-  ///  variable.
-  VarInfo& getVarInfo(const VarDecl* D);
-
-  const VarInfo& getVarInfo(const VarDecl* D) const;
+  /// IsLive - Return true if a variable is live according to the
+  ///  provided livness bitvector.
+  bool isLive(const ValTy& V, const VarDecl* D) const;
+  
+  /// dumpLiveness - Print to stderr the liveness information encoded
+  ///  by a specified bitvector.
+  void dumpLiveness(const ValTy& V, SourceManager& M) const;
   
-  /// getVarInfoMap
-  VarInfoMap& getVarInfoMap() { return VarInfos; }
-
-  const VarInfoMap& getVarInfoMap() const { return VarInfos; }
-  
-  // dumpLiveness
-  void dumpLiveness(const llvm::BitVector& V, SourceManager& M) const;
-  
-  // dumpBlockLiveness
+  /// dumpBlockLiveness - Print to stderr the liveness information
+  ///  associated with each basic block.
   void dumpBlockLiveness(SourceManager& M) const;
   
-  // dumpVarLiveness
-  void dumpVarLiveness(SourceManager& M) const;
-  
-  // getLiveAtBlockEntryMap
-  BlockLivenessMap& getLiveAtBlockEntryMap() { return LiveAtBlockEntryMap; }
-
-  const BlockLivenessMap& getLiveAtBlockEntryMap() const {
-    return LiveAtBlockEntryMap; 
-  }
-  
-  // getNumDecls
-  unsigned& getNumDecls() { return NumDecls; }
-  unsigned getNumDecls() const { return NumDecls; }
-  
-protected:
-
-  unsigned NumDecls;
-  VarInfoMap VarInfos;
-  BlockLivenessMap LiveAtBlockEntryMap;
+  /// getNumDecls - Return the number of variables (declarations) that
+  ///  whose liveness status is being tracked by the dataflow
+  ///  analysis.
+  unsigned getNumDecls() const { return getAnalysisData().getNumDecls(); }
+    
+  /// IntializeValues - Create initial dataflow values and meta data for
+  ///  a given CFG.  This is intended to be called by the dataflow solver.
+  void InitializeValues(const CFG& cfg);
   
+  void runOnCFG(const CFG& cfg);
+  void runOnAllBlocks(const CFG& cfg, ObserverTy& Obs);
 };
 
 } // end namespace clang

Modified: cfe/trunk/include/clang/Analysis/LocalCheckers.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/LocalCheckers.h?rev=42293&r1=42292&r2=42293&view=diff

==============================================================================
--- cfe/trunk/include/clang/Analysis/LocalCheckers.h (original)
+++ cfe/trunk/include/clang/Analysis/LocalCheckers.h Mon Sep 24 23:31:27 2007
@@ -18,14 +18,10 @@
 namespace clang {
 
 class CFG;
-class LiveVariables;
 class Diagnostic;
-  
-void CheckDeadStores(CFG& cfg, LiveVariables& L,
-                     ASTContext &Ctx, Diagnostic &Diags);
-void CheckDeadStores(CFG& cfg, ASTContext &Ctx, Diagnostic &Diags);  
+class ASTContext;
 
-  
+void CheckDeadStores(CFG& cfg, ASTContext &Ctx, Diagnostic &Diags);  
 void CheckUninitializedValues(CFG& cfg, ASTContext& Ctx, Diagnostic& Diags);
 
 

Modified: cfe/trunk/include/clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h?rev=42293&r1=42292&r2=42293&view=diff

==============================================================================
--- cfe/trunk/include/clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h (original)
+++ cfe/trunk/include/clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h Mon Sep 24 23:31:27 2007
@@ -26,7 +26,10 @@
 break;
 
 #define DEFAULT_DISPATCH(CLASS) void Visit##CLASS(CLASS* D) {}
+#define DEFAULT_DISPATCH_VARDECL(CLASS) void Visit##CLASS(CLASS* D)\
+  { static_cast<ImplClass*>(this)->Visit##VarDecl(D); }
 
+  
 namespace clang {
 template <typename ImplClass>
 class CFGRecStmtDeclVisitor : public CFGRecStmtVisitor<ImplClass> {
@@ -66,10 +69,11 @@
     }
   }
   
+  DEFAULT_DISPATCH(VarDecl)
   DEFAULT_DISPATCH(FunctionDecl)
-  DEFAULT_DISPATCH(BlockVarDecl)
-  DEFAULT_DISPATCH(FileVarDecl)
-  DEFAULT_DISPATCH(ParmVarDecl)
+  DEFAULT_DISPATCH_VARDECL(BlockVarDecl)
+  DEFAULT_DISPATCH_VARDECL(FileVarDecl)
+  DEFAULT_DISPATCH_VARDECL(ParmVarDecl)
   DEFAULT_DISPATCH(EnumConstantDecl)
   DEFAULT_DISPATCH(TypedefDecl)
   DEFAULT_DISPATCH(RecordDecl)





More information about the cfe-commits mailing list