From: Argyrios Kyrtzidis Date: Wed, 23 Feb 2011 07:19:23 +0000 (+0000) Subject: [analyzer] Migrate UnreachableCodeChecker to CheckerV2. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=30726c6baee1417307236e854f1474fdb3cedb98;p=clang [analyzer] Migrate UnreachableCodeChecker to CheckerV2. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@126308 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/StaticAnalyzer/Core/CheckerManager.h b/include/clang/StaticAnalyzer/Core/CheckerManager.h index d41bbefe79..c8d8c6681a 100644 --- a/include/clang/StaticAnalyzer/Core/CheckerManager.h +++ b/include/clang/StaticAnalyzer/Core/CheckerManager.h @@ -32,6 +32,7 @@ namespace ento { class ObjCMessage; class SVal; class ExplodedNodeSet; + class ExplodedGraph; class GRState; struct VoidCheckerFnParm {}; @@ -172,6 +173,10 @@ public: const GRState *state, ExprEngine &Eng); + /// \brief Run checkers for end of analysis. + void runCheckersForEndAnalysis(ExplodedGraph &G, BugReporter &BR, + ExprEngine &Eng); + // FIXME: Temporary until checker running is moved completely into // CheckerManager. void registerCheckersToEngine(ExprEngine &eng); @@ -199,6 +204,8 @@ public: typedef CheckerFn CheckObjCMessageFunc; typedef CheckerFn CheckLocationFunc; + typedef CheckerFn + CheckEndAnalysisFunc; typedef bool (*HandlesStmtFunc)(const Stmt *D); void _registerForPreStmt(CheckStmtFunc checkfn, @@ -211,6 +218,8 @@ public: void _registerForLocation(CheckLocationFunc checkfn); + void _registerForEndAnalysis(CheckEndAnalysisFunc checkfn); + //===----------------------------------------------------------------------===// // Implementation details. //===----------------------------------------------------------------------===// @@ -276,6 +285,8 @@ private: std::vector PostObjCMessageCheckers; std::vector LocationCheckers; + + std::vector EndAnalysisCheckers; }; } // end ento namespace diff --git a/include/clang/StaticAnalyzer/Core/CheckerV2.h b/include/clang/StaticAnalyzer/Core/CheckerV2.h index 1f5b19ca80..45c5b73fcc 100644 --- a/include/clang/StaticAnalyzer/Core/CheckerV2.h +++ b/include/clang/StaticAnalyzer/Core/CheckerV2.h @@ -145,6 +145,21 @@ public: } }; +class EndAnalysis { + template + static void _checkEndAnalysis(void *checker, ExplodedGraph &G, + BugReporter &BR, ExprEngine &Eng) { + ((const CHECKER *)checker)->checkEndAnalysis(G, BR, Eng); + } + +public: + template + static void _register(CHECKER *checker, CheckerManager &mgr) { + mgr._registerForEndAnalysis( + CheckerManager::CheckEndAnalysisFunc(checker, _checkEndAnalysis)); + } +}; + } // end check namespace template second->VisitEndAnalysis(G, BR, *this); } + getCheckerManager().runCheckersForEndAnalysis(G, BR, *this); } void ExprEngine::processCFGElement(const CFGElement E, diff --git a/lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp b/lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp index 3038e29c0e..1bc487a49c 100644 --- a/lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp @@ -14,15 +14,16 @@ //===----------------------------------------------------------------------===// #include "ClangSACheckers.h" -#include "clang/AST/ParentMap.h" -#include "clang/Basic/Builtins.h" -#include "clang/Basic/SourceManager.h" +#include "clang/StaticAnalyzer/Core/CheckerV2.h" #include "clang/StaticAnalyzer/Core/CheckerManager.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" +#include "clang/AST/ParentMap.h" +#include "clang/Basic/Builtins.h" +#include "clang/Basic/SourceManager.h" #include "llvm/ADT/SmallPtrSet.h" // The number of CFGBlock pointers we want to reserve memory for. This is used @@ -33,40 +34,27 @@ using namespace clang; using namespace ento; namespace { -class UnreachableCodeChecker : public Checker { +class UnreachableCodeChecker : public CheckerV2 { public: - static void *getTag(); - void VisitEndAnalysis(ExplodedGraph &G, - BugReporter &B, - ExprEngine &Eng); + void checkEndAnalysis(ExplodedGraph &G, BugReporter &B, + ExprEngine &Eng) const; private: + typedef llvm::SmallSet CFGBlocksSet; + static inline const Stmt *getUnreachableStmt(const CFGBlock *CB); - void FindUnreachableEntryPoints(const CFGBlock *CB); + static void FindUnreachableEntryPoints(const CFGBlock *CB, + CFGBlocksSet &reachable, + CFGBlocksSet &visited); static bool isInvalidPath(const CFGBlock *CB, const ParentMap &PM); static inline bool isEmptyCFGBlock(const CFGBlock *CB); - - llvm::SmallSet reachable; - llvm::SmallSet visited; }; } -void *UnreachableCodeChecker::getTag() { - static int x = 0; - return &x; -} - -static void RegisterUnreachableCodeChecker(ExprEngine &Eng) { - Eng.registerCheck(new UnreachableCodeChecker()); -} - -void ento::registerUnreachableCodeChecker(CheckerManager &mgr) { - mgr.addCheckerRegisterFunction(RegisterUnreachableCodeChecker); -} - -void UnreachableCodeChecker::VisitEndAnalysis(ExplodedGraph &G, +void UnreachableCodeChecker::checkEndAnalysis(ExplodedGraph &G, BugReporter &B, - ExprEngine &Eng) { - // Bail out if we didn't cover all paths + ExprEngine &Eng) const { + CFGBlocksSet reachable, visited; + if (Eng.hasWorkRemaining()) return; @@ -109,7 +97,7 @@ void UnreachableCodeChecker::VisitEndAnalysis(ExplodedGraph &G, // Find the entry points for this block if (!visited.count(CB->getBlockID())) - FindUnreachableEntryPoints(CB); + FindUnreachableEntryPoints(CB, reachable, visited); // This block may have been pruned; check if we still want to report it if (reachable.count(CB->getBlockID())) @@ -155,7 +143,9 @@ void UnreachableCodeChecker::VisitEndAnalysis(ExplodedGraph &G, } // Recursively finds the entry point(s) for this dead CFGBlock. -void UnreachableCodeChecker::FindUnreachableEntryPoints(const CFGBlock *CB) { +void UnreachableCodeChecker::FindUnreachableEntryPoints(const CFGBlock *CB, + CFGBlocksSet &reachable, + CFGBlocksSet &visited) { visited.insert(CB->getBlockID()); for (CFGBlock::const_pred_iterator I = CB->pred_begin(), E = CB->pred_end(); @@ -166,7 +156,7 @@ void UnreachableCodeChecker::FindUnreachableEntryPoints(const CFGBlock *CB) { reachable.insert(CB->getBlockID()); if (!visited.count((*I)->getBlockID())) // If we haven't previously visited the unreachable predecessor, recurse - FindUnreachableEntryPoints(*I); + FindUnreachableEntryPoints(*I, reachable, visited); } } } @@ -226,3 +216,7 @@ bool UnreachableCodeChecker::isEmptyCFGBlock(const CFGBlock *CB) { && CB->size() == 0 // No statements && CB->getTerminator() == 0; // No terminator } + +void ento::registerUnreachableCodeChecker(CheckerManager &mgr) { + mgr.registerChecker(); +} diff --git a/lib/StaticAnalyzer/Core/CheckerManager.cpp b/lib/StaticAnalyzer/Core/CheckerManager.cpp index cb7c0ecdb4..0ff29757a6 100644 --- a/lib/StaticAnalyzer/Core/CheckerManager.cpp +++ b/lib/StaticAnalyzer/Core/CheckerManager.cpp @@ -200,6 +200,13 @@ void CheckerManager::runCheckersForLocation(ExplodedNodeSet &Dst, runPathSensitiveCheckers(C, Dst, Src); } +void CheckerManager::runCheckersForEndAnalysis(ExplodedGraph &G, + BugReporter &BR, + ExprEngine &Eng) { + for (unsigned i = 0, e = EndAnalysisCheckers.size(); i != e; ++i) + EndAnalysisCheckers[i](G, BR, Eng); +} + void CheckerManager::registerCheckersToEngine(ExprEngine &eng) { for (unsigned i = 0, e = Funcs.size(); i != e; ++i) Funcs[i](eng); @@ -245,6 +252,10 @@ void CheckerManager::_registerForLocation(CheckLocationFunc checkfn) { LocationCheckers.push_back(checkfn); } +void CheckerManager::_registerForEndAnalysis(CheckEndAnalysisFunc checkfn) { + EndAnalysisCheckers.push_back(checkfn); +} + //===----------------------------------------------------------------------===// // Implementation details. //===----------------------------------------------------------------------===//