From: Ted Kremenek Date: Fri, 7 Sep 2007 23:47:56 +0000 (+0000) Subject: Refactored driver options that perform analyses/work over CFGs to use X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=74bf2c9a4c749e9facba90b3a3ab3f369efa7682;p=clang Refactored driver options that perform analyses/work over CFGs to use "CFGVisitor", which now handles all the boilerplate for iterating over the function definitions in a translation unit and building the CFGs. This logic was previously replicated for each driver option that used CFGs. The options -dump-cfg, -view-cfg, -check-dead-stores, and -dump-live-variables now use this refactored code. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@41779 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/Driver/ASTStreamers.cpp b/Driver/ASTStreamers.cpp index 95d39fa352..d6db959d47 100644 --- a/Driver/ASTStreamers.cpp +++ b/Driver/ASTStreamers.cpp @@ -157,24 +157,44 @@ void clang::DumpASTs(Preprocessor &PP, unsigned MainFileID, bool Stats) { ASTStreamer_Terminate(Streamer); } -void clang::DumpCFGs(Preprocessor &PP, unsigned MainFileID, - bool Stats, bool use_graphviz) -{ +//===----------------------------------------------------------------------===// +// CFGVisitor & VisitCFGs - Boilerplate interface and logic to visit +// the CFGs for all function definitions. + +namespace { + +class CFGVisitor { +public: + virtual ~CFGVisitor() {} + virtual void VisitCFG(CFG& C) = 0; + virtual bool printFuncDeclStart() { return true; } +}; + +} // end anonymous namespace + +static void VisitCFGs(CFGVisitor& Visitor, Preprocessor& PP, + unsigned MainFileID, bool Stats) { + + bool printFDecl = Visitor.printFuncDeclStart(); ASTContext Context(PP.getTargetInfo(), PP.getIdentifierTable()); ASTStreamerTy *Streamer = ASTStreamer_Init(PP, Context, MainFileID); while (Decl *D = ASTStreamer_ReadTopLevelDecl(Streamer)) { - if (FunctionDecl *FD = dyn_cast(D)) { + if (FunctionDecl *FD = dyn_cast(D)) if (FD->getBody()) { - PrintFunctionDeclStart(FD); - fprintf(stderr,"\n"); + + if (printFDecl) { + PrintFunctionDeclStart(FD); + fprintf(stderr,"\n"); + } + if (CFG* C = CFG::buildCFG(FD->getBody())) { - if (use_graphviz) C->viewCFG(); else C->dump(); + Visitor.VisitCFG(*C); + delete C; } else - fprintf(stderr," Error processing CFG.\n"); + fprintf(stderr," Error processing CFG.\n"); } - } } if (Stats) { @@ -186,54 +206,63 @@ void clang::DumpCFGs(Preprocessor &PP, unsigned MainFileID, ASTStreamer_Terminate(Streamer); } -void clang::AnalyzeLiveVariables(Preprocessor &PP, unsigned MainFileID) -{ - ASTContext Context(PP.getTargetInfo(), PP.getIdentifierTable()); - ASTStreamerTy *Streamer = ASTStreamer_Init(PP, Context, MainFileID); +//===----------------------------------------------------------------------===// +// DumpCFGs - Dump CFGs to stderr or visualize with Graphviz + +namespace { + class CFGDumper : public CFGVisitor { + const bool UseGraphviz; + public: + CFGDumper(bool use_graphviz) : UseGraphviz(use_graphviz) {} + + virtual void VisitCFG(CFG& C) { + if (UseGraphviz) C.viewCFG(); + else C.dump(); + } + }; +} // end anonymous namespace - while (Decl *D = ASTStreamer_ReadTopLevelDecl(Streamer)) { - if (FunctionDecl *FD = dyn_cast(D)) { - if (FD->getBody()) { - PrintFunctionDeclStart(FD); - fprintf(stderr,"\n"); - if (CFG* C = CFG::buildCFG(FD->getBody())) { - LiveVariables L; - L.runOnCFG(*C); - L.dumpBlockLiveness(PP.getSourceManager()); - } - else - fprintf(stderr," Error processing CFG.\n"); - } - } - } - - ASTStreamer_Terminate(Streamer); +void clang::DumpCFGs(Preprocessor &PP, unsigned MainFileID, + bool Stats, bool use_graphviz) { + CFGDumper Visitor(use_graphviz); + VisitCFGs(Visitor,PP,MainFileID,Stats); } -void clang::RunDeadStoresCheck(Preprocessor &PP, unsigned MainFileID,bool Stats) -{ - ASTContext Context(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 (CFG* C = CFG::buildCFG(FD->getBody())) { - clang::CheckDeadStores(*C,PP); - } - else - fprintf(stderr," Error processing CFG.\n"); - } +//===----------------------------------------------------------------------===// +// AnalyzeLiveVariables - perform live variable analysis and dump results + +namespace { + class LivenessVisitor : public CFGVisitor { + Preprocessor& PP; + public: + LivenessVisitor(Preprocessor& pp) : PP(pp) {} + + virtual void VisitCFG(CFG& C) { + LiveVariables L; + L.runOnCFG(C); + L.dumpBlockLiveness(PP.getSourceManager()); } - } - - if (Stats) { - fprintf(stderr, "\nSTATISTICS:\n"); - ASTStreamer_PrintStats(Streamer); - Context.PrintStats(); - } + }; +} // end anonymous namespace - ASTStreamer_Terminate(Streamer); +void clang::AnalyzeLiveVariables(Preprocessor &PP, unsigned MainFileID) { + LivenessVisitor Visitor(PP); + VisitCFGs(Visitor,PP,MainFileID,false); } +//===----------------------------------------------------------------------===// +// RunDeadStores - run checker to locate dead stores in a function + +namespace { + class DeadStoreVisitor : public CFGVisitor { + Preprocessor& PP; + public: + DeadStoreVisitor(Preprocessor& pp) : PP(pp) {} + virtual void VisitCFG(CFG& C) { CheckDeadStores(C,PP); } + }; +} // end anonymous namespace +void clang::RunDeadStoresCheck(Preprocessor &PP,unsigned MainFileID,bool Stats){ + DeadStoreVisitor Visitor(PP); + VisitCFGs(Visitor,PP,MainFileID,Stats); +}