]> granicus.if.org Git - clang/commitdiff
Enhance LiveVariables to understand that blocks can extend the liveness of a variable...
authorTed Kremenek <kremenek@apple.com>
Thu, 26 Nov 2009 02:31:33 +0000 (02:31 +0000)
committerTed Kremenek <kremenek@apple.com>
Thu, 26 Nov 2009 02:31:33 +0000 (02:31 +0000)
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*.

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

include/clang/Analysis/Analyses/LiveVariables.h
include/clang/Analysis/PathSensitive/AnalysisContext.h
lib/Analysis/AnalysisContext.cpp
lib/Analysis/LiveVariables.cpp

index 8674943960202ef5bf071482863d4c286fd14424..0077a8505170584cf807881176c60327ef836aa1 100644 (file)
@@ -23,6 +23,7 @@ namespace clang {
 class Stmt;
 class DeclRefExpr;
 class SourceManager;
+class AnalysisContext;
 
 struct LiveVariables_ValueTypes {
 
@@ -39,8 +40,9 @@ struct LiveVariables_ValueTypes {
   struct AnalysisDataTy : public StmtDeclBitVector_Types::AnalysisDataTy {
     ObserverTy* Observer;
     ValTy AlwaysLive;
+    AnalysisContext *AC;
 
-    AnalysisDataTy() : Observer(NULL) {}
+    AnalysisDataTy() : Observer(NULL), AC(NULL) {}
   };
 
   //===-----------------------------------------------------===//
@@ -66,7 +68,7 @@ class LiveVariables : public DataflowValues<LiveVariables_ValueTypes,
 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.
index 9b58f745f0a57afa6b251c3df73ba4c605785c71..8b1a329c0335ce41ab0b90bfde4622b7871088e2 100644 (file)
@@ -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 @@ class AnalysisContext {
   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;
index 640912ad6b39de79aed52e41d00924e802576fd2..339e2c93cea90bcebf5238e373cfdacba2f8fdc6 100644 (file)
 #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 @@ LiveVariables *AnalysisContext::getLiveVariables() {
     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 @@ ScopeContext *LocationContextManager::getScope(AnalysisContext *ctx,
   }
   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;
+}
index 2510445a7f3119bfb123397e34c484ed8e7c87db..e61f27bd39a7c88e93ec5b9cf358e39c3f2b1143 100644 (file)
@@ -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 @@ public:
 };
 } // 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 @@ public:
 
   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::VisitTerminator(CFGBlock* B) {
 
 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) {