forked from OSchip/llvm-project
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:
parent
881ec8534e
commit
dccc2b2277
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue