Make AnalysisManager stateless. Now other analyzer components only depends on
local node information.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@81433 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Analysis/AnalysisManager.cpp b/lib/Analysis/AnalysisManager.cpp
index 623db17..1aa459a 100644
--- a/lib/Analysis/AnalysisManager.cpp
+++ b/lib/Analysis/AnalysisManager.cpp
@@ -16,7 +16,7 @@
using namespace clang;
-void AnalysisManager::DisplayFunction() {
+void AnalysisManager::DisplayFunction(Decl *D) {
if (DisplayedFunction)
return;
@@ -24,12 +24,12 @@
DisplayedFunction = true;
// FIXME: Is getCodeDecl() always a named decl?
- if (isa<FunctionDecl>(getCodeDecl()) ||
- isa<ObjCMethodDecl>(getCodeDecl())) {
- const NamedDecl *ND = cast<NamedDecl>(getCodeDecl());
+ if (isa<FunctionDecl>(D) || isa<ObjCMethodDecl>(D)) {
+ const NamedDecl *ND = cast<NamedDecl>(D);
SourceManager &SM = getASTContext().getSourceManager();
llvm::errs() << "ANALYZE: "
<< SM.getPresumedLoc(ND->getLocation()).getFilename()
<< ' ' << ND->getNameAsString() << '\n';
}
}
+
diff --git a/lib/Analysis/BugReporter.cpp b/lib/Analysis/BugReporter.cpp
index 23ca53d..c15161c 100644
--- a/lib/Analysis/BugReporter.cpp
+++ b/lib/Analysis/BugReporter.cpp
@@ -36,14 +36,6 @@
if ((*I)->isOwnedByReporterContext()) delete *I;
}
-const Decl& BugReporterContext::getCodeDecl() {
- return *BR.getEngine().getAnalysisManager().getCodeDecl();
-}
-
-const CFG& BugReporterContext::getCFG() {
- return *BR.getEngine().getAnalysisManager().getCFG();
-}
-
//===----------------------------------------------------------------------===//
// Helper routines for walking the ExplodedGraph and fetching statements.
//===----------------------------------------------------------------------===//
@@ -158,11 +150,9 @@
PathDiagnosticLocation ExecutionContinues(llvm::raw_string_ostream& os,
const ExplodedNode* N);
- ParentMap& getParentMap() {
- if (PM.get() == 0)
- PM.reset(new ParentMap(getCodeDecl().getBody()));
- return *PM.get();
- }
+ Decl const &getCodeDecl() { return R->getEndNode()->getCodeDecl(); }
+
+ ParentMap& getParentMap() { return R->getEndNode()->getParentMap(); }
const Stmt *getParent(const Stmt *S) {
return getParentMap().getParent(S);
diff --git a/lib/Analysis/CFRefCount.cpp b/lib/Analysis/CFRefCount.cpp
index e511f76..8427679 100644
--- a/lib/Analysis/CFRefCount.cpp
+++ b/lib/Analysis/CFRefCount.cpp
@@ -2641,7 +2641,7 @@
}
if (!L.isValid()) {
- const Decl &D = BRC.getCodeDecl();
+ const Decl &D = EndN->getCodeDecl();
L = PathDiagnosticLocation(D.getBodyRBrace(), SMgr);
}
@@ -2660,7 +2660,7 @@
// FIXME: Per comments in rdar://6320065, "create" only applies to CF
// ojbects. Only "copy", "alloc", "retain" and "new" transfer ownership
// to the caller for NS objects.
- ObjCMethodDecl& MD = cast<ObjCMethodDecl>(BRC.getCodeDecl());
+ ObjCMethodDecl& MD = cast<ObjCMethodDecl>(EndN->getCodeDecl());
os << " is returned from a method whose name ('"
<< MD.getSelector().getAsString()
<< "') does not contain 'copy' or otherwise starts with"
@@ -2668,7 +2668,7 @@
" in the Memory Management Guide for Cocoa (object leaked)";
}
else if (RV->getKind() == RefVal::ErrorGCLeakReturned) {
- ObjCMethodDecl& MD = cast<ObjCMethodDecl>(BRC.getCodeDecl());
+ ObjCMethodDecl& MD = cast<ObjCMethodDecl>(EndN->getCodeDecl());
os << " and returned from method '" << MD.getSelector().getAsString()
<< "' is potentially leaked when using garbage collection. Callers "
"of this method do not expect a returned object with a +1 retain "
@@ -3186,7 +3186,7 @@
// Any leaks or other errors?
if (X.isReturnedOwned() && X.getCount() == 0) {
- const Decl *CD = Eng.getAnalysisManager().getCodeDecl();
+ Decl const *CD = &Pred->getCodeDecl();
if (const ObjCMethodDecl* MD = dyn_cast<ObjCMethodDecl>(CD)) {
const RetainSummary &Summ = *Summaries.getMethodSummary(MD);
RetEffect RE = Summ.getRetEffect();
@@ -3229,7 +3229,7 @@
}
}
else if (X.isReturnedNotOwned()) {
- const Decl *CD = Eng.getAnalysisManager().getCodeDecl();
+ Decl const *CD = &Pred->getCodeDecl();
if (const ObjCMethodDecl* MD = dyn_cast<ObjCMethodDecl>(CD)) {
const RetainSummary &Summ = *Summaries.getMethodSummary(MD);
if (Summ.getRetEffect().isOwned()) {
diff --git a/lib/Analysis/CheckDeadStores.cpp b/lib/Analysis/CheckDeadStores.cpp
index 716affb..d5cb7ca 100644
--- a/lib/Analysis/CheckDeadStores.cpp
+++ b/lib/Analysis/CheckDeadStores.cpp
@@ -251,9 +251,10 @@
} // end anonymous namespace
-void clang::CheckDeadStores(LiveVariables& L, BugReporter& BR) {
- FindEscaped FS(BR.getCFG());
+void clang::CheckDeadStores(CFG &cfg, LiveVariables &L, ParentMap &pmap,
+ BugReporter& BR) {
+ FindEscaped FS(&cfg);
FS.getCFG().VisitBlockStmts(FS);
- DeadStoreObs A(BR.getContext(), BR, BR.getParentMap(), FS.Escaped);
- L.runOnAllBlocks(*BR.getCFG(), &A);
+ DeadStoreObs A(BR.getContext(), BR, pmap, FS.Escaped);
+ L.runOnAllBlocks(cfg, &A);
}
diff --git a/lib/Analysis/GRExprEngine.cpp b/lib/Analysis/GRExprEngine.cpp
index ff9554c..986af10 100644
--- a/lib/Analysis/GRExprEngine.cpp
+++ b/lib/Analysis/GRExprEngine.cpp
@@ -262,7 +262,8 @@
Builder->setAuditor(BatchAuditor.get());
// Create the cleaned state.
- SymbolReaper SymReaper(*AMgr.getLiveVariables(), SymMgr);
+ SymbolReaper SymReaper(Builder->getBasePredecessor()->getLiveVariables(),
+ SymMgr);
CleanedState = AMgr.shouldPurgeDead()
? StateMgr.RemoveDeadBindings(EntryNode->getState(), CurrentStmt, SymReaper)
: EntryNode->getState();
@@ -1670,7 +1671,8 @@
static std::pair<const void*,const void*> EagerlyAssumeTag
= std::pair<const void*,const void*>(&EagerlyAssumeTag,0);
-void GRExprEngine::EvalEagerlyAssume(ExplodedNodeSet &Dst, ExplodedNodeSet &Src, Expr *Ex) {
+void GRExprEngine::EvalEagerlyAssume(ExplodedNodeSet &Dst, ExplodedNodeSet &Src,
+ Expr *Ex) {
for (ExplodedNodeSet::iterator I=Src.begin(), E=Src.end(); I!=E; ++I) {
ExplodedNode *Pred = *I;
@@ -1713,9 +1715,8 @@
// Transfer function: Objective-C ivar references.
//===----------------------------------------------------------------------===//
-void GRExprEngine::VisitObjCIvarRefExpr(ObjCIvarRefExpr* Ex,
- ExplodedNode* Pred, ExplodedNodeSet& Dst,
- bool asLValue) {
+void GRExprEngine::VisitObjCIvarRefExpr(ObjCIvarRefExpr* Ex, ExplodedNode* Pred,
+ ExplodedNodeSet& Dst, bool asLValue) {
Expr* Base = cast<Expr>(Ex->getBase());
ExplodedNodeSet Tmp;
@@ -1738,7 +1739,7 @@
//===----------------------------------------------------------------------===//
void GRExprEngine::VisitObjCForCollectionStmt(ObjCForCollectionStmt* S,
- ExplodedNode* Pred, ExplodedNodeSet& Dst) {
+ ExplodedNode* Pred, ExplodedNodeSet& Dst) {
// ObjCForCollectionStmts are processed in two places. This method
// handles the case where an ObjCForCollectionStmt* occurs as one of the
@@ -1786,7 +1787,7 @@
}
void GRExprEngine::VisitObjCForCollectionStmtAux(ObjCForCollectionStmt* S,
- ExplodedNode* Pred, ExplodedNodeSet& Dst,
+ ExplodedNode* Pred, ExplodedNodeSet& Dst,
SVal ElementV) {
@@ -1845,7 +1846,7 @@
void GRExprEngine::VisitObjCMessageExprArgHelper(ObjCMessageExpr* ME,
ObjCMessageExpr::arg_iterator AI,
ObjCMessageExpr::arg_iterator AE,
- ExplodedNode* Pred, ExplodedNodeSet& Dst) {
+ ExplodedNode* Pred, ExplodedNodeSet& Dst) {
if (AI == AE) {
// Process the receiver.
@@ -1854,7 +1855,8 @@
ExplodedNodeSet Tmp;
Visit(Receiver, Pred, Tmp);
- for (ExplodedNodeSet::iterator NI = Tmp.begin(), NE = Tmp.end(); NI != NE; ++NI)
+ for (ExplodedNodeSet::iterator NI = Tmp.begin(), NE = Tmp.end(); NI != NE;
+ ++NI)
VisitObjCMessageExprDispatchHelper(ME, *NI, Dst);
return;
@@ -1869,7 +1871,7 @@
++AI;
- for (ExplodedNodeSet::iterator NI = Tmp.begin(), NE = Tmp.end(); NI != NE; ++NI)
+ for (ExplodedNodeSet::iterator NI = Tmp.begin(), NE = Tmp.end();NI != NE;++NI)
VisitObjCMessageExprArgHelper(ME, AI, AE, *NI, Dst);
}
@@ -1910,7 +1912,7 @@
// Check if the receiver was nil and the return value a struct.
if (RetTy->isRecordType()) {
- if (BR.getParentMap().isConsumedExpr(ME)) {
+ if (Pred->getParentMap().isConsumedExpr(ME)) {
// The [0 ...] expressions will return garbage. Flag either an
// explicit or implicit error. Because of the structure of this
// function we currently do not bifurfacte the state graph at
@@ -1929,7 +1931,7 @@
else {
ASTContext& Ctx = getContext();
if (RetTy != Ctx.VoidTy) {
- if (BR.getParentMap().isConsumedExpr(ME)) {
+ if (Pred->getParentMap().isConsumedExpr(ME)) {
// sizeof(void *)
const uint64_t voidPtrSize = Ctx.getTypeSize(Ctx.VoidPtrTy);
// sizeof(return type)
diff --git a/lib/Frontend/AnalysisConsumer.cpp b/lib/Frontend/AnalysisConsumer.cpp
index 2d07d89..67328da 100644
--- a/lib/Frontend/AnalysisConsumer.cpp
+++ b/lib/Frontend/AnalysisConsumer.cpp
@@ -45,7 +45,7 @@
//===----------------------------------------------------------------------===//
namespace {
- typedef void (*CodeAction)(AnalysisManager& Mgr);
+ typedef void (*CodeAction)(AnalysisManager& Mgr, Decl *D);
} // end anonymous namespace
//===----------------------------------------------------------------------===//
@@ -223,10 +223,23 @@
}
void AnalysisConsumer::HandleTranslationUnit(ASTContext &C) {
- if (!TranslationUnitActions.empty()) {
- for (Actions::iterator I = TranslationUnitActions.begin(),
+ // Find the entry function definition.
+ FunctionDecl *FD = 0;
+ TranslationUnitDecl *TU = Ctx->getTranslationUnitDecl();
+ for (DeclContext::decl_iterator I = TU->decls_begin(), E = TU->decls_end();
+ I != E; ++I) {
+ if (FunctionDecl *fd = dyn_cast<FunctionDecl>(*I))
+ if (fd->isThisDeclarationADefinition() &&
+ fd->getNameAsString() == Opts.AnalyzeSpecificFunction) {
+ FD = fd;
+ break;
+ }
+ }
+
+ if(!TranslationUnitActions.empty()) {
+ for (Actions::iterator I = TranslationUnitActions.begin(),
E = TranslationUnitActions.end(); I != E; ++I)
- (*I)(*Mgr);
+ (*I)(*Mgr, FD);
}
if (!ObjCImplementationActions.empty()) {
@@ -245,7 +258,7 @@
Mgr.reset(NULL);
}
-void AnalysisConsumer::HandleCode(Decl* D, Stmt* Body, Actions& actions) {
+void AnalysisConsumer::HandleCode(Decl *D, Stmt* Body, Actions& actions) {
// Don't run the actions if an error has occured with parsing the file.
if (Diags.hasErrorOccurred())
@@ -257,41 +270,40 @@
!Ctx->getSourceManager().isFromMainFile(D->getLocation()))
return;
- Mgr->setEntryContext(D);
-
// Dispatch on the actions.
for (Actions::iterator I = actions.begin(), E = actions.end(); I != E; ++I)
- (*I)(*Mgr);
+ (*I)(*Mgr, D);
}
//===----------------------------------------------------------------------===//
// Analyses
//===----------------------------------------------------------------------===//
-static void ActionWarnDeadStores(AnalysisManager& mgr) {
- if (LiveVariables* L = mgr.getLiveVariables()) {
+static void ActionWarnDeadStores(AnalysisManager& mgr, Decl *D) {
+ if (LiveVariables *L = mgr.getLiveVariables(D)) {
BugReporter BR(mgr);
- CheckDeadStores(*L, BR);
+ CheckDeadStores(*mgr.getCFG(D), *L, mgr.getParentMap(D), BR);
}
}
-static void ActionWarnUninitVals(AnalysisManager& mgr) {
- if (CFG* c = mgr.getCFG())
+static void ActionWarnUninitVals(AnalysisManager& mgr, Decl *D) {
+ if (CFG* c = mgr.getCFG(D))
CheckUninitializedValues(*c, mgr.getASTContext(), mgr.getDiagnostic());
}
-static void ActionGRExprEngine(AnalysisManager& mgr, GRTransferFuncs* tf,
+static void ActionGRExprEngine(AnalysisManager& mgr, Decl *D,
+ GRTransferFuncs* tf,
bool StandardWarnings = true) {
llvm::OwningPtr<GRTransferFuncs> TF(tf);
// Display progress.
- mgr.DisplayFunction();
+ mgr.DisplayFunction(D);
// Construct the analysis engine.
- LiveVariables* L = mgr.getLiveVariables();
+ LiveVariables* L = mgr.getLiveVariables(D);
if (!L) return;
GRExprEngine Eng(mgr);
@@ -300,7 +312,7 @@
if (StandardWarnings) {
Eng.RegisterInternalChecks();
- RegisterAppleChecks(Eng, *mgr.getCodeDecl());
+ RegisterAppleChecks(Eng, *D);
}
// Set the graph auditor.
@@ -311,7 +323,7 @@
}
// Execute the worklist algorithm.
- Eng.ExecuteWorkList(mgr.getEntryStackFrame());
+ Eng.ExecuteWorkList(mgr.getStackFrame(D));
// Release the auditor (if any) so that it doesn't monitor the graph
// created BugReporter.
@@ -325,82 +337,79 @@
Eng.getBugReporter().FlushReports();
}
-static void ActionCheckerCFRefAux(AnalysisManager& mgr, bool GCEnabled,
- bool StandardWarnings) {
+static void ActionCheckerCFRefAux(AnalysisManager& mgr, Decl *D,
+ bool GCEnabled, bool StandardWarnings) {
GRTransferFuncs* TF = MakeCFRefCountTF(mgr.getASTContext(),
GCEnabled,
mgr.getLangOptions());
- ActionGRExprEngine(mgr, TF, StandardWarnings);
+ ActionGRExprEngine(mgr, D, TF, StandardWarnings);
}
-static void ActionCheckerCFRef(AnalysisManager& mgr) {
+static void ActionCheckerCFRef(AnalysisManager& mgr, Decl *D) {
switch (mgr.getLangOptions().getGCMode()) {
default:
assert (false && "Invalid GC mode.");
case LangOptions::NonGC:
- ActionCheckerCFRefAux(mgr, false, true);
+ ActionCheckerCFRefAux(mgr, D, false, true);
break;
case LangOptions::GCOnly:
- ActionCheckerCFRefAux(mgr, true, true);
+ ActionCheckerCFRefAux(mgr, D, true, true);
break;
case LangOptions::HybridGC:
- ActionCheckerCFRefAux(mgr, false, true);
- ActionCheckerCFRefAux(mgr, true, false);
+ ActionCheckerCFRefAux(mgr, D, false, true);
+ ActionCheckerCFRefAux(mgr, D, true, false);
break;
}
}
-static void ActionDisplayLiveVariables(AnalysisManager& mgr) {
- if (LiveVariables* L = mgr.getLiveVariables()) {
- mgr.DisplayFunction();
+static void ActionDisplayLiveVariables(AnalysisManager& mgr, Decl *D) {
+ if (LiveVariables* L = mgr.getLiveVariables(D)) {
+ mgr.DisplayFunction(D);
L->dumpBlockLiveness(mgr.getSourceManager());
}
}
-static void ActionCFGDump(AnalysisManager& mgr) {
- if (CFG* c = mgr.getCFG()) {
- mgr.DisplayFunction();
+static void ActionCFGDump(AnalysisManager& mgr, Decl *D) {
+ if (CFG* c = mgr.getCFG(D)) {
+ mgr.DisplayFunction(D);
c->dump(mgr.getLangOptions());
}
}
-static void ActionCFGView(AnalysisManager& mgr) {
- if (CFG* c = mgr.getCFG()) {
- mgr.DisplayFunction();
+static void ActionCFGView(AnalysisManager& mgr, Decl *D) {
+ if (CFG* c = mgr.getCFG(D)) {
+ mgr.DisplayFunction(D);
c->viewCFG(mgr.getLangOptions());
}
}
-static void ActionSecuritySyntacticChecks(AnalysisManager &mgr) {
+static void ActionSecuritySyntacticChecks(AnalysisManager &mgr, Decl *D) {
BugReporter BR(mgr);
- CheckSecuritySyntaxOnly(mgr.getCodeDecl(), BR);
+ CheckSecuritySyntaxOnly(D, BR);
}
-static void ActionWarnObjCDealloc(AnalysisManager& mgr) {
+static void ActionWarnObjCDealloc(AnalysisManager& mgr, Decl *D) {
if (mgr.getLangOptions().getGCMode() == LangOptions::GCOnly)
return;
BugReporter BR(mgr);
-
- CheckObjCDealloc(cast<ObjCImplementationDecl>(mgr.getCodeDecl()),
- mgr.getLangOptions(), BR);
+ CheckObjCDealloc(cast<ObjCImplementationDecl>(D), mgr.getLangOptions(), BR);
}
-static void ActionWarnObjCUnusedIvars(AnalysisManager& mgr) {
+static void ActionWarnObjCUnusedIvars(AnalysisManager& mgr, Decl *D) {
BugReporter BR(mgr);
- CheckObjCUnusedIvar(cast<ObjCImplementationDecl>(mgr.getCodeDecl()), BR);
+ CheckObjCUnusedIvar(cast<ObjCImplementationDecl>(D), BR);
}
-static void ActionWarnObjCMethSigs(AnalysisManager& mgr) {
+static void ActionWarnObjCMethSigs(AnalysisManager& mgr, Decl *D) {
BugReporter BR(mgr);
- CheckObjCInstMethSignature(cast<ObjCImplementationDecl>(mgr.getCodeDecl()),
- BR);
+ CheckObjCInstMethSignature(cast<ObjCImplementationDecl>(D), BR);
}
//===----------------------------------------------------------------------===//