Remove AnalysisContext::getLiveVariables(), and introduce a templatized mechanism to lazily create analyses that are attached to AnalysisContext objects.

llvm-svn: 141425
This commit is contained in:
Ted Kremenek 2011-10-07 22:21:02 +00:00
parent 881ec8534e
commit dccc2b2277
10 changed files with 97 additions and 37 deletions

View File

@ -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

View File

@ -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 {

View File

@ -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) {

View File

@ -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; }

View File

@ -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() {

View File

@ -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; }

View File

@ -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);

View File

@ -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());
}
}

View File

@ -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)

View File

@ -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);