diff options
author | Ted Kremenek <kremenek@apple.com> | 2011-10-07 22:21:02 +0000 |
---|---|---|
committer | Ted Kremenek <kremenek@apple.com> | 2011-10-07 22:21:02 +0000 |
commit | a5937bbfd19e61d651a58b0f0ffeef68457902a5 (patch) | |
tree | 89900f2c77818128c031816dfe2a5154ee1ef592 | |
parent | ec2ec1f20322076717c3865b196f7a1c95d883a4 (diff) |
Remove AnalysisContext::getLiveVariables(), and introduce a templatized mechanism to lazily create analyses that are attached to AnalysisContext objects.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@141425 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/Analysis/Analyses/LiveVariables.h | 25 | ||||
-rw-r--r-- | include/clang/Analysis/AnalysisContext.h | 46 | ||||
-rw-r--r-- | include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h | 5 | ||||
-rw-r--r-- | include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h | 5 | ||||
-rw-r--r-- | lib/Analysis/AnalysisContext.cpp | 36 | ||||
-rw-r--r-- | lib/Analysis/LiveVariables.cpp | 2 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp | 2 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Checkers/DebugCheckers.cpp | 2 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/SymbolManager.cpp | 6 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp | 5 |
10 files changed, 97 insertions, 37 deletions
diff --git a/include/clang/Analysis/Analyses/LiveVariables.h b/include/clang/Analysis/Analyses/LiveVariables.h index f5d6e51e8a..302ae1c41f 100644 --- a/include/clang/Analysis/Analyses/LiveVariables.h +++ b/include/clang/Analysis/Analyses/LiveVariables.h @@ -14,6 +14,7 @@ #ifndef LLVM_CLANG_LIVEVARIABLES_H #define LLVM_CLANG_LIVEVARIABLES_H +#include "clang/Analysis/AnalysisContext.h" #include "clang/AST/Decl.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/ImmutableSet.h" @@ -25,9 +26,8 @@ class CFGBlock; class Stmt; class DeclRefExpr; class SourceManager; -class AnalysisContext; -class LiveVariables { +class LiveVariables : public ManagedAnalysis { public: class LivenessValues { public: @@ -67,11 +67,11 @@ public: }; - ~LiveVariables(); + virtual ~LiveVariables(); /// Compute the liveness information for a given CFG. static LiveVariables *computeLiveness(AnalysisContext &analysisContext, - bool killAtAssign = true); + bool killAtAssign); /// Return true if a variable is live at the end of a /// specified block. @@ -92,12 +92,27 @@ public: void dumpBlockLiveness(const SourceManager& M); void runOnAllBlocks(Observer &obs); - + + static LiveVariables *create(AnalysisContext &analysisContext) { + return computeLiveness(analysisContext, true); + } + + static const void *getTag(); + private: LiveVariables(void *impl); void *impl; }; +class RelaxedLiveVariables : public LiveVariables { +public: + static LiveVariables *create(AnalysisContext &analysisContext) { + return computeLiveness(analysisContext, false); + } + + static const void *getTag(); +}; + } // end namespace clang #endif diff --git a/include/clang/Analysis/AnalysisContext.h b/include/clang/Analysis/AnalysisContext.h index fe017fe802..3d0e88a51d 100644 --- a/include/clang/Analysis/AnalysisContext.h +++ b/include/clang/Analysis/AnalysisContext.h @@ -32,14 +32,35 @@ class Stmt; class CFGReverseBlockReachabilityAnalysis; class CFGStmtMap; class LiveVariables; +class ManagedAnalysis; class ParentMap; class PseudoConstantAnalysis; class ImplicitParamDecl; class LocationContextManager; class StackFrameContext; - + namespace idx { class TranslationUnit; } +/// The base class of a hierarchy of objects representing analyses tied +/// to AnalysisContext. +class ManagedAnalysis { +protected: + ManagedAnalysis() {} +public: + virtual ~ManagedAnalysis(); + + // Subclasses need to implement: + // + // static const void *getTag(); + // + // Which returns a fixed pointer address to distinguish classes of + // analysis objects. They also need to implement: + // + // static [Derived*] create(AnalysisContext &Ctx); + // + // which creates the analysis object given an AnalysisContext. +}; + /// AnalysisContext contains the context data for the function or method under /// analysis. class AnalysisContext { @@ -67,6 +88,8 @@ class AnalysisContext { // FIXME: remove. llvm::DenseMap<const BlockDecl*,void*> *ReferencedBlockVars; + void *ManagedAnalyses; + public: AnalysisContext(const Decl *d, idx::TranslationUnit *tu); @@ -122,8 +145,6 @@ public: ParentMap &getParentMap(); PseudoConstantAnalysis *getPseudoConstantAnalysis(); - LiveVariables *getLiveVariables(); - LiveVariables *getRelaxedLiveVariables(); typedef const VarDecl * const * referenced_decls_iterator; @@ -133,6 +154,20 @@ public: /// Return the ImplicitParamDecl* associated with 'self' if this /// AnalysisContext wraps an ObjCMethodDecl. Returns NULL otherwise. const ImplicitParamDecl *getSelfDecl() const; + + /// Return the specified analysis object, lazily running the analysis if + /// necessary. Return NULL if the analysis could not run. + template <typename T> + T *getAnalysis() { + const void *tag = T::getTag(); + ManagedAnalysis *&data = getAnalysisImpl(tag); + if (!data) { + data = T::create(*this); + } + return static_cast<T*>(data); + } +private: + ManagedAnalysis *&getAnalysisImpl(const void* tag); }; class AnalysisContextManager { @@ -196,8 +231,9 @@ public: CFG *getCFG() const { return getAnalysisContext()->getCFG(); } - LiveVariables *getLiveVariables() const { - return getAnalysisContext()->getLiveVariables(); + template <typename T> + T *getAnalysis() const { + return getAnalysisContext()->getAnalysis<T>(); } ParentMap &getParentMap() const { diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h index 9c333ce268..6c93f59d20 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h @@ -172,8 +172,9 @@ public: return AnaCtxMgr.getContext(D)->getCFG(); } - LiveVariables *getLiveVariables(Decl const *D) { - return AnaCtxMgr.getContext(D)->getLiveVariables(); + template <typename T> + T *getAnalysis(Decl const *D) { + return AnaCtxMgr.getContext(D)->getAnalysis<T>(); } ParentMap &getParentMap(Decl const *D) { diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h index d14d86e0ce..fdfed3da54 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h @@ -138,8 +138,9 @@ public: ParentMap &getParentMap() const {return getLocationContext()->getParentMap();} - LiveVariables &getLiveVariables() const { - return *getLocationContext()->getLiveVariables(); + template <typename T> + T &getAnalysis() const { + return *getLocationContext()->getAnalysis<T>(); } const ProgramState *getState() const { return State; } diff --git a/lib/Analysis/AnalysisContext.cpp b/lib/Analysis/AnalysisContext.cpp index 200183a027..3dd194b8e8 100644 --- a/lib/Analysis/AnalysisContext.cpp +++ b/lib/Analysis/AnalysisContext.cpp @@ -30,6 +30,8 @@ using namespace clang; +typedef llvm::DenseMap<const void *, ManagedAnalysis *> ManagedAnalysisMap; + AnalysisContext::AnalysisContext(const Decl *d, idx::TranslationUnit *tu, const CFG::BuildOptions &buildOptions) @@ -38,7 +40,8 @@ AnalysisContext::AnalysisContext(const Decl *d, forcedBlkExprs(0), builtCFG(false), builtCompleteCFG(false), - ReferencedBlockVars(0) + ReferencedBlockVars(0), + ManagedAnalyses(0) { cfgBuildOptions.forcedBlkExprs = &forcedBlkExprs; } @@ -49,7 +52,8 @@ AnalysisContext::AnalysisContext(const Decl *d, forcedBlkExprs(0), builtCFG(false), builtCompleteCFG(false), - ReferencedBlockVars(0) + ReferencedBlockVars(0), + ManagedAnalyses(0) { cfgBuildOptions.forcedBlkExprs = &forcedBlkExprs; } @@ -176,18 +180,6 @@ PseudoConstantAnalysis *AnalysisContext::getPseudoConstantAnalysis() { return PCA.get(); } -LiveVariables *AnalysisContext::getLiveVariables() { - if (!liveness) - liveness.reset(LiveVariables::computeLiveness(*this)); - return liveness.get(); -} - -LiveVariables *AnalysisContext::getRelaxedLiveVariables() { - if (!relaxedLiveness) - relaxedLiveness.reset(LiveVariables::computeLiveness(*this, false)); - return relaxedLiveness.get(); -} - AnalysisContext *AnalysisContextManager::getContext(const Decl *D, idx::TranslationUnit *TU) { AnalysisContext *&AC = Contexts[D]; @@ -395,13 +387,29 @@ AnalysisContext::getReferencedBlockVars(const BlockDecl *BD) { return std::make_pair(V->begin(), V->end()); } +ManagedAnalysis *&AnalysisContext::getAnalysisImpl(const void *tag) { + if (!ManagedAnalyses) + ManagedAnalyses = new ManagedAnalysisMap(); + ManagedAnalysisMap *M = (ManagedAnalysisMap*) ManagedAnalyses; + return (*M)[tag]; +} + //===----------------------------------------------------------------------===// // Cleanup. //===----------------------------------------------------------------------===// +ManagedAnalysis::~ManagedAnalysis() {} + AnalysisContext::~AnalysisContext() { delete forcedBlkExprs; delete ReferencedBlockVars; + // Release the managed analyses. + if (ManagedAnalyses) { + ManagedAnalysisMap *M = (ManagedAnalysisMap*) ManagedAnalyses; + for (ManagedAnalysisMap::iterator I = M->begin(), E = M->end(); I!=E; ++I) + delete I->second; + delete M; + } } AnalysisContextManager::~AnalysisContextManager() { diff --git a/lib/Analysis/LiveVariables.cpp b/lib/Analysis/LiveVariables.cpp index c800c70a38..62c5455e0f 100644 --- a/lib/Analysis/LiveVariables.cpp +++ b/lib/Analysis/LiveVariables.cpp @@ -670,3 +670,5 @@ void LiveVariablesImpl::dumpBlockLiveness(const SourceManager &M) { llvm::errs() << "\n"; } +const void *LiveVariables::getTag() { static int x; return &x; } +const void *RelaxedLiveVariables::getTag() { static int x; return &x; } diff --git a/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp b/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp index 5d272ea382..df66aaf19a 100644 --- a/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp @@ -348,7 +348,7 @@ class DeadStoresChecker : public Checker<check::ASTCodeBody> { public: void checkASTCodeBody(const Decl *D, AnalysisManager& mgr, BugReporter &BR) const { - if (LiveVariables *L = mgr.getLiveVariables(D)) { + if (LiveVariables *L = mgr.getAnalysis<LiveVariables>(D)) { CFG &cfg = *mgr.getCFG(D); AnalysisContext *AC = mgr.getAnalysisContext(D); ParentMap &pmap = mgr.getParentMap(D); diff --git a/lib/StaticAnalyzer/Checkers/DebugCheckers.cpp b/lib/StaticAnalyzer/Checkers/DebugCheckers.cpp index 486b7f7feb..d9d569423d 100644 --- a/lib/StaticAnalyzer/Checkers/DebugCheckers.cpp +++ b/lib/StaticAnalyzer/Checkers/DebugCheckers.cpp @@ -28,7 +28,7 @@ class LiveVariablesDumper : public Checker<check::ASTCodeBody> { public: void checkASTCodeBody(const Decl *D, AnalysisManager& mgr, BugReporter &BR) const { - if (LiveVariables* L = mgr.getLiveVariables(D)) { + if (LiveVariables* L = mgr.getAnalysis<LiveVariables>(D)) { L->dumpBlockLiveness(mgr.getSourceManager()); } } diff --git a/lib/StaticAnalyzer/Core/SymbolManager.cpp b/lib/StaticAnalyzer/Core/SymbolManager.cpp index dc3a2fe660..b843ab1a90 100644 --- a/lib/StaticAnalyzer/Core/SymbolManager.cpp +++ b/lib/StaticAnalyzer/Core/SymbolManager.cpp @@ -382,8 +382,7 @@ bool SymbolReaper::isLive(SymbolRef sym) { } bool SymbolReaper::isLive(const Stmt *ExprVal) const { - return LCtx->getAnalysisContext()->getRelaxedLiveVariables()-> - isLive(Loc, ExprVal); + return LCtx->getAnalysis<RelaxedLiveVariables>()->isLive(Loc, ExprVal); } bool SymbolReaper::isLive(const VarRegion *VR, bool includeStoreBindings) const{ @@ -391,8 +390,7 @@ bool SymbolReaper::isLive(const VarRegion *VR, bool includeStoreBindings) const{ const StackFrameContext *CurrentContext = LCtx->getCurrentStackFrame(); if (VarContext == CurrentContext) { - if (LCtx->getAnalysisContext()->getRelaxedLiveVariables()-> - isLive(Loc, VR->getDecl())) + if (LCtx->getAnalysis<RelaxedLiveVariables>()->isLive(Loc, VR->getDecl())) return true; if (!includeStoreBindings) diff --git a/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp b/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp index 876136ba68..50cbefd142 100644 --- a/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp +++ b/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp @@ -304,10 +304,9 @@ void AnalysisConsumer::HandleCode(Decl *D) { static void ActionExprEngine(AnalysisConsumer &C, AnalysisManager &mgr, Decl *D, bool ObjCGCEnabled) { - // Construct the analysis engine. We first query for the LiveVariables - // information to see if the CFG is valid. + // Construct the analysis engine. First check if the CFG is valid. // FIXME: Inter-procedural analysis will need to handle invalid CFGs. - if (!mgr.getLiveVariables(D)) + if (!mgr.getCFG(D)) return; ExprEngine Eng(mgr, ObjCGCEnabled); |