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;
bool DisplayedFunction;
bool VisualizeEGDot;
bool VisualizeEGUbi;
bool PurgeDead;
@ -62,7 +61,7 @@ public:
: Ctx(ctx), Diags(diags), LangInfo(lang), PD(pd),
CreateStoreMgr(storemgr), CreateConstraintMgr(constraintmgr),
AScope(ScopeDecl), DisplayedFunction(!displayProgress),
AScope(ScopeDecl),
VisualizeEGDot(vizdot), VisualizeEGUbi(vizubi), PurgeDead(purge),
EagerlyAssume(eager), TrimGraph(trim) {}
@ -120,8 +119,6 @@ public:
bool shouldEagerlyAssume() const { return EagerlyAssume; }
void DisplayFunction(Decl *D);
CFG *getCFG(Decl const *D) {
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 {
typedef void (*CodeAction)(AnalysisManager& Mgr, Decl *D);
class AnalysisConsumer;
typedef void (*CodeAction)(AnalysisConsumer &C, AnalysisManager &M, Decl *D);
} // end anonymous namespace
//===----------------------------------------------------------------------===//
@ -66,111 +67,125 @@ CreatePlistHTMLDiagnosticClient(const std::string& prefix,
namespace {
class VISIBILITY_HIDDEN AnalysisConsumer : public ASTConsumer {
typedef std::vector<CodeAction> Actions;
Actions FunctionActions;
Actions ObjCMethodActions;
Actions ObjCImplementationActions;
Actions TranslationUnitActions;
class VISIBILITY_HIDDEN AnalysisConsumer : public ASTConsumer {
typedef std::vector<CodeAction> Actions;
Actions FunctionActions;
Actions ObjCMethodActions;
Actions ObjCImplementationActions;
Actions TranslationUnitActions;
public:
ASTContext* Ctx;
const Preprocessor &PP;
const std::string OutDir;
AnalyzerOptions Opts;
public:
ASTContext* Ctx;
const Preprocessor &PP;
const std::string OutDir;
AnalyzerOptions Opts;
bool declDisplayed;
// PD is owned by AnalysisManager.
PathDiagnosticClient *PD;
// PD is owned by AnalysisManager.
PathDiagnosticClient *PD;
StoreManagerCreator CreateStoreMgr;
ConstraintManagerCreator CreateConstraintMgr;
StoreManagerCreator CreateStoreMgr;
ConstraintManagerCreator CreateConstraintMgr;
llvm::OwningPtr<AnalysisManager> Mgr;
llvm::OwningPtr<AnalysisManager> Mgr;
AnalysisConsumer(const Preprocessor& pp,
const std::string& outdir,
const AnalyzerOptions& opts)
: Ctx(0), PP(pp), OutDir(outdir),
Opts(opts), PD(0) {
DigestAnalyzerOptions();
}
AnalysisConsumer(const Preprocessor& pp,
const std::string& outdir,
const AnalyzerOptions& opts)
: Ctx(0), PP(pp), OutDir(outdir),
Opts(opts), declDisplayed(false), PD(0) {
DigestAnalyzerOptions();
}
void DigestAnalyzerOptions() {
// Create the PathDiagnosticClient.
if (!OutDir.empty()) {
switch (Opts.AnalysisDiagOpt) {
default:
void DigestAnalyzerOptions() {
// Create the PathDiagnosticClient.
if (!OutDir.empty()) {
switch (Opts.AnalysisDiagOpt) {
default:
#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"
}
}
}
// Create the analyzer component creators.
if (ManagerRegistry::StoreMgrCreator != 0) {
CreateStoreMgr = ManagerRegistry::StoreMgrCreator;
}
else {
switch (Opts.AnalysisStoreOpt) {
default:
assert(0 && "Unknown store manager.");
// Create the analyzer component creators.
if (ManagerRegistry::StoreMgrCreator != 0) {
CreateStoreMgr = ManagerRegistry::StoreMgrCreator;
}
else {
switch (Opts.AnalysisStoreOpt) {
default:
assert(0 && "Unknown store manager.");
#define ANALYSIS_STORE(NAME, CMDFLAG, DESC, CREATEFN) \
case NAME##Model: CreateStoreMgr = CREATEFN; break;
case NAME##Model: CreateStoreMgr = CREATEFN; break;
#include "clang/Frontend/Analyses.def"
}
}
}
if (ManagerRegistry::ConstraintMgrCreator != 0)
CreateConstraintMgr = ManagerRegistry::ConstraintMgrCreator;
else {
switch (Opts.AnalysisConstraintsOpt) {
default:
assert(0 && "Unknown store manager.");
if (ManagerRegistry::ConstraintMgrCreator != 0)
CreateConstraintMgr = ManagerRegistry::ConstraintMgrCreator;
else {
switch (Opts.AnalysisConstraintsOpt) {
default:
assert(0 && "Unknown store manager.");
#define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATEFN) \
case NAME##Model: CreateConstraintMgr = CREATEFN; break;
case NAME##Model: CreateConstraintMgr = CREATEFN; break;
#include "clang/Frontend/Analyses.def"
}
}
}
}
void addCodeAction(CodeAction action) {
FunctionActions.push_back(action);
ObjCMethodActions.push_back(action);
void DisplayFunction(const Decl *D) {
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) {
ObjCImplementationActions.push_back(action);
}
void addCodeAction(CodeAction action) {
FunctionActions.push_back(action);
ObjCMethodActions.push_back(action);
}
void addTranslationUnitAction(CodeAction action) {
TranslationUnitActions.push_back(action);
}
void addObjCImplementationAction(CodeAction action) {
ObjCImplementationActions.push_back(action);
}
virtual void Initialize(ASTContext &Context) {
Ctx = &Context;
Mgr.reset(new AnalysisManager(*Ctx, PP.getDiagnostics(),
PP.getLangOptions(), PD,
CreateStoreMgr, CreateConstraintMgr,
Opts.AnalyzerDisplayProgress,
Opts.VisualizeEGDot, Opts.VisualizeEGUbi,
Opts.PurgeDead, Opts.EagerlyAssume,
Opts.TrimGraph));
}
void addTranslationUnitAction(CodeAction action) {
TranslationUnitActions.push_back(action);
}
virtual void HandleTopLevelDecl(DeclGroupRef D) {
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);
};
virtual void Initialize(ASTContext &Context) {
Ctx = &Context;
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) {
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
namespace llvm {
@ -238,7 +253,7 @@ void AnalysisConsumer::HandleTranslationUnit(ASTContext &C) {
for (Actions::iterator I = TranslationUnitActions.begin(),
E = TranslationUnitActions.end(); I != E; ++I)
(*I)(*Mgr, FD);
(*I)(*this, *Mgr, FD);
}
if (!ObjCImplementationActions.empty()) {
@ -272,34 +287,38 @@ void AnalysisConsumer::HandleCode(Decl *D, Stmt* Body, Actions& actions) {
// Dispatch on the actions.
for (Actions::iterator I = actions.begin(), E = actions.end(); I != E; ++I)
(*I)(*Mgr, D);
(*I)(*this, *Mgr, D);
}
//===----------------------------------------------------------------------===//
// Analyses
//===----------------------------------------------------------------------===//
static void ActionWarnDeadStores(AnalysisManager& mgr, Decl *D) {
static void ActionWarnDeadStores(AnalysisConsumer &C, AnalysisManager& mgr,
Decl *D) {
if (LiveVariables *L = mgr.getLiveVariables(D)) {
C.DisplayFunction(D);
BugReporter BR(mgr);
CheckDeadStores(*mgr.getCFG(D), *L, mgr.getParentMap(D), BR);
}
}
static void ActionWarnUninitVals(AnalysisManager& mgr, Decl *D) {
if (CFG* c = mgr.getCFG(D))
static void ActionWarnUninitVals(AnalysisConsumer &C, AnalysisManager& mgr,
Decl *D) {
if (CFG* c = mgr.getCFG(D)) {
C.DisplayFunction(D);
CheckUninitializedValues(*c, mgr.getASTContext(), mgr.getDiagnostic());
}
}
static void ActionGRExprEngine(AnalysisManager& mgr, Decl *D,
static void ActionGRExprEngine(AnalysisConsumer &C, AnalysisManager& mgr, Decl *D,
GRTransferFuncs* tf) {
llvm::OwningPtr<GRTransferFuncs> TF(tf);
// Display progress.
mgr.DisplayFunction(D);
C.DisplayFunction(D);
// Construct the analysis engine. We first query for the LiveVariables
// information to see if the CFG is valid.
@ -337,90 +356,103 @@ static void ActionGRExprEngine(AnalysisManager& mgr, Decl *D,
Eng.getBugReporter().FlushReports();
}
static void ActionCheckerCFRefAux(AnalysisManager& mgr, Decl *D,
bool GCEnabled) {
static void ActionCheckerCFRefAux(AnalysisConsumer &C, AnalysisManager& mgr,
Decl *D, bool GCEnabled) {
GRTransferFuncs* TF = MakeCFRefCountTF(mgr.getASTContext(),
GCEnabled,
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()) {
default:
assert (false && "Invalid GC mode.");
case LangOptions::NonGC:
ActionCheckerCFRefAux(mgr, D, false);
ActionCheckerCFRefAux(C, mgr, D, false);
break;
case LangOptions::GCOnly:
ActionCheckerCFRefAux(mgr, D, true);
ActionCheckerCFRefAux(C, mgr, D, true);
break;
case LangOptions::HybridGC:
ActionCheckerCFRefAux(mgr, D, false);
ActionCheckerCFRefAux(mgr, D, true);
ActionCheckerCFRefAux(C, mgr, D, false);
ActionCheckerCFRefAux(C, mgr, D, true);
break;
}
}
static void ActionDisplayLiveVariables(AnalysisManager& mgr, Decl *D) {
static void ActionDisplayLiveVariables(AnalysisConsumer &C,
AnalysisManager& mgr, Decl *D) {
if (LiveVariables* L = mgr.getLiveVariables(D)) {
mgr.DisplayFunction(D);
C.DisplayFunction(D);
L->dumpBlockLiveness(mgr.getSourceManager());
}
}
static void ActionCFGDump(AnalysisManager& mgr, Decl *D) {
if (CFG* c = mgr.getCFG(D)) {
mgr.DisplayFunction(D);
c->dump(mgr.getLangOptions());
static void ActionCFGDump(AnalysisConsumer &C, AnalysisManager& mgr, Decl *D) {
if (CFG *cfg = mgr.getCFG(D)) {
C.DisplayFunction(D);
cfg->dump(mgr.getLangOptions());
}
}
static void ActionCFGView(AnalysisManager& mgr, Decl *D) {
if (CFG* c = mgr.getCFG(D)) {
mgr.DisplayFunction(D);
c->viewCFG(mgr.getLangOptions());
static void ActionCFGView(AnalysisConsumer &C, AnalysisManager& mgr, Decl *D) {
if (CFG *cfg = mgr.getCFG(D)) {
C.DisplayFunction(D);
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);
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)
return;
C.DisplayFunction(D);
BugReporter BR(mgr);
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);
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);
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);
CheckSizeofPointer(D, BR);
}
static void ActionInlineCall(AnalysisManager &mgr, Decl *D) {
static void ActionInlineCall(AnalysisConsumer &C, AnalysisManager &mgr,
Decl *D) {
if (!D)
return;
C.DisplayFunction(D);
llvm::OwningPtr<GRTransferFuncs> TF(CreateCallInliner(mgr.getASTContext()));
// Construct the analysis engine.