From 254987c411774589abc90c83066c3104fe76d20e Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Sat, 15 Sep 2007 23:21:08 +0000 Subject: [PATCH] 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 --- clang/Analysis/DeadStores.cpp | 29 +++--- clang/Driver/ASTStreamers.cpp | 103 ++++++++----------- clang/Driver/ASTStreamers.h | 14 +-- clang/Driver/clang.cpp | 20 ++-- clang/include/clang/Analysis/LocalCheckers.h | 7 +- 5 files changed, 78 insertions(+), 95 deletions(-) diff --git a/clang/Analysis/DeadStores.cpp b/clang/Analysis/DeadStores.cpp index e898f3ca5715..8e2e3628e076 100644 --- a/clang/Analysis/DeadStores.cpp +++ b/clang/Analysis/DeadStores.cpp @@ -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(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 diff --git a/clang/Driver/ASTStreamers.cpp b/clang/Driver/ASTStreamers.cpp index 72524f16bc76..3c67d9524a84 100644 --- a/clang/Driver/ASTStreamers.cpp +++ b/clang/Driver/ASTStreamers.cpp @@ -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(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(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); } diff --git a/clang/Driver/ASTStreamers.h b/clang/Driver/ASTStreamers.h index 09f1423e6591..60b23ef70d33 100644 --- a/clang/Driver/ASTStreamers.h +++ b/clang/Driver/ASTStreamers.h @@ -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 diff --git a/clang/Driver/clang.cpp b/clang/Driver/clang.cpp index 7c25a0a9b08f..7301354c176d 100644 --- a/clang/Driver/clang.cpp +++ b/clang/Driver/clang.cpp @@ -855,17 +855,21 @@ static void ProcessInputFile(Preprocessor &PP, unsigned MainFileID, break; } case ParseCFGDump: - DumpCFGs(PP, MainFileID, Stats); + case ParseCFGView: { + std::auto_ptr C(CreateCFGDumper(ProgAction == ParseCFGView)); + ParseAST(PP, MainFileID, *C.get(), Stats); break; - case ParseCFGView: - DumpCFGs(PP, MainFileID, Stats, true); + } + case AnalysisLiveVariables: { + std::auto_ptr 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 C(CreateDeadStoreChecker(PP.getDiagnostics())); + ParseAST(PP, MainFileID, *C.get(), Stats); break; + } case EmitLLVM: EmitLLVMFromASTs(PP, MainFileID, Stats); break; diff --git a/clang/include/clang/Analysis/LocalCheckers.h b/clang/include/clang/Analysis/LocalCheckers.h index 346945d6e870..19825fe228ec 100644 --- a/clang/include/clang/Analysis/LocalCheckers.h +++ b/clang/include/clang/Analysis/LocalCheckers.h @@ -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