aboutsummaryrefslogtreecommitdiff
path: root/lib/StaticAnalyzer/Core
diff options
context:
space:
mode:
Diffstat (limited to 'lib/StaticAnalyzer/Core')
-rw-r--r--lib/StaticAnalyzer/Core/CheckerManager.cpp21
-rw-r--r--lib/StaticAnalyzer/Core/CoreEngine.cpp55
-rw-r--r--lib/StaticAnalyzer/Core/ExprEngine.cpp37
3 files changed, 53 insertions, 60 deletions
diff --git a/lib/StaticAnalyzer/Core/CheckerManager.cpp b/lib/StaticAnalyzer/Core/CheckerManager.cpp
index b24f9a0b3c..67fe4d6ca2 100644
--- a/lib/StaticAnalyzer/Core/CheckerManager.cpp
+++ b/lib/StaticAnalyzer/Core/CheckerManager.cpp
@@ -298,12 +298,25 @@ void CheckerManager::runCheckersForEndAnalysis(ExplodedGraph &G,
}
/// \brief Run checkers for end of path.
-void CheckerManager::runCheckersForEndPath(EndOfFunctionNodeBuilder &B,
+// Note, We do not chain the checker output (like in expandGraphWithCheckers)
+// for this callback since end of path nodes are expected to be final.
+void CheckerManager::runCheckersForEndPath(NodeBuilderContext &BC,
+ ExplodedNodeSet &Dst,
ExprEngine &Eng) {
+ ExplodedNode *Pred = BC.Pred;
+
+ // We define the builder outside of the loop bacause if at least one checkers
+ // creates a sucsessor for Pred, we do not need to generate an
+ // autotransition for it.
+ NodeBuilder Bldr(Pred, Dst, BC);
for (unsigned i = 0, e = EndPathCheckers.size(); i != e; ++i) {
- CheckEndPathFunc fn = EndPathCheckers[i];
- EndOfFunctionNodeBuilder specialB = B.withCheckerTag(fn.Checker);
- fn(specialB, Eng);
+ CheckEndPathFunc checkFn = EndPathCheckers[i];
+
+ const ProgramPoint &L = BlockEntrance(BC.Block,
+ Pred->getLocationContext(),
+ checkFn.Checker);
+ CheckerContext C(Bldr, Eng, Pred, L, 0);
+ checkFn(C);
}
}
diff --git a/lib/StaticAnalyzer/Core/CoreEngine.cpp b/lib/StaticAnalyzer/Core/CoreEngine.cpp
index 6a14815d5d..6b8c7df224 100644
--- a/lib/StaticAnalyzer/Core/CoreEngine.cpp
+++ b/lib/StaticAnalyzer/Core/CoreEngine.cpp
@@ -269,8 +269,8 @@ void CoreEngine::HandleBlockEdge(const BlockEdge &L, ExplodedNode *Pred) {
&& "EXIT block cannot contain Stmts.");
// Process the final state transition.
- EndOfFunctionNodeBuilder Builder(Blk, Pred, this);
- SubEng.processEndOfFunction(Builder);
+ NodeBuilderContext BuilderCtx(*this, Blk, Pred);
+ SubEng.processEndOfFunction(BuilderCtx);
// This path is done. Don't enqueue any more nodes.
return;
@@ -597,57 +597,6 @@ SwitchNodeBuilder::generateDefaultCaseNode(const ProgramState *St,
return NULL;
}
-EndOfFunctionNodeBuilder::~EndOfFunctionNodeBuilder() {
- // Auto-generate an EOP node if one has not been generated.
- if (!hasGeneratedNode) {
- // If we are in an inlined call, generate CallExit node.
- if (Pred->getLocationContext()->getParent())
- GenerateCallExitNode(Pred->State);
- else
- generateNode(Pred->State);
- }
-}
-
-ExplodedNode*
-EndOfFunctionNodeBuilder::generateNode(const ProgramState *State,
- ExplodedNode *P,
- const ProgramPointTag *tag) {
- hasGeneratedNode = true;
- bool IsNew;
-
- ExplodedNode *Node = Eng.G->getNode(BlockEntrance(&B,
- Pred->getLocationContext(), tag ? tag : Tag),
- State, &IsNew);
-
- Node->addPredecessor(P ? P : Pred, *Eng.G);
-
- if (IsNew) {
- Eng.G->addEndOfPath(Node);
- return Node;
- }
-
- return NULL;
-}
-
-void EndOfFunctionNodeBuilder::GenerateCallExitNode(const ProgramState *state) {
- hasGeneratedNode = true;
- // Create a CallExit node and enqueue it.
- const StackFrameContext *LocCtx
- = cast<StackFrameContext>(Pred->getLocationContext());
- const Stmt *CE = LocCtx->getCallSite();
-
- // Use the the callee location context.
- CallExit Loc(CE, LocCtx);
-
- bool isNew;
- ExplodedNode *Node = Eng.G->getNode(Loc, state, &isNew);
- Node->addPredecessor(Pred, *Eng.G);
-
- if (isNew)
- Eng.WList->enqueue(Node);
-}
-
-
void CallEnterNodeBuilder::generateNode(const ProgramState *state) {
// Check if the callee is in the same translation unit.
if (CalleeCtx->getTranslationUnit() !=
diff --git a/lib/StaticAnalyzer/Core/ExprEngine.cpp b/lib/StaticAnalyzer/Core/ExprEngine.cpp
index 13550c793d..3e5a31cda0 100644
--- a/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -1153,11 +1153,42 @@ void ExprEngine::processIndirectGoto(IndirectGotoNodeBuilder &builder) {
builder.generateNode(I, state);
}
+// TODO: The next two functions should be moved into CoreEngine.
+void ExprEngine::GenerateCallExitNode(ExplodedNode *N) {
+ // Create a CallExit node and enqueue it.
+ const StackFrameContext *LocCtx
+ = cast<StackFrameContext>(N->getLocationContext());
+ const Stmt *CE = LocCtx->getCallSite();
+
+ // Use the the callee location context.
+ CallExit Loc(CE, LocCtx);
+
+ bool isNew;
+ ExplodedNode *Node = Engine.G->getNode(Loc, N->getState(), &isNew);
+ Node->addPredecessor(N, *Engine.G);
+
+ if (isNew)
+ Engine.WList->enqueue(Node);
+}
+
+void ExprEngine::enqueueEndOfPath(ExplodedNodeSet &S) {
+ for (ExplodedNodeSet::iterator I = S.begin(), E = S.end(); I != E; ++I) {
+ ExplodedNode *N = *I;
+ // If we are in an inlined call, generate CallExit node.
+ if (N->getLocationContext()->getParent())
+ GenerateCallExitNode(N);
+ else
+ Engine.G->addEndOfPath(N);
+ }
+}
+
/// ProcessEndPath - Called by CoreEngine. Used to generate end-of-path
/// nodes when the control reaches the end of a function.
-void ExprEngine::processEndOfFunction(EndOfFunctionNodeBuilder& builder) {
- StateMgr.EndPath(builder.getState());
- getCheckerManager().runCheckersForEndPath(builder, *this);
+void ExprEngine::processEndOfFunction(NodeBuilderContext& BC) {
+ StateMgr.EndPath(BC.Pred->getState());
+ ExplodedNodeSet Dst;
+ getCheckerManager().runCheckersForEndPath(BC, Dst, *this);
+ enqueueEndOfPath(Dst);
}
/// ProcessSwitch - Called by CoreEngine. Used to generate successor