diff options
Diffstat (limited to 'lib/StaticAnalyzer/Core')
-rw-r--r-- | lib/StaticAnalyzer/Core/CheckerManager.cpp | 21 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/CoreEngine.cpp | 55 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/ExprEngine.cpp | 37 |
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 |