Fix display of "ANALYZE" statements in AnalysisConsumer by correctly resetting the flag indicating that the current Decl* has not yet been displayed. Also move this out of AnalysisManager, since AnalysisManager should not handle text output to the user.

llvm-svn: 86812
This commit is contained in:
Ted Kremenek 2009-11-11 06:28:42 +00:00
parent 999215c8c8
commit 55d59bf785
3 changed files with 147 additions and 153 deletions

View File

@ -37,7 +37,6 @@ class AnalysisManager : public BugReporterData {
enum AnalysisScope { ScopeTU, ScopeDecl } AScope; enum AnalysisScope { ScopeTU, ScopeDecl } AScope;
bool DisplayedFunction;
bool VisualizeEGDot; bool VisualizeEGDot;
bool VisualizeEGUbi; bool VisualizeEGUbi;
bool PurgeDead; bool PurgeDead;
@ -62,7 +61,7 @@ public:
: Ctx(ctx), Diags(diags), LangInfo(lang), PD(pd), : Ctx(ctx), Diags(diags), LangInfo(lang), PD(pd),
CreateStoreMgr(storemgr), CreateConstraintMgr(constraintmgr), CreateStoreMgr(storemgr), CreateConstraintMgr(constraintmgr),
AScope(ScopeDecl), DisplayedFunction(!displayProgress), AScope(ScopeDecl),
VisualizeEGDot(vizdot), VisualizeEGUbi(vizubi), PurgeDead(purge), VisualizeEGDot(vizdot), VisualizeEGUbi(vizubi), PurgeDead(purge),
EagerlyAssume(eager), TrimGraph(trim) {} EagerlyAssume(eager), TrimGraph(trim) {}
@ -120,8 +119,6 @@ public:
bool shouldEagerlyAssume() const { return EagerlyAssume; } bool shouldEagerlyAssume() const { return EagerlyAssume; }
void DisplayFunction(Decl *D);
CFG *getCFG(Decl const *D) { CFG *getCFG(Decl const *D) {
return AnaCtxMgr.getContext(D)->getCFG(); return AnaCtxMgr.getContext(D)->getCFG();
} }

View File

@ -1,35 +0,0 @@
//== AnalysisManager.cpp - Path sensitive analysis data manager ----*- C++ -*-//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the AnalysisManager class.
//
//===----------------------------------------------------------------------===//
#include "clang/Analysis/PathSensitive/AnalysisManager.h"
#include "clang/Basic/SourceManager.h"
using namespace clang;
void AnalysisManager::DisplayFunction(Decl *D) {
if (DisplayedFunction)
return;
DisplayedFunction = true;
// FIXME: Is getCodeDecl() always a named decl?
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').flush();
}
}

View File

@ -45,7 +45,8 @@ static ExplodedNode::Auditor* CreateUbiViz();
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
namespace { namespace {
typedef void (*CodeAction)(AnalysisManager& Mgr, Decl *D); class AnalysisConsumer;
typedef void (*CodeAction)(AnalysisConsumer &C, AnalysisManager &M, Decl *D);
} // end anonymous namespace } // end anonymous namespace
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
@ -66,111 +67,125 @@ CreatePlistHTMLDiagnosticClient(const std::string& prefix,
namespace { namespace {
class VISIBILITY_HIDDEN AnalysisConsumer : public ASTConsumer { class VISIBILITY_HIDDEN AnalysisConsumer : public ASTConsumer {
typedef std::vector<CodeAction> Actions; typedef std::vector<CodeAction> Actions;
Actions FunctionActions; Actions FunctionActions;
Actions ObjCMethodActions; Actions ObjCMethodActions;
Actions ObjCImplementationActions; Actions ObjCImplementationActions;
Actions TranslationUnitActions; Actions TranslationUnitActions;
public: public:
ASTContext* Ctx; ASTContext* Ctx;
const Preprocessor &PP; const Preprocessor &PP;
const std::string OutDir; const std::string OutDir;
AnalyzerOptions Opts; AnalyzerOptions Opts;
bool declDisplayed;
// PD is owned by AnalysisManager. // PD is owned by AnalysisManager.
PathDiagnosticClient *PD; PathDiagnosticClient *PD;
StoreManagerCreator CreateStoreMgr; StoreManagerCreator CreateStoreMgr;
ConstraintManagerCreator CreateConstraintMgr; ConstraintManagerCreator CreateConstraintMgr;
llvm::OwningPtr<AnalysisManager> Mgr; llvm::OwningPtr<AnalysisManager> Mgr;
AnalysisConsumer(const Preprocessor& pp, AnalysisConsumer(const Preprocessor& pp,
const std::string& outdir, const std::string& outdir,
const AnalyzerOptions& opts) const AnalyzerOptions& opts)
: Ctx(0), PP(pp), OutDir(outdir), : Ctx(0), PP(pp), OutDir(outdir),
Opts(opts), PD(0) { Opts(opts), declDisplayed(false), PD(0) {
DigestAnalyzerOptions(); DigestAnalyzerOptions();
} }
void DigestAnalyzerOptions() { void DigestAnalyzerOptions() {
// Create the PathDiagnosticClient. // Create the PathDiagnosticClient.
if (!OutDir.empty()) { if (!OutDir.empty()) {
switch (Opts.AnalysisDiagOpt) { switch (Opts.AnalysisDiagOpt) {
default: default:
#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN, AUTOCREATE) \ #define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN, AUTOCREATE) \
case PD_##NAME: PD = CREATEFN(OutDir, PP); break; case PD_##NAME: PD = CREATEFN(OutDir, PP); break;
#include "clang/Frontend/Analyses.def" #include "clang/Frontend/Analyses.def"
}
} }
}
// Create the analyzer component creators. // Create the analyzer component creators.
if (ManagerRegistry::StoreMgrCreator != 0) { if (ManagerRegistry::StoreMgrCreator != 0) {
CreateStoreMgr = ManagerRegistry::StoreMgrCreator; CreateStoreMgr = ManagerRegistry::StoreMgrCreator;
} }
else { else {
switch (Opts.AnalysisStoreOpt) { switch (Opts.AnalysisStoreOpt) {
default: default:
assert(0 && "Unknown store manager."); assert(0 && "Unknown store manager.");
#define ANALYSIS_STORE(NAME, CMDFLAG, DESC, CREATEFN) \ #define ANALYSIS_STORE(NAME, CMDFLAG, DESC, CREATEFN) \
case NAME##Model: CreateStoreMgr = CREATEFN; break; case NAME##Model: CreateStoreMgr = CREATEFN; break;
#include "clang/Frontend/Analyses.def" #include "clang/Frontend/Analyses.def"
}
} }
}
if (ManagerRegistry::ConstraintMgrCreator != 0) if (ManagerRegistry::ConstraintMgrCreator != 0)
CreateConstraintMgr = ManagerRegistry::ConstraintMgrCreator; CreateConstraintMgr = ManagerRegistry::ConstraintMgrCreator;
else { else {
switch (Opts.AnalysisConstraintsOpt) { switch (Opts.AnalysisConstraintsOpt) {
default: default:
assert(0 && "Unknown store manager."); assert(0 && "Unknown store manager.");
#define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATEFN) \ #define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATEFN) \
case NAME##Model: CreateConstraintMgr = CREATEFN; break; case NAME##Model: CreateConstraintMgr = CREATEFN; break;
#include "clang/Frontend/Analyses.def" #include "clang/Frontend/Analyses.def"
}
} }
} }
}
void addCodeAction(CodeAction action) {
FunctionActions.push_back(action); void DisplayFunction(const Decl *D) {
ObjCMethodActions.push_back(action); if (!Opts.AnalyzerDisplayProgress || declDisplayed)
return;
declDisplayed = true;
// FIXME: Is getCodeDecl() always a named decl?
if (isa<FunctionDecl>(D) || isa<ObjCMethodDecl>(D)) {
const NamedDecl *ND = cast<NamedDecl>(D);
SourceManager &SM = Mgr->getASTContext().getSourceManager();
llvm::errs() << "ANALYZE: "
<< SM.getPresumedLoc(ND->getLocation()).getFilename()
<< ' ' << ND->getNameAsString() << '\n';
} }
}
void addObjCImplementationAction(CodeAction action) { void addCodeAction(CodeAction action) {
ObjCImplementationActions.push_back(action); FunctionActions.push_back(action);
} ObjCMethodActions.push_back(action);
}
void addTranslationUnitAction(CodeAction action) { void addObjCImplementationAction(CodeAction action) {
TranslationUnitActions.push_back(action); ObjCImplementationActions.push_back(action);
} }
virtual void Initialize(ASTContext &Context) { void addTranslationUnitAction(CodeAction action) {
Ctx = &Context; TranslationUnitActions.push_back(action);
Mgr.reset(new AnalysisManager(*Ctx, PP.getDiagnostics(), }
PP.getLangOptions(), PD,
CreateStoreMgr, CreateConstraintMgr,
Opts.AnalyzerDisplayProgress,
Opts.VisualizeEGDot, Opts.VisualizeEGUbi,
Opts.PurgeDead, Opts.EagerlyAssume,
Opts.TrimGraph));
}
virtual void HandleTopLevelDecl(DeclGroupRef D) { virtual void Initialize(ASTContext &Context) {
for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I) Ctx = &Context;
HandleTopLevelSingleDecl(*I); Mgr.reset(new AnalysisManager(*Ctx, PP.getDiagnostics(),
} PP.getLangOptions(), PD,
CreateStoreMgr, CreateConstraintMgr,
void HandleTopLevelSingleDecl(Decl *D); Opts.AnalyzerDisplayProgress,
virtual void HandleTranslationUnit(ASTContext &C); Opts.VisualizeEGDot, Opts.VisualizeEGUbi,
Opts.PurgeDead, Opts.EagerlyAssume,
void HandleCode(Decl* D, Stmt* Body, Actions& actions); Opts.TrimGraph));
}; }
virtual void HandleTopLevelDecl(DeclGroupRef D) {
declDisplayed = false;
for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I)
HandleTopLevelSingleDecl(*I);
}
void HandleTopLevelSingleDecl(Decl *D);
virtual void HandleTranslationUnit(ASTContext &C);
void HandleCode(Decl* D, Stmt* Body, Actions& actions);
};
} // end anonymous namespace } // end anonymous namespace
namespace llvm { namespace llvm {
@ -238,7 +253,7 @@ void AnalysisConsumer::HandleTranslationUnit(ASTContext &C) {
for (Actions::iterator I = TranslationUnitActions.begin(), for (Actions::iterator I = TranslationUnitActions.begin(),
E = TranslationUnitActions.end(); I != E; ++I) E = TranslationUnitActions.end(); I != E; ++I)
(*I)(*Mgr, FD); (*I)(*this, *Mgr, FD);
} }
if (!ObjCImplementationActions.empty()) { if (!ObjCImplementationActions.empty()) {
@ -272,34 +287,38 @@ void AnalysisConsumer::HandleCode(Decl *D, Stmt* Body, Actions& actions) {
// Dispatch on the actions. // Dispatch on the actions.
for (Actions::iterator I = actions.begin(), E = actions.end(); I != E; ++I) for (Actions::iterator I = actions.begin(), E = actions.end(); I != E; ++I)
(*I)(*Mgr, D); (*I)(*this, *Mgr, D);
} }
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// Analyses // Analyses
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
static void ActionWarnDeadStores(AnalysisManager& mgr, Decl *D) { static void ActionWarnDeadStores(AnalysisConsumer &C, AnalysisManager& mgr,
Decl *D) {
if (LiveVariables *L = mgr.getLiveVariables(D)) { if (LiveVariables *L = mgr.getLiveVariables(D)) {
C.DisplayFunction(D);
BugReporter BR(mgr); BugReporter BR(mgr);
CheckDeadStores(*mgr.getCFG(D), *L, mgr.getParentMap(D), BR); CheckDeadStores(*mgr.getCFG(D), *L, mgr.getParentMap(D), BR);
} }
} }
static void ActionWarnUninitVals(AnalysisManager& mgr, Decl *D) { static void ActionWarnUninitVals(AnalysisConsumer &C, AnalysisManager& mgr,
if (CFG* c = mgr.getCFG(D)) Decl *D) {
if (CFG* c = mgr.getCFG(D)) {
C.DisplayFunction(D);
CheckUninitializedValues(*c, mgr.getASTContext(), mgr.getDiagnostic()); CheckUninitializedValues(*c, mgr.getASTContext(), mgr.getDiagnostic());
}
} }
static void ActionGRExprEngine(AnalysisManager& mgr, Decl *D, static void ActionGRExprEngine(AnalysisConsumer &C, AnalysisManager& mgr, Decl *D,
GRTransferFuncs* tf) { GRTransferFuncs* tf) {
llvm::OwningPtr<GRTransferFuncs> TF(tf); llvm::OwningPtr<GRTransferFuncs> TF(tf);
// Display progress. // Display progress.
mgr.DisplayFunction(D); C.DisplayFunction(D);
// Construct the analysis engine. We first query for the LiveVariables // Construct the analysis engine. We first query for the LiveVariables
// information to see if the CFG is valid. // information to see if the CFG is valid.
@ -337,90 +356,103 @@ static void ActionGRExprEngine(AnalysisManager& mgr, Decl *D,
Eng.getBugReporter().FlushReports(); Eng.getBugReporter().FlushReports();
} }
static void ActionCheckerCFRefAux(AnalysisManager& mgr, Decl *D, static void ActionCheckerCFRefAux(AnalysisConsumer &C, AnalysisManager& mgr,
bool GCEnabled) { Decl *D, bool GCEnabled) {
GRTransferFuncs* TF = MakeCFRefCountTF(mgr.getASTContext(), GRTransferFuncs* TF = MakeCFRefCountTF(mgr.getASTContext(),
GCEnabled, GCEnabled,
mgr.getLangOptions()); mgr.getLangOptions());
ActionGRExprEngine(mgr, D, TF); ActionGRExprEngine(C, mgr, D, TF);
} }
static void ActionCheckerCFRef(AnalysisManager& mgr, Decl *D) { static void ActionCheckerCFRef(AnalysisConsumer &C, AnalysisManager& mgr,
Decl *D) {
switch (mgr.getLangOptions().getGCMode()) { switch (mgr.getLangOptions().getGCMode()) {
default: default:
assert (false && "Invalid GC mode."); assert (false && "Invalid GC mode.");
case LangOptions::NonGC: case LangOptions::NonGC:
ActionCheckerCFRefAux(mgr, D, false); ActionCheckerCFRefAux(C, mgr, D, false);
break; break;
case LangOptions::GCOnly: case LangOptions::GCOnly:
ActionCheckerCFRefAux(mgr, D, true); ActionCheckerCFRefAux(C, mgr, D, true);
break; break;
case LangOptions::HybridGC: case LangOptions::HybridGC:
ActionCheckerCFRefAux(mgr, D, false); ActionCheckerCFRefAux(C, mgr, D, false);
ActionCheckerCFRefAux(mgr, D, true); ActionCheckerCFRefAux(C, mgr, D, true);
break; break;
} }
} }
static void ActionDisplayLiveVariables(AnalysisManager& mgr, Decl *D) { static void ActionDisplayLiveVariables(AnalysisConsumer &C,
AnalysisManager& mgr, Decl *D) {
if (LiveVariables* L = mgr.getLiveVariables(D)) { if (LiveVariables* L = mgr.getLiveVariables(D)) {
mgr.DisplayFunction(D); C.DisplayFunction(D);
L->dumpBlockLiveness(mgr.getSourceManager()); L->dumpBlockLiveness(mgr.getSourceManager());
} }
} }
static void ActionCFGDump(AnalysisManager& mgr, Decl *D) { static void ActionCFGDump(AnalysisConsumer &C, AnalysisManager& mgr, Decl *D) {
if (CFG* c = mgr.getCFG(D)) { if (CFG *cfg = mgr.getCFG(D)) {
mgr.DisplayFunction(D); C.DisplayFunction(D);
c->dump(mgr.getLangOptions()); cfg->dump(mgr.getLangOptions());
} }
} }
static void ActionCFGView(AnalysisManager& mgr, Decl *D) { static void ActionCFGView(AnalysisConsumer &C, AnalysisManager& mgr, Decl *D) {
if (CFG* c = mgr.getCFG(D)) { if (CFG *cfg = mgr.getCFG(D)) {
mgr.DisplayFunction(D); C.DisplayFunction(D);
c->viewCFG(mgr.getLangOptions()); cfg->viewCFG(mgr.getLangOptions());
} }
} }
static void ActionSecuritySyntacticChecks(AnalysisManager &mgr, Decl *D) { static void ActionSecuritySyntacticChecks(AnalysisConsumer &C,
AnalysisManager &mgr, Decl *D) {
C.DisplayFunction(D);
BugReporter BR(mgr); BugReporter BR(mgr);
CheckSecuritySyntaxOnly(D, BR); CheckSecuritySyntaxOnly(D, BR);
} }
static void ActionWarnObjCDealloc(AnalysisManager& mgr, Decl *D) { static void ActionWarnObjCDealloc(AnalysisConsumer &C, AnalysisManager& mgr,
Decl *D) {
if (mgr.getLangOptions().getGCMode() == LangOptions::GCOnly) if (mgr.getLangOptions().getGCMode() == LangOptions::GCOnly)
return; return;
C.DisplayFunction(D);
BugReporter BR(mgr); BugReporter BR(mgr);
CheckObjCDealloc(cast<ObjCImplementationDecl>(D), mgr.getLangOptions(), BR); CheckObjCDealloc(cast<ObjCImplementationDecl>(D), mgr.getLangOptions(), BR);
} }
static void ActionWarnObjCUnusedIvars(AnalysisManager& mgr, Decl *D) { static void ActionWarnObjCUnusedIvars(AnalysisConsumer &C, AnalysisManager& mgr,
Decl *D) {
C.DisplayFunction(D);
BugReporter BR(mgr); BugReporter BR(mgr);
CheckObjCUnusedIvar(cast<ObjCImplementationDecl>(D), BR); CheckObjCUnusedIvar(cast<ObjCImplementationDecl>(D), BR);
} }
static void ActionWarnObjCMethSigs(AnalysisManager& mgr, Decl *D) { static void ActionWarnObjCMethSigs(AnalysisConsumer &C, AnalysisManager& mgr,
Decl *D) {
C.DisplayFunction(D);
BugReporter BR(mgr); BugReporter BR(mgr);
CheckObjCInstMethSignature(cast<ObjCImplementationDecl>(D), BR); CheckObjCInstMethSignature(cast<ObjCImplementationDecl>(D), BR);
} }
static void ActionWarnSizeofPointer(AnalysisManager &mgr, Decl *D) { static void ActionWarnSizeofPointer(AnalysisConsumer &C, AnalysisManager &mgr,
Decl *D) {
C.DisplayFunction(D);
BugReporter BR(mgr); BugReporter BR(mgr);
CheckSizeofPointer(D, BR); CheckSizeofPointer(D, BR);
} }
static void ActionInlineCall(AnalysisManager &mgr, Decl *D) { static void ActionInlineCall(AnalysisConsumer &C, AnalysisManager &mgr,
Decl *D) {
if (!D) if (!D)
return; return;
C.DisplayFunction(D);
llvm::OwningPtr<GRTransferFuncs> TF(CreateCallInliner(mgr.getASTContext())); llvm::OwningPtr<GRTransferFuncs> TF(CreateCallInliner(mgr.getASTContext()));
// Construct the analysis engine. // Construct the analysis engine.