[cfe-commits] r89924 - in /cfe/trunk: include/clang/Analysis/Analyses/LiveVariables.h include/clang/Analysis/PathSensitive/AnalysisContext.h lib/Analysis/AnalysisContext.cpp lib/Analysis/LiveVariables.cpp

Ted Kremenek kremenek at apple.com
Wed Nov 25 18:31:33 PST 2009


Author: kremenek
Date: Wed Nov 25 20:31:33 2009
New Revision: 89924

URL: http://llvm.org/viewvc/llvm-project?rev=89924&view=rev
Log:
Enhance LiveVariables to understand that blocks can extend the liveness of a variable by "capturing" them in a BlockExpr.

This required two changes:

1) Added 'getReferencedgetReferencedBlockVars()' to AnalysisContext so
that clients can iterate over the "captured" variables in a block.

2) Modified LiveVariables to take an AnalysisContext& in its
constructor and to call getReferencedgetReferencedBlockVars() when it
processes a BlockExpr*.

Modified:
    cfe/trunk/include/clang/Analysis/Analyses/LiveVariables.h
    cfe/trunk/include/clang/Analysis/PathSensitive/AnalysisContext.h
    cfe/trunk/lib/Analysis/AnalysisContext.cpp
    cfe/trunk/lib/Analysis/LiveVariables.cpp

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=89924&r1=89923&r2=89924&view=diff

==============================================================================
--- cfe/trunk/include/clang/Analysis/Analyses/LiveVariables.h (original)
+++ cfe/trunk/include/clang/Analysis/Analyses/LiveVariables.h Wed Nov 25 20:31:33 2009
@@ -23,6 +23,7 @@
 class Stmt;
 class DeclRefExpr;
 class SourceManager;
+class AnalysisContext;
 
 struct LiveVariables_ValueTypes {
 
@@ -39,8 +40,9 @@
   struct AnalysisDataTy : public StmtDeclBitVector_Types::AnalysisDataTy {
     ObserverTy* Observer;
     ValTy AlwaysLive;
+    AnalysisContext *AC;
 
-    AnalysisDataTy() : Observer(NULL) {}
+    AnalysisDataTy() : Observer(NULL), AC(NULL) {}
   };
 
   //===-----------------------------------------------------===//
@@ -66,7 +68,7 @@
 public:
   typedef LiveVariables_ValueTypes::ObserverTy ObserverTy;
 
-  LiveVariables(ASTContext& Ctx, CFG& cfg);
+  LiveVariables(AnalysisContext &AC);
 
   /// IsLive - Return true if a variable is live at beginning of a
   /// specified block.

Modified: cfe/trunk/include/clang/Analysis/PathSensitive/AnalysisContext.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/PathSensitive/AnalysisContext.h?rev=89924&r1=89923&r2=89924&view=diff

==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/AnalysisContext.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/AnalysisContext.h Wed Nov 25 20:31:33 2009
@@ -19,6 +19,7 @@
 #include "llvm/ADT/OwningPtr.h"
 #include "llvm/ADT/FoldingSet.h"
 #include "llvm/ADT/DenseMap.h"
+#include "llvm/Support/Allocator.h"
 
 namespace clang {
 
@@ -38,17 +39,26 @@
   CFG *cfg;
   LiveVariables *liveness;
   ParentMap *PM;
-
+  llvm::DenseMap<const BlockDecl*,void*> *ReferencedBlockVars;
+  llvm::BumpPtrAllocator A;
 public:
-  AnalysisContext(const Decl *d) : D(d), cfg(0), liveness(0), PM(0) {}
+  AnalysisContext(const Decl *d) : D(d), cfg(0), liveness(0), PM(0),
+    ReferencedBlockVars(0) {}
+
   ~AnalysisContext();
 
+  ASTContext &getASTContext() { return D->getASTContext(); }
   const Decl *getDecl() { return D; }
   Stmt *getBody();
   CFG *getCFG();
   ParentMap &getParentMap();
   LiveVariables *getLiveVariables();
 
+  typedef const VarDecl * const * referenced_decls_iterator;
+
+  std::pair<referenced_decls_iterator, referenced_decls_iterator>
+    getReferencedBlockVars(const BlockDecl *BD);
+  
   /// Return the ImplicitParamDecl* associated with 'self' if this
   /// AnalysisContext wraps an ObjCMethodDecl.  Returns NULL otherwise.
   const ImplicitParamDecl *getSelfDecl() const;

Modified: cfe/trunk/lib/Analysis/AnalysisContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/AnalysisContext.cpp?rev=89924&r1=89923&r2=89924&view=diff

==============================================================================
--- cfe/trunk/lib/Analysis/AnalysisContext.cpp (original)
+++ cfe/trunk/lib/Analysis/AnalysisContext.cpp Wed Nov 25 20:31:33 2009
@@ -18,21 +18,12 @@
 #include "clang/AST/Decl.h"
 #include "clang/AST/DeclObjC.h"
 #include "clang/AST/ParentMap.h"
+#include "clang/AST/StmtVisitor.h"
+#include "clang/Analysis/Support/BumpVector.h"
 #include "llvm/Support/ErrorHandling.h"
 
 using namespace clang;
 
-AnalysisContext::~AnalysisContext() {
-  delete cfg;
-  delete liveness;
-  delete PM;
-}
-
-AnalysisContextManager::~AnalysisContextManager() {
-  for (ContextMap::iterator I = Contexts.begin(), E = Contexts.end(); I!=E; ++I)
-    delete I->second;
-}
-
 void AnalysisContextManager::clear() {
   for (ContextMap::iterator I = Contexts.begin(), E = Contexts.end(); I!=E; ++I)
     delete I->second;
@@ -73,7 +64,7 @@
     if (!c)
       return 0;
 
-    liveness = new LiveVariables(D->getASTContext(), *c);
+    liveness = new LiveVariables(*this);
     liveness->runOnCFG(*c);
     liveness->runOnAllBlocks(*c, 0, true);
   }
@@ -157,3 +148,75 @@
   }
   return scope;
 }
+
+//===----------------------------------------------------------------------===//
+// Lazily generated map to query the external variables referenced by a Block.
+//===----------------------------------------------------------------------===//
+
+namespace {
+class FindBlockDeclRefExprsVals : public StmtVisitor<FindBlockDeclRefExprsVals>{
+  BumpVector<const VarDecl*> &BEVals;
+  BumpVectorContext &BC;
+public:
+  FindBlockDeclRefExprsVals(BumpVector<const VarDecl*> &bevals,
+                            BumpVectorContext &bc)
+  : BEVals(bevals), BC(bc) {}
+  
+  void VisitStmt(Stmt *S) {
+    for (Stmt::child_iterator I = S->child_begin(), E = S->child_end();I!=E;++I)
+      if (Stmt *child = *I)
+        Visit(child);
+  }
+  
+  void VisitBlockDeclRefExpr(BlockDeclRefExpr *DR) {
+    if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl()))
+      BEVals.push_back(VD, BC);
+  }
+};  
+} // end anonymous namespace
+
+typedef BumpVector<const VarDecl*> DeclVec;
+
+static DeclVec* LazyInitializeReferencedDecls(const BlockDecl *BD,
+                                              void *&Vec,
+                                              llvm::BumpPtrAllocator &A) {
+  if (Vec)
+    return (DeclVec*) Vec;
+  
+  BumpVectorContext BC(A);
+  DeclVec *BV = (DeclVec*) A.Allocate<DeclVec>();
+  new (BV) DeclVec(BC, 10);
+  
+  // Find the referenced variables.
+  FindBlockDeclRefExprsVals F(*BV, BC);
+  F.Visit(BD->getBody());
+  
+  Vec = BV;  
+  return BV;
+}
+
+std::pair<AnalysisContext::referenced_decls_iterator,
+          AnalysisContext::referenced_decls_iterator>
+AnalysisContext::getReferencedBlockVars(const BlockDecl *BD) {
+  if (!ReferencedBlockVars)
+    ReferencedBlockVars = new llvm::DenseMap<const BlockDecl*,void*>();
+  
+  DeclVec *V = LazyInitializeReferencedDecls(BD, (*ReferencedBlockVars)[BD], A);
+  return std::make_pair(V->begin(), V->end());
+}
+
+//===----------------------------------------------------------------------===//
+// Cleanup.
+//===----------------------------------------------------------------------===//
+
+AnalysisContext::~AnalysisContext() {
+  delete cfg;
+  delete liveness;
+  delete PM;
+  delete ReferencedBlockVars;
+}
+
+AnalysisContextManager::~AnalysisContextManager() {
+  for (ContextMap::iterator I = Contexts.begin(), E = Contexts.end(); I!=E; ++I)
+    delete I->second;
+}

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

==============================================================================
--- cfe/trunk/lib/Analysis/LiveVariables.cpp (original)
+++ cfe/trunk/lib/Analysis/LiveVariables.cpp Wed Nov 25 20:31:33 2009
@@ -19,6 +19,7 @@
 #include "clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h"
 #include "clang/Analysis/FlowSensitive/DataflowSolver.h"
 #include "clang/Analysis/Support/SaveAndRestore.h"
+#include "clang/Analysis/PathSensitive/AnalysisContext.h"
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/Support/Compiler.h"
@@ -77,10 +78,12 @@
 };
 } // end anonymous namespace
 
-LiveVariables::LiveVariables(ASTContext& Ctx, CFG& cfg) {
+LiveVariables::LiveVariables(AnalysisContext &AC) {  
   // Register all referenced VarDecls.
+  CFG &cfg = *AC.getCFG();
   getAnalysisData().setCFG(cfg);
-  getAnalysisData().setContext(Ctx);
+  getAnalysisData().setContext(AC.getASTContext());
+  getAnalysisData().AC = &AC;
 
   RegisterDecls R(getAnalysisData());
   cfg.VisitBlockStmts(R);
@@ -103,6 +106,7 @@
 
   void VisitDeclRefExpr(DeclRefExpr* DR);
   void VisitBinaryOperator(BinaryOperator* B);
+  void VisitBlockExpr(BlockExpr *B);
   void VisitAssign(BinaryOperator* B);
   void VisitDeclStmt(DeclStmt* DS);
   void BlockStmt_VisitObjCForCollectionStmt(ObjCForCollectionStmt* S);
@@ -153,7 +157,17 @@
 
 void TransferFuncs::VisitDeclRefExpr(DeclRefExpr* DR) {
   if (VarDecl* V = dyn_cast<VarDecl>(DR->getDecl()))
-    LiveState(V,AD) = Alive;
+    LiveState(V, AD) = Alive;
+}
+  
+void TransferFuncs::VisitBlockExpr(BlockExpr *BE) {
+  AnalysisContext::referenced_decls_iterator I, E;
+  llvm::tie(I, E) = AD.AC->getReferencedBlockVars(BE->getBlockDecl());
+  for ( ; I != E ; ++I) {
+    DeclBitVector_Types::Idx i = AD.getIdx(*I);
+    if (i.isValid())
+      LiveState.getBit(i) = Alive;
+  }
 }
 
 void TransferFuncs::VisitBinaryOperator(BinaryOperator* B) {





More information about the cfe-commits mailing list