forked from OSchip/llvm-project
switch the various CFG-based stuff over to using ASTConsumer interface,
this eliminates their dependence on the preprocessor and eliminates some duplicated code. llvm-svn: 41993
This commit is contained in:
parent
09c39db0c4
commit
254987c411
|
@ -17,7 +17,6 @@
|
|||
#include "clang/Analysis/LiveVariables.h"
|
||||
#include "clang/AST/CFG.h"
|
||||
#include "clang/Basic/Diagnostic.h"
|
||||
#include "clang/Lex/Preprocessor.h"
|
||||
#include "clang/AST/ASTContext.h"
|
||||
|
||||
using namespace clang;
|
||||
|
@ -25,12 +24,11 @@ using namespace clang;
|
|||
namespace {
|
||||
|
||||
class DeadStoreObserver : public LiveVariablesObserver {
|
||||
Preprocessor& PP;
|
||||
ASTContext Ctx;
|
||||
ASTContext &Ctx;
|
||||
Diagnostic &Diags;
|
||||
public:
|
||||
DeadStoreObserver(Preprocessor& pp) :
|
||||
PP(pp), Ctx(PP.getSourceManager(), PP.getTargetInfo(),
|
||||
PP.getIdentifierTable()) {
|
||||
DeadStoreObserver(ASTContext &ctx, Diagnostic &diags)
|
||||
: Ctx(ctx), Diags(diags) {
|
||||
}
|
||||
|
||||
virtual ~DeadStoreObserver() {}
|
||||
|
@ -46,9 +44,8 @@ public:
|
|||
// Is the variable live?
|
||||
if (!L.isLive(Live,cast<VarDecl>(DR->getDecl()))) {
|
||||
SourceRange R = B->getRHS()->getSourceRange();
|
||||
PP.getDiagnostics().Report(DR->getSourceRange().Begin(),
|
||||
diag::warn_dead_store, 0, 0,
|
||||
&R,1);
|
||||
Diags.Report(DR->getSourceRange().Begin(), diag::warn_dead_store,
|
||||
0, 0, &R, 1);
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -70,9 +67,8 @@ public:
|
|||
L.getVarInfo(V).Kills.size() == 0) {
|
||||
// Flag a warning.
|
||||
SourceRange R = E->getSourceRange();
|
||||
PP.getDiagnostics().Report(V->getLocation(),
|
||||
diag::warn_dead_store, 0, 0,
|
||||
&R,1);
|
||||
Diags.Report(V->getLocation(), diag::warn_dead_store, 0, 0,
|
||||
&R,1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -82,17 +78,18 @@ public:
|
|||
|
||||
namespace clang {
|
||||
|
||||
void CheckDeadStores(CFG& cfg, LiveVariables& L, Preprocessor& PP) {
|
||||
DeadStoreObserver A(PP);
|
||||
void CheckDeadStores(CFG& cfg, LiveVariables& L,
|
||||
ASTContext &Ctx, Diagnostic &Diags) {
|
||||
DeadStoreObserver A(Ctx, Diags);
|
||||
|
||||
for (CFG::iterator I = cfg.begin(), E = cfg.end(); I != E; ++I)
|
||||
L.runOnBlock(&(*I),&A);
|
||||
}
|
||||
|
||||
void CheckDeadStores(CFG& cfg, Preprocessor& PP) {
|
||||
void CheckDeadStores(CFG& cfg, ASTContext &Ctx, Diagnostic &Diags) {
|
||||
LiveVariables L;
|
||||
L.runOnCFG(cfg);
|
||||
CheckDeadStores(cfg,L,PP);
|
||||
CheckDeadStores(cfg,L, Ctx, Diags);
|
||||
}
|
||||
|
||||
} // end namespace clang
|
||||
|
|
|
@ -17,8 +17,6 @@
|
|||
#include "clang/AST/CFG.h"
|
||||
#include "clang/Analysis/LiveVariables.h"
|
||||
#include "clang/Analysis/LocalCheckers.h"
|
||||
#include "clang/Lex/Preprocessor.h"
|
||||
#include "clang/Sema/ASTStreamer.h"
|
||||
using namespace clang;
|
||||
|
||||
|
||||
|
@ -139,48 +137,32 @@ ASTConsumer *clang::CreateASTDumper() { return new ASTDumper(); }
|
|||
|
||||
namespace {
|
||||
|
||||
class CFGVisitor {
|
||||
class CFGVisitor : public ASTConsumer {
|
||||
public:
|
||||
virtual ~CFGVisitor() {}
|
||||
// CFG Visitor interface to be implemented by subclass.
|
||||
virtual void VisitCFG(CFG& C) = 0;
|
||||
virtual bool printFuncDeclStart() { return true; }
|
||||
|
||||
virtual void HandleTopLevelDecl(Decl *D);
|
||||
};
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
static void VisitCFGs(CFGVisitor& Visitor, Preprocessor& PP,
|
||||
unsigned MainFileID, bool Stats) {
|
||||
|
||||
bool printFDecl = Visitor.printFuncDeclStart();
|
||||
ASTContext Context(PP.getSourceManager(), PP.getTargetInfo(),
|
||||
PP.getIdentifierTable());
|
||||
ASTStreamerTy *Streamer = ASTStreamer_Init(PP, Context, MainFileID);
|
||||
|
||||
while (Decl *D = ASTStreamer_ReadTopLevelDecl(Streamer)) {
|
||||
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
|
||||
if (FD->getBody()) {
|
||||
|
||||
if (printFDecl) {
|
||||
PrintFunctionDeclStart(FD);
|
||||
fprintf(stderr,"\n");
|
||||
}
|
||||
|
||||
if (CFG* C = CFG::buildCFG(FD->getBody())) {
|
||||
Visitor.VisitCFG(*C);
|
||||
delete C;
|
||||
}
|
||||
else
|
||||
fprintf(stderr," Error processing CFG.\n");
|
||||
}
|
||||
void CFGVisitor::HandleTopLevelDecl(Decl *D) {
|
||||
FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
|
||||
if (!FD || !FD->getBody())
|
||||
return;
|
||||
|
||||
if (printFuncDeclStart()) {
|
||||
PrintFunctionDeclStart(FD);
|
||||
fprintf(stderr,"\n");
|
||||
}
|
||||
|
||||
if (Stats) {
|
||||
fprintf(stderr, "\nSTATISTICS:\n");
|
||||
ASTStreamer_PrintStats(Streamer);
|
||||
Context.PrintStats();
|
||||
}
|
||||
|
||||
ASTStreamer_Terminate(Streamer);
|
||||
|
||||
if (CFG *C = CFG::buildCFG(FD->getBody())) {
|
||||
VisitCFG(*C);
|
||||
delete C;
|
||||
} else
|
||||
fprintf(stderr, " Error processing CFG.\n");
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -192,17 +174,17 @@ namespace {
|
|||
public:
|
||||
CFGDumper(bool use_graphviz) : UseGraphviz(use_graphviz) {}
|
||||
|
||||
virtual void VisitCFG(CFG& C) {
|
||||
if (UseGraphviz) C.viewCFG();
|
||||
else C.dump();
|
||||
}
|
||||
virtual void VisitCFG(CFG &C) {
|
||||
if (UseGraphviz)
|
||||
C.viewCFG();
|
||||
else
|
||||
C.dump();
|
||||
}
|
||||
};
|
||||
} // end anonymous namespace
|
||||
|
||||
void clang::DumpCFGs(Preprocessor &PP, unsigned MainFileID,
|
||||
bool Stats, bool use_graphviz) {
|
||||
CFGDumper Visitor(use_graphviz);
|
||||
VisitCFGs(Visitor,PP,MainFileID,Stats);
|
||||
ASTConsumer *clang::CreateCFGDumper(bool ViewGraphs) {
|
||||
return new CFGDumper(ViewGraphs);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -210,22 +192,23 @@ void clang::DumpCFGs(Preprocessor &PP, unsigned MainFileID,
|
|||
|
||||
namespace {
|
||||
class LivenessVisitor : public CFGVisitor {
|
||||
Preprocessor& PP;
|
||||
SourceManager *SM;
|
||||
public:
|
||||
LivenessVisitor(Preprocessor& pp) : PP(pp) {}
|
||||
|
||||
virtual void Initialize(ASTContext &Context, unsigned MainFileID) {
|
||||
SM = &Context.SourceMgr;
|
||||
}
|
||||
|
||||
virtual void VisitCFG(CFG& C) {
|
||||
LiveVariables L;
|
||||
L.runOnCFG(C);
|
||||
L.dumpBlockLiveness(PP.getSourceManager());
|
||||
L.dumpVarLiveness(PP.getSourceManager());
|
||||
L.dumpBlockLiveness(*SM);
|
||||
L.dumpVarLiveness(*SM);
|
||||
}
|
||||
};
|
||||
} // end anonymous namespace
|
||||
|
||||
void clang::AnalyzeLiveVariables(Preprocessor &PP, unsigned MainFileID) {
|
||||
LivenessVisitor Visitor(PP);
|
||||
VisitCFGs(Visitor,PP,MainFileID,false);
|
||||
ASTConsumer *clang::CreateLiveVarAnalyzer() {
|
||||
return new LivenessVisitor();
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -233,15 +216,19 @@ void clang::AnalyzeLiveVariables(Preprocessor &PP, unsigned MainFileID) {
|
|||
|
||||
namespace {
|
||||
class DeadStoreVisitor : public CFGVisitor {
|
||||
Preprocessor& PP;
|
||||
Diagnostic &Diags;
|
||||
ASTContext *Ctx;
|
||||
public:
|
||||
DeadStoreVisitor(Preprocessor& pp) : PP(pp) {}
|
||||
virtual void VisitCFG(CFG& C) { CheckDeadStores(C,PP); }
|
||||
DeadStoreVisitor(Diagnostic &diags) : Diags(diags) {}
|
||||
virtual void Initialize(ASTContext &Context, unsigned MainFileID) {
|
||||
Ctx = &Context;
|
||||
}
|
||||
|
||||
virtual void VisitCFG(CFG& C) { CheckDeadStores(C, *Ctx, Diags); }
|
||||
virtual bool printFuncDeclStart() { return false; }
|
||||
};
|
||||
} // end anonymous namespace
|
||||
|
||||
void clang::RunDeadStoresCheck(Preprocessor &PP,unsigned MainFileID,bool Stats){
|
||||
DeadStoreVisitor Visitor(PP);
|
||||
VisitCFGs(Visitor,PP,MainFileID,Stats);
|
||||
ASTConsumer *clang::CreateDeadStoreChecker(Diagnostic &Diags) {
|
||||
return new DeadStoreVisitor(Diags);
|
||||
}
|
||||
|
|
|
@ -16,20 +16,14 @@
|
|||
|
||||
namespace clang {
|
||||
|
||||
class Preprocessor;
|
||||
class FunctionDecl;
|
||||
class TypedefDecl;
|
||||
class ASTConsumer;
|
||||
class Diagnostic;
|
||||
|
||||
ASTConsumer *CreateASTPrinter();
|
||||
ASTConsumer *CreateASTDumper();
|
||||
|
||||
void DumpCFGs(Preprocessor &PP, unsigned MainFileID,
|
||||
bool Stats, bool use_graphviz = false);
|
||||
|
||||
void AnalyzeLiveVariables(Preprocessor &PP, unsigned MainFileID);
|
||||
|
||||
void RunDeadStoresCheck(Preprocessor &PP, unsigned MainFileID, bool Stats);
|
||||
ASTConsumer *CreateCFGDumper(bool ViewGraphs = false);
|
||||
ASTConsumer *CreateLiveVarAnalyzer();
|
||||
ASTConsumer *CreateDeadStoreChecker(Diagnostic &Diags);
|
||||
|
||||
} // end clang namespace
|
||||
|
||||
|
|
|
@ -855,17 +855,21 @@ static void ProcessInputFile(Preprocessor &PP, unsigned MainFileID,
|
|||
break;
|
||||
}
|
||||
case ParseCFGDump:
|
||||
DumpCFGs(PP, MainFileID, Stats);
|
||||
case ParseCFGView: {
|
||||
std::auto_ptr<ASTConsumer> C(CreateCFGDumper(ProgAction == ParseCFGView));
|
||||
ParseAST(PP, MainFileID, *C.get(), Stats);
|
||||
break;
|
||||
case ParseCFGView:
|
||||
DumpCFGs(PP, MainFileID, Stats, true);
|
||||
}
|
||||
case AnalysisLiveVariables: {
|
||||
std::auto_ptr<ASTConsumer> C(CreateLiveVarAnalyzer());
|
||||
ParseAST(PP, MainFileID, *C.get(), Stats);
|
||||
break;
|
||||
case AnalysisLiveVariables:
|
||||
AnalyzeLiveVariables(PP, MainFileID);
|
||||
break;
|
||||
case WarnDeadStores:
|
||||
RunDeadStoresCheck(PP, MainFileID, Stats);
|
||||
}
|
||||
case WarnDeadStores: {
|
||||
std::auto_ptr<ASTConsumer> C(CreateDeadStoreChecker(PP.getDiagnostics()));
|
||||
ParseAST(PP, MainFileID, *C.get(), Stats);
|
||||
break;
|
||||
}
|
||||
case EmitLLVM:
|
||||
EmitLLVMFromASTs(PP, MainFileID, Stats);
|
||||
break;
|
||||
|
|
|
@ -17,12 +17,13 @@
|
|||
|
||||
namespace clang {
|
||||
|
||||
class Preprocessor;
|
||||
class CFG;
|
||||
class LiveVariables;
|
||||
class Diagnostic;
|
||||
|
||||
void CheckDeadStores(CFG& cfg, LiveVariables& L, Preprocessor& PP);
|
||||
void CheckDeadStores(CFG& cfg, Preprocessor& PP);
|
||||
void CheckDeadStores(CFG& cfg, LiveVariables& L,
|
||||
ASTContext &Ctx, Diagnostic &Diags);
|
||||
void CheckDeadStores(CFG& cfg, ASTContext &Ctx, Diagnostic &Diags);
|
||||
|
||||
} // end namespace clang
|
||||
|
||||
|
|
Loading…
Reference in New Issue