class Stmt;
class DeclRefExpr;
class SourceManager;
+class AnalysisContext;
struct LiveVariables_ValueTypes {
struct AnalysisDataTy : public StmtDeclBitVector_Types::AnalysisDataTy {
ObserverTy* Observer;
ValTy AlwaysLive;
+ AnalysisContext *AC;
- AnalysisDataTy() : Observer(NULL) {}
+ AnalysisDataTy() : Observer(NULL), AC(NULL) {}
};
//===-----------------------------------------------------===//
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.
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/Support/Allocator.h"
namespace clang {
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;
#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;
if (!c)
return 0;
- liveness = new LiveVariables(D->getASTContext(), *c);
+ liveness = new LiveVariables(*this);
liveness->runOnCFG(*c);
liveness->runOnAllBlocks(*c, 0, true);
}
}
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;
+}
#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"
};
} // 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);
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);
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) {