summaryrefslogtreecommitdiffstats
path: root/clang/lib/StaticAnalyzer/Core
diff options
context:
space:
mode:
authorDevin Coughlin <dcoughlin@apple.com>2016-02-19 01:35:10 +0000
committerDevin Coughlin <dcoughlin@apple.com>2016-02-19 01:35:10 +0000
commit8d922aa746a1cdf951dc12f43b86139c68f23e57 (patch)
treeff80bda6a69d3002abbdfd870422c1f117b58d88 /clang/lib/StaticAnalyzer/Core
parentbde5ede5261062a838d57651ace09c35d3ebcdc8 (diff)
downloadbcm5719-llvm-8d922aa746a1cdf951dc12f43b86139c68f23e57.tar.gz
bcm5719-llvm-8d922aa746a1cdf951dc12f43b86139c68f23e57.zip
[analyzer] Add checker callback for beginning of function.
Add a checker callback that is called when the analyzer starts analyzing a function either at the top level or when inlined. This will be used by a follow-on patch making the DeallocChecker path sensitive. Differential Revision: http://reviews.llvm.org/D17418 llvm-svn: 261293
Diffstat (limited to 'clang/lib/StaticAnalyzer/Core')
-rw-r--r--clang/lib/StaticAnalyzer/Core/CheckerManager.cpp38
-rw-r--r--clang/lib/StaticAnalyzer/Core/CoreEngine.cpp24
-rw-r--r--clang/lib/StaticAnalyzer/Core/ExprEngine.cpp9
-rw-r--r--clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp17
4 files changed, 75 insertions, 13 deletions
diff --git a/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp b/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
index 008e8ef31cd..d8382e88691 100644
--- a/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
+++ b/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
@@ -377,6 +377,40 @@ void CheckerManager::runCheckersForEndAnalysis(ExplodedGraph &G,
EndAnalysisCheckers[i](G, BR, Eng);
}
+namespace {
+struct CheckBeginFunctionContext {
+ typedef std::vector<CheckerManager::CheckBeginFunctionFunc> CheckersTy;
+ const CheckersTy &Checkers;
+ ExprEngine &Eng;
+ const ProgramPoint &PP;
+
+ CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
+ CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
+
+ CheckBeginFunctionContext(const CheckersTy &Checkers, ExprEngine &Eng,
+ const ProgramPoint &PP)
+ : Checkers(Checkers), Eng(Eng), PP(PP) {}
+
+ void runChecker(CheckerManager::CheckBeginFunctionFunc checkFn,
+ NodeBuilder &Bldr, ExplodedNode *Pred) {
+ const ProgramPoint &L = PP.withTag(checkFn.Checker);
+ CheckerContext C(Bldr, Eng, Pred, L);
+
+ checkFn(C);
+ }
+};
+}
+
+void CheckerManager::runCheckersForBeginFunction(ExplodedNodeSet &Dst,
+ const BlockEdge &L,
+ ExplodedNode *Pred,
+ ExprEngine &Eng) {
+ ExplodedNodeSet Src;
+ Src.insert(Pred);
+ CheckBeginFunctionContext C(BeginFunctionCheckers, Eng, L);
+ expandGraphWithCheckers(C, Dst, Src);
+}
+
/// \brief Run checkers for end of path.
// Note, We do not chain the checker output (like in expandGraphWithCheckers)
// for this callback since end of path nodes are expected to be final.
@@ -671,6 +705,10 @@ void CheckerManager::_registerForEndAnalysis(CheckEndAnalysisFunc checkfn) {
EndAnalysisCheckers.push_back(checkfn);
}
+void CheckerManager::_registerForBeginFunction(CheckBeginFunctionFunc checkfn) {
+ BeginFunctionCheckers.push_back(checkfn);
+}
+
void CheckerManager::_registerForEndFunction(CheckEndFunctionFunc checkfn) {
EndFunctionCheckers.push_back(checkfn);
}
diff --git a/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp b/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp
index 39cf7e77175..c75fb2e763d 100644
--- a/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp
+++ b/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp
@@ -192,10 +192,18 @@ bool CoreEngine::ExecuteWorkList(const LocationContext *L, unsigned Steps,
WList->setBlockCounter(BCounterFactory.GetEmptyCounter());
if (!InitState)
- // Generate the root.
- generateNode(StartLoc, SubEng.getInitialState(L), nullptr);
- else
- generateNode(StartLoc, InitState, nullptr);
+ InitState = SubEng.getInitialState(L);
+
+ bool IsNew;
+ ExplodedNode *Node = G.getNode(StartLoc, InitState, false, &IsNew);
+ assert (IsNew);
+ G.addRoot(Node);
+
+ NodeBuilderContext BuilderCtx(*this, StartLoc.getDst(), Node);
+ ExplodedNodeSet DstBegin;
+ SubEng.processBeginOfFunction(BuilderCtx, Node, DstBegin, StartLoc);
+
+ enqueue(DstBegin);
}
// Check if we have a steps limit
@@ -243,8 +251,7 @@ void CoreEngine::dispatchWorkItem(ExplodedNode* Pred, ProgramPoint Loc,
break;
case ProgramPoint::CallEnterKind: {
- CallEnter CEnter = Loc.castAs<CallEnter>();
- SubEng.processCallEnter(CEnter, Pred);
+ HandleCallEnter(Loc.castAs<CallEnter>(), Pred);
break;
}
@@ -456,6 +463,11 @@ void CoreEngine::HandleBlockExit(const CFGBlock * B, ExplodedNode *Pred) {
Pred->State, Pred);
}
+void CoreEngine::HandleCallEnter(const CallEnter &CE, ExplodedNode *Pred) {
+ NodeBuilderContext BuilderCtx(*this, CE.getEntry(), Pred);
+ SubEng.processCallEnter(BuilderCtx, CE, Pred);
+}
+
void CoreEngine::HandleBranch(const Stmt *Cond, const Stmt *Term,
const CFGBlock * B, ExplodedNode *Pred) {
assert(B->succ_size() == 2);
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
index 22b32f84141..0b669336a38 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -30,6 +30,7 @@
#include "llvm/ADT/ImmutableList.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/SaveAndRestore.h"
#ifndef NDEBUG
#include "llvm/Support/GraphWriter.h"
@@ -1749,6 +1750,14 @@ static bool stackFrameDoesNotContainInitializedTemporaries(ExplodedNode &Pred) {
}
#endif
+void ExprEngine::processBeginOfFunction(NodeBuilderContext &BC,
+ ExplodedNode *Pred,
+ ExplodedNodeSet &Dst,
+ const BlockEdge &L) {
+ SaveAndRestore<const NodeBuilderContext *> NodeContextRAII(currBldrCtx, &BC);
+ getCheckerManager().runCheckersForBeginFunction(Dst, L, Pred, *this);
+}
+
/// ProcessEndPath - Called by CoreEngine. Used to generate end-of-path
/// nodes when the control reaches the end of a function.
void ExprEngine::processEndOfFunction(NodeBuilderContext& BC,
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
index e667194198c..39d88bfda14 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
@@ -37,13 +37,12 @@ STATISTIC(NumInlinedCalls,
STATISTIC(NumReachedInlineCountMax,
"The # of times we reached inline count maximum");
-void ExprEngine::processCallEnter(CallEnter CE, ExplodedNode *Pred) {
+void ExprEngine::processCallEnter(NodeBuilderContext& BC, CallEnter CE,
+ ExplodedNode *Pred) {
// Get the entry block in the CFG of the callee.
const StackFrameContext *calleeCtx = CE.getCalleeContext();
PrettyStackTraceLocationContext CrashInfo(calleeCtx);
-
- const CFG *CalleeCFG = calleeCtx->getCFG();
- const CFGBlock *Entry = &(CalleeCFG->getEntry());
+ const CFGBlock *Entry = CE.getEntry();
// Validate the CFG.
assert(Entry->empty());
@@ -57,12 +56,16 @@ void ExprEngine::processCallEnter(CallEnter CE, ExplodedNode *Pred) {
ProgramStateRef state = Pred->getState();
- // Construct a new node and add it to the worklist.
+ // Construct a new node, notify checkers that analysis of the function has
+ // begun, and add the resultant nodes to the worklist.
bool isNew;
ExplodedNode *Node = G.getNode(Loc, state, false, &isNew);
Node->addPredecessor(Pred, G);
- if (isNew)
- Engine.getWorkList()->enqueue(Node);
+ if (isNew) {
+ ExplodedNodeSet DstBegin;
+ processBeginOfFunction(BC, Node, DstBegin, Loc);
+ Engine.enqueue(DstBegin);
+ }
}
// Find the last statement on the path to the exploded node and the
OpenPOWER on IntegriCloud