[cfe-commits] r46143 - in /cfe/trunk: AST/CFG.cpp Analysis/LiveVariables.cpp include/clang/AST/CFG.h include/clang/Analysis/Analyses/LiveVariables.h include/clang/Analysis/FlowSensitive/DataflowSolver.h include/clang/Analysis/FlowSensitive/DataflowValues.h include/clang/Analysis/Support/ExprDeclBitVector.h include/clang/Analysis/Visitors/CFGStmtVisitor.h

Ted Kremenek kremenek at apple.com
Thu Jan 17 12:48:38 PST 2008


Author: kremenek
Date: Thu Jan 17 14:48:37 2008
New Revision: 46143

URL: http://llvm.org/viewvc/llvm-project?rev=46143&view=rev
Log:
Modified the notion of "Block-level expressions" in CFGs to include Stmt*. This
is because GNU-style Statement-expressions cause the last statement in the
statement-expression to act like an expression.

We now have two notions: block-level statements and block-level expressions.

The former are all Stmt* that appear in the list of statements in CFGBlocks. The
latter is the subset of the former; these block-level statements are used as
subexpressions somewhere in the AST. CFG::isBlockExpr() returns true for the
latter, not the former (previously isBlockExpr() always returned true for
non-Expr Stmt*).

Modified the LiveVariables analysis to also track liveness state for block-level
expressions (using the updated definition of block-level expressions).

Modified the dataflow solver so that when it records values for block-level
statements, it records the dataflow value *before* the transfer function for a
Stmt* is evaluated (not after). This is more in sync in what clients will want.

Modified CFGStmtVisitor to record the current block-level statement.

Modified:
    cfe/trunk/AST/CFG.cpp
    cfe/trunk/Analysis/LiveVariables.cpp
    cfe/trunk/include/clang/AST/CFG.h
    cfe/trunk/include/clang/Analysis/Analyses/LiveVariables.h
    cfe/trunk/include/clang/Analysis/FlowSensitive/DataflowSolver.h
    cfe/trunk/include/clang/Analysis/FlowSensitive/DataflowValues.h
    cfe/trunk/include/clang/Analysis/Support/ExprDeclBitVector.h
    cfe/trunk/include/clang/Analysis/Visitors/CFGStmtVisitor.h

Modified: cfe/trunk/AST/CFG.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/AST/CFG.cpp?rev=46143&r1=46142&r2=46143&view=diff

==============================================================================
--- cfe/trunk/AST/CFG.cpp (original)
+++ cfe/trunk/AST/CFG.cpp Thu Jan 17 14:48:37 2008
@@ -988,7 +988,7 @@
 //===----------------------------------------------------------------------===//
 
 namespace {
-  typedef llvm::DenseMap<const Expr*,unsigned> BlkExprMapTy;
+  typedef llvm::DenseMap<const Stmt*,unsigned> BlkExprMapTy;
 }
 
 static BlkExprMapTy* PopulateBlkExprMap(CFG& cfg) {
@@ -999,23 +999,27 @@
       if (const Expr* E = dyn_cast<Expr>(*BI)) {
         unsigned x = M->size();
         (*M)[E] = x;
+
+        // Special handling for statement expressions.  The last statement
+        // in the statement expression is also a block-level expr.
+        if (const StmtExpr* S = dyn_cast<StmtExpr>(E)) {
+          const CompoundStmt* C = S->getSubStmt();
+          if (!C->body_empty()) {
+            x = M->size();
+            (*M)[C->body_back()] = x;
+          }
+        }
       }
-  
-  return M;
-}
 
-bool CFG::isBlkExpr(const Stmt* S) {
-  assert (S != NULL);
-  if (const Expr* E = dyn_cast<Expr>(S)) return getBlkExprNum(E);
-  else return true;  // Statements are by default "block-level expressions."
+  return M;
 }
 
-CFG::BlkExprNumTy CFG::getBlkExprNum(const Expr* E) {
-  assert(E != NULL);
+CFG::BlkExprNumTy CFG::getBlkExprNum(const Stmt* S) {
+  assert(S != NULL);
   if (!BlkExprMap) { BlkExprMap = (void*) PopulateBlkExprMap(*this); }
   
   BlkExprMapTy* M = reinterpret_cast<BlkExprMapTy*>(BlkExprMap);
-  BlkExprMapTy::iterator I = M->find(E);
+  BlkExprMapTy::iterator I = M->find(S);
   
   if (I == M->end()) return CFG::BlkExprNumTy();
   else return CFG::BlkExprNumTy(I->second);

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

==============================================================================
--- cfe/trunk/Analysis/LiveVariables.cpp (original)
+++ cfe/trunk/Analysis/LiveVariables.cpp Thu Jan 17 14:48:37 2008
@@ -77,7 +77,16 @@
   if (AD.Observer)
     AD.Observer->ObserveStmt(S,AD,LiveState);
   
-  static_cast<CFGStmtVisitor<TransferFuncs>*>(this)->Visit(S);
+
+  if (S == getCurrentBlkStmt()) {
+    StmtVisitor<TransferFuncs,void>::Visit(S);
+    if (getCFG().isBlkExpr(S)) LiveState(S,AD) = Dead;
+  }
+  else if (!getCFG().isBlkExpr(S))
+    StmtVisitor<TransferFuncs,void>::Visit(S);
+  else
+    // For block-level expressions, mark that they are live.
+    LiveState(S,AD) = Alive;
 }
 
 void TransferFuncs::VisitDeclRefExpr(DeclRefExpr* DR) {
@@ -186,6 +195,10 @@
   return Live(D,getAnalysisData());
 }
 
+bool LiveVariables::isLive(const Stmt* Loc, const Stmt* StmtVal) const {
+  return getStmtData(Loc)(StmtVal,getAnalysisData());
+}
+
 //===----------------------------------------------------------------------===//
 // printing liveness state for debugging
 //

Modified: cfe/trunk/include/clang/AST/CFG.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/CFG.h?rev=46143&r1=46142&r2=46143&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/CFG.h (original)
+++ cfe/trunk/include/clang/AST/CFG.h Thu Jan 17 14:48:37 2008
@@ -255,9 +255,8 @@
     operator unsigned() const { assert(Idx >=0); return (unsigned) Idx; }
   };
     
-  bool          isBlkExpr(const Stmt* S);
-  bool          isBlkExpr(const Expr* E) { return getBlkExprNum(E); }
-  BlkExprNumTy  getBlkExprNum(const Expr* E);
+  bool          isBlkExpr(const Stmt* S) { return getBlkExprNum(S); }
+  BlkExprNumTy  getBlkExprNum(const Stmt* S);
   unsigned      getNumBlkExprs();
   
   unsigned getNumBlockIDs() const { return NumBlockIDs; }

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

==============================================================================
--- cfe/trunk/include/clang/Analysis/Analyses/LiveVariables.h (original)
+++ cfe/trunk/include/clang/Analysis/Analyses/LiveVariables.h Thu Jan 17 14:48:37 2008
@@ -30,11 +30,10 @@
 
 
   // We need to keep track of both declarations and CFGBlock-level expressions,
-  // (so that we don't explore such expressions twice), but we only need
-  // liveness information for declarations (hence 
-  // ValTy = DeclBitVector_Types::ValTy instead of 
-  // ValTy = ExprDeclBitVector_Types::ValTy).
-
+  // (so that we don't explore such expressions twice).  We also want
+  // to compute liveness information for block-level expressions, since these
+  // act as "temporary" values.
+  
   struct AnalysisDataTy : public ExprDeclBitVector_Types::AnalysisDataTy {
     ObserverTy* Observer;
     
@@ -42,7 +41,7 @@
   };
 
     // We only keep actual dataflow state for declarations.
-  typedef DeclBitVector_Types::ValTy ValTy;
+  typedef ExprDeclBitVector_Types::ValTy ValTy;
   
   //===-----------------------------------------------------===//
   // ObserverTy - Observer for uninitialized values queries.
@@ -76,6 +75,10 @@
   ///  has been recorded at the statement level (see runOnAllBlocks), and
   ///  only returns liveness information for block-level expressions.
   bool isLive(const Stmt* S, const VarDecl* D) const;
+                                              
+  /// IsLive - Returns true the block-level expression "value" is live
+  ///  before the given block-level expression (see runOnAllBlocks).
+  bool isLive(const Stmt* Loc, const Stmt* StmtVal) const;
   
   /// IsLive - Return true if a variable is live according to the
   ///  provided livness bitvector.

Modified: cfe/trunk/include/clang/Analysis/FlowSensitive/DataflowSolver.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/FlowSensitive/DataflowSolver.h?rev=46143&r1=46142&r2=46143&view=diff

==============================================================================
--- cfe/trunk/include/clang/Analysis/FlowSensitive/DataflowSolver.h (original)
+++ cfe/trunk/include/clang/Analysis/FlowSensitive/DataflowSolver.h Thu Jan 17 14:48:37 2008
@@ -236,8 +236,8 @@
   /// ProcessBlock - Process the transfer functions for a given block.
   void ProcessBlock(const CFGBlock* B, bool recordStmtValues) {
     for (StmtItr I=ItrTraits::StmtBegin(B), E=ItrTraits::StmtEnd(B); I!=E;++I) {
-      TF.BlockStmt_Visit(const_cast<Stmt*>(*I));
       if (recordStmtValues) D.getStmtDataMap()[*I] = TF.getVal();
+      TF.BlockStmt_Visit(const_cast<Stmt*>(*I));
     }      
   }
 

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

==============================================================================
--- cfe/trunk/include/clang/Analysis/FlowSensitive/DataflowValues.h (original)
+++ cfe/trunk/include/clang/Analysis/FlowSensitive/DataflowValues.h Thu Jan 17 14:48:37 2008
@@ -110,9 +110,9 @@
   
   /// getStmtData - Retrieves the dataflow values associated with a 
   ///  specified Stmt.  If the dataflow analysis is a forward analysis,
-  ///  this data corresponds to the point immediately after a Stmt. 
+  ///  this data corresponds to the point immediately before a Stmt. 
   ///  If the analysis is a backwards analysis, it is associated with
-  ///  the point before a Stmt.  This data is only computed for block-level
+  ///  the point after a Stmt.  This data is only computed for block-level
   ///  expressions, and only when requested when the analysis is executed.
   ValTy& getStmtData(const Stmt* S) {
     assert (StmtDataMap && "Dataflow values were not computed for statements.");

Modified: cfe/trunk/include/clang/Analysis/Support/ExprDeclBitVector.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/Support/ExprDeclBitVector.h?rev=46143&r1=46142&r2=46143&view=diff

==============================================================================
--- cfe/trunk/include/clang/Analysis/Support/ExprDeclBitVector.h (original)
+++ cfe/trunk/include/clang/Analysis/Support/ExprDeclBitVector.h Thu Jan 17 14:48:37 2008
@@ -139,11 +139,11 @@
     void setCFG(CFG* c) { cfg = c; }
     CFG& getCFG() { assert(cfg && "CFG should not be NULL."); return *cfg; }
     
-    bool isTracked(const Expr* E) { return cfg->isBlkExpr(E); }
+    bool isTracked(const Stmt* S) { return cfg->isBlkExpr(S); }
     using DeclBitVector_Types::AnalysisDataTy::isTracked;
 
-    unsigned getIdx(const Expr* E) const {
-      CFG::BlkExprNumTy I = cfg->getBlkExprNum(E);
+    unsigned getIdx(const Stmt* S) const {
+      CFG::BlkExprNumTy I = cfg->getBlkExprNum(S);
       assert(I && "expression not tracked for bitvector.");
       return I;
     }
@@ -187,12 +187,12 @@
     }
         
     llvm::BitVector::reference
-    operator()(const Expr* E, const AnalysisDataTy& AD) {
-      return ExprBV[AD.getIdx(E)];      
+    operator()(const Stmt* S, const AnalysisDataTy& AD) {
+      return ExprBV[AD.getIdx(S)];      
     }    
     const llvm::BitVector::reference
-    operator()(const Expr* E, const AnalysisDataTy& AD) const {
-      return const_cast<ValTy&>(*this)(E,AD);
+    operator()(const Stmt* S, const AnalysisDataTy& AD) const {
+      return const_cast<ValTy&>(*this)(S,AD);
     }
     
     using DeclBitVector_Types::ValTy::operator();

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

==============================================================================
--- cfe/trunk/include/clang/Analysis/Visitors/CFGStmtVisitor.h (original)
+++ cfe/trunk/include/clang/Analysis/Visitors/CFGStmtVisitor.h Thu Jan 17 14:48:37 2008
@@ -33,7 +33,7 @@
 
 template <typename ImplClass, typename RetTy=void>
 class CFGStmtVisitor : public StmtVisitor<ImplClass,RetTy> {
-  Stmt* CurrentBlkExpr;
+  Stmt* CurrentBlkStmt;
 
   struct NullifyStmt {
     Stmt*& S;  
@@ -42,11 +42,13 @@
     ~NullifyStmt() { S = NULL; }
   };
   
-public:  
-  CFGStmtVisitor() : CurrentBlkExpr(NULL) {}  
+public:
+  CFGStmtVisitor() : CurrentBlkStmt(NULL) {}  
+  
+  Stmt* getCurrentBlkStmt() const { return CurrentBlkStmt; }
   
   RetTy Visit(Stmt* S) {
-    if (S == CurrentBlkExpr || 
+    if (S == CurrentBlkStmt || 
         !static_cast<ImplClass*>(this)->getCFG().isBlkExpr(S))
       return StmtVisitor<ImplClass,RetTy>::Visit(S);
     else
@@ -59,8 +61,8 @@
   /// is no implementation provided for a BlockStmt_XXX method, we default
   /// to using StmtVisitor's Visit method.
   RetTy BlockStmt_Visit(Stmt* S) {
-    CurrentBlkExpr = S;
-    NullifyStmt cleanup(CurrentBlkExpr);
+    CurrentBlkStmt = S;
+    NullifyStmt cleanup(CurrentBlkStmt);
     
     switch (S->getStmtClass()) {
       DISPATCH_CASE(CallExpr)





More information about the cfe-commits mailing list