diff options
author | Ted Kremenek <kremenek@apple.com> | 2009-11-26 02:31:33 +0000 |
---|---|---|
committer | Ted Kremenek <kremenek@apple.com> | 2009-11-26 02:31:33 +0000 |
commit | b1a7b65231e86f7da6aacbf00bcdc16c56350e65 (patch) | |
tree | a72b34bb5372c1f89a4841fac28fd2250132342f | |
parent | f21bf9b87a5edefb3f10a96ac036f92f538b8d32 (diff) |
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*.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@89924 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/Analysis/Analyses/LiveVariables.h | 6 | ||||
-rw-r--r-- | include/clang/Analysis/PathSensitive/AnalysisContext.h | 14 | ||||
-rw-r--r-- | lib/Analysis/AnalysisContext.cpp | 87 | ||||
-rw-r--r-- | lib/Analysis/LiveVariables.cpp | 20 |
4 files changed, 108 insertions, 19 deletions
diff --git a/include/clang/Analysis/Analyses/LiveVariables.h b/include/clang/Analysis/Analyses/LiveVariables.h index 8674943960..0077a85051 100644 --- a/include/clang/Analysis/Analyses/LiveVariables.h +++ b/include/clang/Analysis/Analyses/LiveVariables.h @@ -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. diff --git a/include/clang/Analysis/PathSensitive/AnalysisContext.h b/include/clang/Analysis/PathSensitive/AnalysisContext.h index 9b58f745f0..8b1a329c03 100644 --- a/include/clang/Analysis/PathSensitive/AnalysisContext.h +++ b/include/clang/Analysis/PathSensitive/AnalysisContext.h @@ -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; diff --git a/lib/Analysis/AnalysisContext.cpp b/lib/Analysis/AnalysisContext.cpp index 640912ad6b..339e2c93ce 100644 --- a/lib/Analysis/AnalysisContext.cpp +++ b/lib/Analysis/AnalysisContext.cpp @@ -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 @@ 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; +} diff --git a/lib/Analysis/LiveVariables.cpp b/lib/Analysis/LiveVariables.cpp index 2510445a7f..e61f27bd39 100644 --- a/lib/Analysis/LiveVariables.cpp +++ b/lib/Analysis/LiveVariables.cpp @@ -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) { |