diff options
author | Anna Zaks <ganna@apple.com> | 2012-03-28 17:05:50 +0000 |
---|---|---|
committer | Anna Zaks <ganna@apple.com> | 2012-03-28 17:05:50 +0000 |
commit | 253955ca25c7e7049963b5db613c0cd15d66e4f8 (patch) | |
tree | cf67d311462fa4c77a9a30cd90dbee2a0bfc2a40 | |
parent | 64ee9d03c9fa0e9f4b944300167f871d9a65a991 (diff) |
[analyser] Stats checker: do not mark a node as exhausted if we will
retry without inlining.
(+ other minor cleanups)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@153581 91177308-0d34-0410-b5e6-96231b3b80d8
5 files changed, 34 insertions, 34 deletions
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h index a9a4ae4230..85d92ff5f7 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h @@ -42,6 +42,7 @@ class NodeBuilder; class CoreEngine { friend struct NodeBuilderContext; friend class NodeBuilder; + friend class ExprEngine; friend class CommonNodeBuilder; friend class IndirectGotoNodeBuilder; friend class SwitchNodeBuilder; @@ -124,7 +125,8 @@ public: /// steps. Returns true if there is still simulation state on the worklist. bool ExecuteWorkList(const LocationContext *L, unsigned Steps, ProgramStateRef InitState); - void ExecuteWorkListWithInitialState(const LocationContext *L, + /// Returns true if there is still simulation state on the worklist. + bool ExecuteWorkListWithInitialState(const LocationContext *L, unsigned Steps, ProgramStateRef InitState, ExplodedNodeSet &Dst); diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h index 2c144109b2..c0c6ef3fb4 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h @@ -95,17 +95,19 @@ public: ~ExprEngine(); - void ExecuteWorkList(const LocationContext *L, unsigned Steps = 150000) { - Engine.ExecuteWorkList(L, Steps, 0); + /// Returns true if there is still simulation state on the worklist. + bool ExecuteWorkList(const LocationContext *L, unsigned Steps = 150000) { + return Engine.ExecuteWorkList(L, Steps, 0); } /// Execute the work list with an initial state. Nodes that reaches the exit /// of the function are added into the Dst set, which represent the exit - /// state of the function call. - void ExecuteWorkListWithInitialState(const LocationContext *L, unsigned Steps, + /// state of the function call. Returns true if there is still simulation + /// state on the worklist. + bool ExecuteWorkListWithInitialState(const LocationContext *L, unsigned Steps, ProgramStateRef InitState, ExplodedNodeSet &Dst) { - Engine.ExecuteWorkListWithInitialState(L, Steps, InitState, Dst); + return Engine.ExecuteWorkListWithInitialState(L, Steps, InitState, Dst); } /// getContext - Return the ASTContext associated with this analysis. @@ -168,7 +170,8 @@ public: ExplodedNode *Pred, ExplodedNodeSet &Dst); /// Called by CoreEngine when processing the entrance of a CFGBlock. - virtual void processCFGBlockEntrance(NodeBuilderWithSinks &nodeBuilder); + virtual void processCFGBlockEntrance(const BlockEdge &L, + NodeBuilderWithSinks &nodeBuilder); /// ProcessBranch - Called by CoreEngine. Used to generate successor /// nodes by processing the 'effects' of a branch condition. diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h index 0fb04b8325..baf57d4906 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h @@ -59,7 +59,8 @@ public: /// Called by CoreEngine when it starts processing a CFGBlock. The /// SubEngine is expected to populate dstNodes with new nodes representing /// updated analysis state, or generate no nodes at all if it doesn't. - virtual void processCFGBlockEntrance(NodeBuilderWithSinks &nodeBuilder) = 0; + virtual void processCFGBlockEntrance(const BlockEdge &L, + NodeBuilderWithSinks &nodeBuilder) = 0; /// Called by CoreEngine. Used to generate successor /// nodes by processing the 'effects' of a branch condition. diff --git a/lib/StaticAnalyzer/Core/CoreEngine.cpp b/lib/StaticAnalyzer/Core/CoreEngine.cpp index f303c7af3a..de94f0f2dd 100644 --- a/lib/StaticAnalyzer/Core/CoreEngine.cpp +++ b/lib/StaticAnalyzer/Core/CoreEngine.cpp @@ -263,15 +263,16 @@ void CoreEngine::dispatchWorkItem(ExplodedNode* Pred, ProgramPoint Loc, } } -void CoreEngine::ExecuteWorkListWithInitialState(const LocationContext *L, +bool CoreEngine::ExecuteWorkListWithInitialState(const LocationContext *L, unsigned Steps, ProgramStateRef InitState, ExplodedNodeSet &Dst) { - ExecuteWorkList(L, Steps, InitState); + bool DidNotFinish = ExecuteWorkList(L, Steps, InitState); for (ExplodedGraph::eop_iterator I = G->eop_begin(), E = G->eop_end(); I != E; ++I) { Dst.Add(*I); } + return DidNotFinish; } void CoreEngine::HandleBlockEdge(const BlockEdge &L, ExplodedNode *Pred) { @@ -296,7 +297,7 @@ void CoreEngine::HandleBlockEdge(const BlockEdge &L, ExplodedNode *Pred) { ExplodedNodeSet dstNodes; BlockEntrance BE(Blk, Pred->getLocationContext()); NodeBuilderWithSinks nodeBuilder(Pred, dstNodes, BuilderCtx, BE); - SubEng.processCFGBlockEntrance(nodeBuilder); + SubEng.processCFGBlockEntrance(L, nodeBuilder); // Auto-generate a node. if (!nodeBuilder.hasGeneratedNodes()) { @@ -305,13 +306,6 @@ void CoreEngine::HandleBlockEdge(const BlockEdge &L, ExplodedNode *Pred) { // Enqueue nodes onto the worklist. enqueue(dstNodes); - - // Make sink nodes as exhausted. - const SmallVectorImpl<ExplodedNode*> &Sinks = nodeBuilder.getSinks(); - for (SmallVectorImpl<ExplodedNode*>::const_iterator - I =Sinks.begin(), E = Sinks.end(); I != E; ++I) { - blocksExhausted.push_back(std::make_pair(L, *I)); - } } void CoreEngine::HandleBlockEntrance(const BlockEntrance &L, diff --git a/lib/StaticAnalyzer/Core/ExprEngine.cpp b/lib/StaticAnalyzer/Core/ExprEngine.cpp index c47b7f4eb5..a53ffd4eb5 100644 --- a/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -53,11 +53,6 @@ STATISTIC(NumMaxBlockCountReachedInInlined, STATISTIC(NumTimesRetriedWithoutInlining, "The # of times we re-evaluated a call without inlining"); -STATISTIC(NumNotNew, - "Cached out"); -STATISTIC(NumNull, - "Null node"); - //===----------------------------------------------------------------------===// // Utility functions. //===----------------------------------------------------------------------===// @@ -1005,10 +1000,8 @@ bool ExprEngine::replayWithoutInlining(ExplodedNode *N, break; } - if (!BeforeProcessingCall) { - NumNull++; + if (!BeforeProcessingCall) return false; - } // TODO: Clean up the unneeded nodes. @@ -1024,10 +1017,11 @@ bool ExprEngine::replayWithoutInlining(ExplodedNode *N, // Make the new node a successor of BeforeProcessingCall. bool IsNew = false; ExplodedNode *NewNode = G.getNode(NewNodeLoc, NewNodeState, false, &IsNew); - if (!IsNew) { - NumNotNew++; - return false; - } + // We cached out at this point. Caching out is common due to us backtracking + // from the inlined function, which might spawn several paths. + if (!IsNew) + return true; + NewNode->addPredecessor(BeforeProcessingCall, G); // Add the new node to the work list. @@ -1038,14 +1032,16 @@ bool ExprEngine::replayWithoutInlining(ExplodedNode *N, } /// Block entrance. (Update counters). -void ExprEngine::processCFGBlockEntrance(NodeBuilderWithSinks &nodeBuilder) { +void ExprEngine::processCFGBlockEntrance(const BlockEdge &L, + NodeBuilderWithSinks &nodeBuilder) { // FIXME: Refactor this into a checker. ExplodedNode *pred = nodeBuilder.getContext().getPred(); if (nodeBuilder.getContext().getCurrentBlockCount() >= AMgr.getMaxVisit()) { static SimpleProgramPointTag tag("ExprEngine : Block count exceeded"); - nodeBuilder.generateNode(pred->getState(), pred, &tag, true); + const ExplodedNode *Sink = + nodeBuilder.generateNode(pred->getState(), pred, &tag, true); // Check if we stopped at the top level function or not. // Root node should have the location context of the top most function. @@ -1057,10 +1053,14 @@ void ExprEngine::processCFGBlockEntrance(NodeBuilderWithSinks &nodeBuilder) { // no-inlining policy in the state and enqueuing the new work item on // the list. Replay should almost never fail. Use the stats to catch it // if it does. - if (!(AMgr.RetryExhausted && replayWithoutInlining(pred, CalleeLC))) - NumMaxBlockCountReachedInInlined++; + if ((AMgr.RetryExhausted && replayWithoutInlining(pred, CalleeLC))) + return; + NumMaxBlockCountReachedInInlined++; } else NumMaxBlockCountReached++; + + // Make sink nodes as exhausted(for stats) only if retry failed. + Engine.blocksExhausted.push_back(std::make_pair(L, Sink)); } } |