summaryrefslogtreecommitdiffstats
path: root/lib/StaticAnalyzer/Core/CheckerManager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/StaticAnalyzer/Core/CheckerManager.cpp')
-rw-r--r--lib/StaticAnalyzer/Core/CheckerManager.cpp133
1 files changed, 88 insertions, 45 deletions
diff --git a/lib/StaticAnalyzer/Core/CheckerManager.cpp b/lib/StaticAnalyzer/Core/CheckerManager.cpp
index 0bcc343..c786655 100644
--- a/lib/StaticAnalyzer/Core/CheckerManager.cpp
+++ b/lib/StaticAnalyzer/Core/CheckerManager.cpp
@@ -14,7 +14,7 @@
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
#include "clang/Analysis/ProgramPoint.h"
#include "clang/AST/DeclBase.h"
@@ -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() ||
@@ -138,7 +140,7 @@ namespace {
const CheckersTy &Checkers;
const Stmt *S;
ExprEngine &Eng;
- bool wasInlined;
+ bool WasInlined;
CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
@@ -146,7 +148,7 @@ namespace {
CheckStmtContext(bool isPreVisit, const CheckersTy &checkers,
const Stmt *s, ExprEngine &eng, bool wasInlined = false)
: IsPreVisit(isPreVisit), Checkers(checkers), S(s), Eng(eng),
- wasInlined(wasInlined) {}
+ WasInlined(wasInlined) {}
void runChecker(CheckerManager::CheckStmtFunc checkFn,
NodeBuilder &Bldr, ExplodedNode *Pred) {
@@ -155,7 +157,7 @@ namespace {
ProgramPoint::PostStmtKind;
const ProgramPoint &L = ProgramPoint::getProgramPoint(S, K,
Pred->getLocationContext(), checkFn.Checker);
- CheckerContext C(Bldr, Eng, Pred, L, wasInlined);
+ CheckerContext C(Bldr, Eng, Pred, L, WasInlined);
checkFn(S, C);
}
};
@@ -167,38 +169,35 @@ void CheckerManager::runCheckersForStmt(bool isPreVisit,
const ExplodedNodeSet &Src,
const Stmt *S,
ExprEngine &Eng,
- bool wasInlined) {
+ bool WasInlined) {
CheckStmtContext C(isPreVisit, *getCachedStmtCheckersFor(S, isPreVisit),
- S, Eng, wasInlined);
+ S, Eng, WasInlined);
expandGraphWithCheckers(C, Dst, Src);
}
namespace {
struct CheckObjCMessageContext {
typedef std::vector<CheckerManager::CheckObjCMessageFunc> CheckersTy;
- bool IsPreVisit;
+ bool IsPreVisit, WasInlined;
const CheckersTy &Checkers;
- const ObjCMessage &Msg;
+ const ObjCMethodCall &Msg;
ExprEngine &Eng;
CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
CheckObjCMessageContext(bool isPreVisit, const CheckersTy &checkers,
- const ObjCMessage &msg, ExprEngine &eng)
- : IsPreVisit(isPreVisit), Checkers(checkers), Msg(msg), Eng(eng) { }
+ const ObjCMethodCall &msg, ExprEngine &eng,
+ bool wasInlined)
+ : IsPreVisit(isPreVisit), WasInlined(wasInlined), Checkers(checkers),
+ Msg(msg), Eng(eng) { }
void runChecker(CheckerManager::CheckObjCMessageFunc checkFn,
NodeBuilder &Bldr, ExplodedNode *Pred) {
- ProgramPoint::Kind K = IsPreVisit ? ProgramPoint::PreStmtKind :
- ProgramPoint::PostStmtKind;
- const ProgramPoint &L =
- ProgramPoint::getProgramPoint(Msg.getMessageExpr(),
- K, Pred->getLocationContext(),
- checkFn.Checker);
- CheckerContext C(Bldr, Eng, Pred, L);
+ const ProgramPoint &L = Msg.getProgramPoint(IsPreVisit,checkFn.Checker);
+ CheckerContext C(Bldr, Eng, Pred, L, WasInlined);
- checkFn(Msg, C);
+ checkFn(*Msg.cloneWithState<ObjCMethodCall>(Pred->getState()), C);
}
};
}
@@ -207,12 +206,56 @@ namespace {
void CheckerManager::runCheckersForObjCMessage(bool isPreVisit,
ExplodedNodeSet &Dst,
const ExplodedNodeSet &Src,
- const ObjCMessage &msg,
- ExprEngine &Eng) {
+ const ObjCMethodCall &msg,
+ ExprEngine &Eng,
+ bool WasInlined) {
CheckObjCMessageContext C(isPreVisit,
isPreVisit ? PreObjCMessageCheckers
: PostObjCMessageCheckers,
- msg, Eng);
+ msg, Eng, WasInlined);
+ expandGraphWithCheckers(C, Dst, Src);
+}
+
+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, WasInlined;
+ 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,
+ bool wasInlined)
+ : IsPreVisit(isPreVisit), WasInlined(wasInlined), Checkers(checkers),
+ Call(call), Eng(eng) { }
+
+ void runChecker(CheckerManager::CheckCallFunc checkFn,
+ NodeBuilder &Bldr, ExplodedNode *Pred) {
+ const ProgramPoint &L = Call.getProgramPoint(IsPreVisit,checkFn.Checker);
+ CheckerContext C(Bldr, Eng, Pred, L, WasInlined);
+
+ checkFn(*Call.cloneWithState(Pred->getState()), 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,
+ bool WasInlined) {
+ CheckCallContext C(isPreVisit,
+ isPreVisit ? PreCallCheckers
+ : PostCallCheckers,
+ Call, Eng, WasInlined);
expandGraphWithCheckers(C, Dst, Src);
}
@@ -381,21 +424,25 @@ namespace {
SymbolReaper &SR;
const Stmt *S;
ExprEngine &Eng;
+ ProgramPoint::Kind ProgarmPointKind;
CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
CheckDeadSymbolsContext(const CheckersTy &checkers, SymbolReaper &sr,
- const Stmt *s, ExprEngine &eng)
- : Checkers(checkers), SR(sr), S(s), Eng(eng) { }
+ const Stmt *s, ExprEngine &eng,
+ ProgramPoint::Kind K)
+ : Checkers(checkers), SR(sr), S(s), Eng(eng), ProgarmPointKind(K) { }
void runChecker(CheckerManager::CheckDeadSymbolsFunc checkFn,
NodeBuilder &Bldr, ExplodedNode *Pred) {
- ProgramPoint::Kind K = ProgramPoint::PostPurgeDeadSymbolsKind;
- const ProgramPoint &L = ProgramPoint::getProgramPoint(S, K,
+ const ProgramPoint &L = ProgramPoint::getProgramPoint(S, ProgarmPointKind,
Pred->getLocationContext(), checkFn.Checker);
CheckerContext C(Bldr, Eng, Pred, L);
+ // Note, do not pass the statement to the checkers without letting them
+ // differentiate if we ran remove dead bindings before or after the
+ // statement.
checkFn(SR, C);
}
};
@@ -406,8 +453,9 @@ void CheckerManager::runCheckersForDeadSymbols(ExplodedNodeSet &Dst,
const ExplodedNodeSet &Src,
SymbolReaper &SymReaper,
const Stmt *S,
- ExprEngine &Eng) {
- CheckDeadSymbolsContext C(DeadSymbolsCheckers, SymReaper, S, Eng);
+ ExprEngine &Eng,
+ ProgramPoint::Kind K) {
+ CheckDeadSymbolsContext C(DeadSymbolsCheckers, SymReaper, S, Eng, K);
expandGraphWithCheckers(C, Dst, Src);
}
@@ -426,7 +474,7 @@ CheckerManager::runCheckersForRegionChanges(ProgramStateRef state,
const StoreManager::InvalidatedSymbols *invalidated,
ArrayRef<const MemRegion *> ExplicitRegions,
ArrayRef<const MemRegion *> Regions,
- const CallOrObjCMessage *Call) {
+ const CallEvent *Call) {
for (unsigned i = 0, e = RegionChangesCheckers.size(); i != e; ++i) {
// If any checker declares the state infeasible (or if it starts that way),
// bail out.
@@ -456,16 +504,9 @@ CheckerManager::runCheckersForEvalAssume(ProgramStateRef state,
/// Only one checker will evaluate the call.
void CheckerManager::runCheckersForEvalCall(ExplodedNodeSet &Dst,
const ExplodedNodeSet &Src,
- const CallExpr *CE,
- ExprEngine &Eng,
- GraphExpander *defaultEval) {
- if (EvalCallCheckers.empty() &&
- InlineCallCheckers.empty() &&
- defaultEval == 0) {
- Dst.insert(Src);
- return;
- }
-
+ const CallEvent &Call,
+ ExprEngine &Eng) {
+ const CallExpr *CE = cast<CallExpr>(Call.getOriginExpr());
for (ExplodedNodeSet::iterator
NI = Src.begin(), NE = Src.end(); NI != NE; ++NI) {
@@ -529,10 +570,8 @@ void CheckerManager::runCheckersForEvalCall(ExplodedNodeSet &Dst,
// If none of the checkers evaluated the call, ask ExprEngine to handle it.
if (!anyEvaluated) {
- if (defaultEval)
- defaultEval->expandGraph(Dst, Pred);
- else
- Dst.insert(Pred);
+ NodeBuilder B(Pred, Dst, Eng.getBuilderContext());
+ Eng.defaultEvalCall(B, Pred, Call);
}
}
}
@@ -590,6 +629,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);
}
@@ -673,6 +719,3 @@ CheckerManager::~CheckerManager() {
for (unsigned i = 0, e = CheckerDtors.size(); i != e; ++i)
CheckerDtors[i]();
}
-
-// Anchor for the vtable.
-GraphExpander::~GraphExpander() { }
OpenPOWER on IntegriCloud