diff options
author | Jordan Rose <jordan_rose@apple.com> | 2012-07-02 19:28:16 +0000 |
---|---|---|
committer | Jordan Rose <jordan_rose@apple.com> | 2012-07-02 19:28:16 +0000 |
commit | 96479da6ad9d921d875e7be29fe1bfa127be8069 (patch) | |
tree | 2ed3115bd58612c84b2ac3c98821743cd09996c8 /lib/StaticAnalyzer/Core/CheckerManager.cpp | |
parent | 362a31cacc19764f3630928a9e4779af2576e074 (diff) |
[analyzer] Add generic preCall and postCall checks.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@159562 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/StaticAnalyzer/Core/CheckerManager.cpp')
-rw-r--r-- | lib/StaticAnalyzer/Core/CheckerManager.cpp | 57 |
1 files changed, 57 insertions, 0 deletions
diff --git a/lib/StaticAnalyzer/Core/CheckerManager.cpp b/lib/StaticAnalyzer/Core/CheckerManager.cpp index e4209e50b3..39a3621826 100644 --- a/lib/StaticAnalyzer/Core/CheckerManager.cpp +++ b/lib/StaticAnalyzer/Core/CheckerManager.cpp @@ -25,6 +25,8 @@ bool CheckerManager::hasPathSensitiveCheckers() const { return !StmtCheckers.empty() || !PreObjCMessageCheckers.empty() || !PostObjCMessageCheckers.empty() || + !PreCallCheckers.empty() || + !PostCallCheckers.empty() || !LocationCheckers.empty() || !BindCheckers.empty() || !EndAnalysisCheckers.empty() || @@ -217,6 +219,54 @@ void CheckerManager::runCheckersForObjCMessage(bool isPreVisit, } namespace { + // FIXME: This has all the same signatures as CheckObjCMessageContext. + // Is there a way we can merge the two? + struct CheckCallContext { + typedef std::vector<CheckerManager::CheckCallFunc> CheckersTy; + bool IsPreVisit; + const CheckersTy &Checkers; + const CallEvent &Call; + ExprEngine &Eng; + + CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); } + CheckersTy::const_iterator checkers_end() { return Checkers.end(); } + + CheckCallContext(bool isPreVisit, const CheckersTy &checkers, + const CallEvent &call, ExprEngine &eng) + : IsPreVisit(isPreVisit), Checkers(checkers), Call(call), Eng(eng) { } + + void runChecker(CheckerManager::CheckCallFunc checkFn, + NodeBuilder &Bldr, ExplodedNode *Pred) { + // FIXME: This will be wrong as soon as we handle any calls without + // associated statements. + ProgramPoint::Kind K = IsPreVisit ? ProgramPoint::PreStmtKind + : ProgramPoint::PostStmtKind; + assert(Call.getOriginExpr() && "Calls without stmts not yet handled"); + const ProgramPoint &L = + ProgramPoint::getProgramPoint(Call.getOriginExpr(), + K, Pred->getLocationContext(), + checkFn.Checker); + CheckerContext C(Bldr, Eng, Pred, L); + + checkFn(Call, C); + } + }; +} + +/// \brief Run checkers for visiting an abstract call event. +void CheckerManager::runCheckersForCallEvent(bool isPreVisit, + ExplodedNodeSet &Dst, + const ExplodedNodeSet &Src, + const CallEvent &Call, + ExprEngine &Eng) { + CheckCallContext C(isPreVisit, + isPreVisit ? PreCallCheckers + : PostCallCheckers, + Call, Eng); + expandGraphWithCheckers(C, Dst, Src); +} + +namespace { struct CheckLocationContext { typedef std::vector<CheckerManager::CheckLocationFunc> CheckersTy; const CheckersTy &Checkers; @@ -584,6 +634,13 @@ void CheckerManager::_registerForPostObjCMessage(CheckObjCMessageFunc checkfn) { PostObjCMessageCheckers.push_back(checkfn); } +void CheckerManager::_registerForPreCall(CheckCallFunc checkfn) { + PreCallCheckers.push_back(checkfn); +} +void CheckerManager::_registerForPostCall(CheckCallFunc checkfn) { + PostCallCheckers.push_back(checkfn); +} + void CheckerManager::_registerForLocation(CheckLocationFunc checkfn) { LocationCheckers.push_back(checkfn); } |