[analyzer] Remove LocationContext creation methods from AnalysisManager, and change clients to use AnalysisContext instead.

WIP to remove/reduce ExprEngine's usage of AnalysisManager.

llvm-svn: 142739
This commit is contained in:
Ted Kremenek 2011-10-23 02:31:52 +00:00
parent e94d277db8
commit 142adc492b
9 changed files with 130 additions and 75 deletions

View File

@ -38,7 +38,9 @@ class PseudoConstantAnalysis;
class ImplicitParamDecl;
class LocationContextManager;
class StackFrameContext;
class AnalysisContextManager;
class LocationContext;
namespace idx { class TranslationUnit; }
/// The base class of a hierarchy of objects representing analyses tied
@ -61,9 +63,14 @@ public:
// which creates the analysis object given an AnalysisContext.
};
/// AnalysisContext contains the context data for the function or method under
/// analysis.
class AnalysisContext {
/// Backpoint to the AnalysisManager object that created this AnalysisContext.
/// This may be null.
AnalysisContextManager *Manager;
const Decl *D;
// TranslationUnit is NULL if we don't have multiple translation units.
@ -91,10 +98,14 @@ class AnalysisContext {
void *ManagedAnalyses;
public:
AnalysisContext(const Decl *d, idx::TranslationUnit *tu);
AnalysisContext(AnalysisContextManager *Mgr,
const Decl *D,
idx::TranslationUnit *TU);
AnalysisContext(const Decl *d, idx::TranslationUnit *tu,
const CFG::BuildOptions &buildOptions);
AnalysisContext(AnalysisContextManager *Mgr,
const Decl *D,
idx::TranslationUnit *TU,
const CFG::BuildOptions &BuildOptions);
~AnalysisContext();
@ -155,6 +166,11 @@ public:
/// AnalysisContext wraps an ObjCMethodDecl. Returns NULL otherwise.
const ImplicitParamDecl *getSelfDecl() const;
const StackFrameContext *getStackFrame(LocationContext const *Parent,
const Stmt *S,
const CFGBlock *Blk,
unsigned Idx);
/// Return the specified analysis object, lazily running the analysis if
/// necessary. Return NULL if the analysis could not run.
template <typename T>
@ -168,31 +184,8 @@ public:
}
private:
ManagedAnalysis *&getAnalysisImpl(const void* tag);
};
class AnalysisContextManager {
typedef llvm::DenseMap<const Decl*, AnalysisContext*> ContextMap;
ContextMap Contexts;
CFG::BuildOptions cfgBuildOptions;
public:
AnalysisContextManager(bool useUnoptimizedCFG = false,
bool addImplicitDtors = false,
bool addInitializers = false);
~AnalysisContextManager();
AnalysisContext *getContext(const Decl *D, idx::TranslationUnit *TU = 0);
bool getUseUnoptimizedCFG() const {
return !cfgBuildOptions.PruneTriviallyFalseEdges;
}
CFG::BuildOptions &getCFGBuildOptions() {
return cfgBuildOptions;
}
/// Discard all previously created AnalysisContexts.
void clear();
LocationContextManager &getLocationContextManager();
};
class LocationContext : public llvm::FoldingSetNode {
@ -375,5 +368,64 @@ private:
const DATA *d);
};
class AnalysisContextManager {
typedef llvm::DenseMap<const Decl*, AnalysisContext*> ContextMap;
ContextMap Contexts;
LocationContextManager LocContexts;
CFG::BuildOptions cfgBuildOptions;
public:
AnalysisContextManager(bool useUnoptimizedCFG = false,
bool addImplicitDtors = false,
bool addInitializers = false);
~AnalysisContextManager();
AnalysisContext *getContext(const Decl *D, idx::TranslationUnit *TU = 0);
bool getUseUnoptimizedCFG() const {
return !cfgBuildOptions.PruneTriviallyFalseEdges;
}
CFG::BuildOptions &getCFGBuildOptions() {
return cfgBuildOptions;
}
const StackFrameContext *getStackFrame(AnalysisContext *Ctx,
LocationContext const *Parent,
const Stmt *S,
const CFGBlock *Blk,
unsigned Idx) {
return LocContexts.getStackFrame(Ctx, Parent, S, Blk, Idx);
}
// Get the top level stack frame.
const StackFrameContext *getStackFrame(Decl const *D,
idx::TranslationUnit *TU) {
return LocContexts.getStackFrame(getContext(D, TU), 0, 0, 0, 0);
}
// Get a stack frame with parent.
StackFrameContext const *getStackFrame(const Decl *D,
LocationContext const *Parent,
const Stmt *S,
const CFGBlock *Blk,
unsigned Idx) {
return LocContexts.getStackFrame(getContext(D), Parent, S, Blk, Idx);
}
/// Discard all previously created AnalysisContexts.
void clear();
private:
friend class AnalysisContext;
LocationContextManager &getLocationContextManager() {
return LocContexts;
}
};
} // end clang namespace
#endif

View File

@ -32,7 +32,6 @@ namespace ento {
class AnalysisManager : public BugReporterData {
AnalysisContextManager AnaCtxMgr;
LocationContextManager LocCtxMgr;
ASTContext &Ctx;
DiagnosticsEngine &Diags;
@ -97,7 +96,6 @@ public:
~AnalysisManager() { FlushDiagnostics(); }
void ClearContexts() {
LocCtxMgr.clear();
AnaCtxMgr.clear();
}
@ -189,30 +187,9 @@ public:
return AnaCtxMgr.getContext(D, TU);
}
const StackFrameContext *getStackFrame(AnalysisContext *Ctx,
LocationContext const *Parent,
const Stmt *S,
const CFGBlock *Blk, unsigned Idx) {
return LocCtxMgr.getStackFrame(Ctx, Parent, S, Blk, Idx);
}
// Get the top level stack frame.
const StackFrameContext *getStackFrame(Decl const *D,
idx::TranslationUnit *TU) {
return LocCtxMgr.getStackFrame(AnaCtxMgr.getContext(D, TU), 0, 0, 0, 0);
}
// Get a stack frame with parent.
StackFrameContext const *getStackFrame(const Decl *D,
LocationContext const *Parent,
const Stmt *S,
const CFGBlock *Blk, unsigned Idx) {
return LocCtxMgr.getStackFrame(AnaCtxMgr.getContext(D), Parent, S,
Blk,Idx);
}
};
} // end GR namespace
} // enAnaCtxMgrspace
} // end clang namespace

View File

@ -28,8 +28,9 @@
namespace clang {
class AnalysisContextManager;
class ObjCForCollectionStmt;
namespace ento {
class AnalysisManager;
@ -38,6 +39,8 @@ class ObjCMessage;
class ExprEngine : public SubEngine {
AnalysisManager &AMgr;
AnalysisContextManager &AnalysisContexts;
CoreEngine Engine;

View File

@ -32,10 +32,13 @@ using namespace clang;
typedef llvm::DenseMap<const void *, ManagedAnalysis *> ManagedAnalysisMap;
AnalysisContext::AnalysisContext(const Decl *d,
AnalysisContext::AnalysisContext(AnalysisContextManager *Mgr,
const Decl *d,
idx::TranslationUnit *tu,
const CFG::BuildOptions &buildOptions)
: D(d), TU(tu),
: Manager(Mgr),
D(d),
TU(tu),
cfgBuildOptions(buildOptions),
forcedBlkExprs(0),
builtCFG(false),
@ -46,9 +49,12 @@ AnalysisContext::AnalysisContext(const Decl *d,
cfgBuildOptions.forcedBlkExprs = &forcedBlkExprs;
}
AnalysisContext::AnalysisContext(const Decl *d,
AnalysisContext::AnalysisContext(AnalysisContextManager *Mgr,
const Decl *d,
idx::TranslationUnit *tu)
: D(d), TU(tu),
: Manager(Mgr),
D(d),
TU(tu),
forcedBlkExprs(0),
builtCFG(false),
builtCompleteCFG(false),
@ -184,10 +190,22 @@ AnalysisContext *AnalysisContextManager::getContext(const Decl *D,
idx::TranslationUnit *TU) {
AnalysisContext *&AC = Contexts[D];
if (!AC)
AC = new AnalysisContext(D, TU, cfgBuildOptions);
AC = new AnalysisContext(this, D, TU, cfgBuildOptions);
return AC;
}
const StackFrameContext *
AnalysisContext::getStackFrame(LocationContext const *Parent, const Stmt *S,
const CFGBlock *Blk, unsigned Idx) {
return getLocationContextManager().getStackFrame(this, Parent, S, Blk, Idx);
}
LocationContextManager & AnalysisContext::getLocationContextManager() {
assert(Manager &&
"Cannot create LocationContexts without an AnalysisContextManager!");
return Manager->getLocationContextManager();
}
//===----------------------------------------------------------------------===//
// FoldingSet profiling.
//===----------------------------------------------------------------------===//

View File

@ -830,7 +830,7 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
const Stmt *Body = D->getBody();
assert(Body);
AnalysisContext AC(D, 0);
AnalysisContext AC(/* AnalysisContextManager */ 0, D, 0);
// Don't generate EH edges for CallExprs as we'd like to avoid the n^2
// explosion for destrutors that can result and the compile time hit.

View File

@ -725,14 +725,16 @@ void CallEnterNodeBuilder::generateNode(const ProgramState *state) {
ExprEngine NewEng(AMgr, GCEnabled);
// Create the new LocationContext.
AnalysisContext *NewAnaCtx = AMgr.getAnalysisContext(CalleeCtx->getDecl(),
CalleeCtx->getTranslationUnit());
AnalysisContext *NewAnaCtx =
AMgr.getAnalysisContext(CalleeCtx->getDecl(),
CalleeCtx->getTranslationUnit());
const StackFrameContext *OldLocCtx = CalleeCtx;
const StackFrameContext *NewLocCtx = AMgr.getStackFrame(NewAnaCtx,
OldLocCtx->getParent(),
OldLocCtx->getCallSite(),
OldLocCtx->getCallSiteBlock(),
OldLocCtx->getIndex());
const StackFrameContext *NewLocCtx =
NewAnaCtx->getStackFrame(OldLocCtx->getParent(),
OldLocCtx->getCallSite(),
OldLocCtx->getCallSiteBlock(),
OldLocCtx->getIndex());
// Now create an initial state for the new engine.
const ProgramState *NewState =

View File

@ -53,6 +53,7 @@ static inline Selector GetNullarySelector(const char* name, ASTContext &Ctx) {
ExprEngine::ExprEngine(AnalysisManager &mgr, bool gcEnabled)
: AMgr(mgr),
AnalysisContexts(mgr.getAnalysisContextManager()),
Engine(*this),
G(Engine.getGraph()),
Builder(NULL),

View File

@ -215,17 +215,18 @@ void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *E,
}
void ExprEngine::VisitCXXDestructor(const CXXDestructorDecl *DD,
const MemRegion *Dest,
const Stmt *S,
ExplodedNode *Pred,
ExplodedNodeSet &Dst) {
const MemRegion *Dest,
const Stmt *S,
ExplodedNode *Pred,
ExplodedNodeSet &Dst) {
if (!(DD->doesThisDeclarationHaveABody() && AMgr.shouldInlineCall()))
return;
// Create the context for 'this' region.
const StackFrameContext *SFC = AMgr.getStackFrame(DD,
Pred->getLocationContext(),
S, Builder->getBlock(),
Builder->getIndex());
const StackFrameContext *SFC =
AnalysisContexts.getContext(DD)->
getStackFrame(Pred->getLocationContext(), S,
Builder->getBlock(), Builder->getIndex());
const CXXThisRegion *ThisR = getCXXThisRegion(DD->getParent(), SFC);

View File

@ -318,7 +318,8 @@ static void ActionExprEngine(AnalysisConsumer &C, AnalysisManager &mgr,
}
// Execute the worklist algorithm.
Eng.ExecuteWorkList(mgr.getStackFrame(D, 0), mgr.getMaxNodes());
Eng.ExecuteWorkList(mgr.getAnalysisContextManager().getStackFrame(D, 0),
mgr.getMaxNodes());
// Release the auditor (if any) so that it doesn't monitor the graph
// created BugReporter.