From: Anna Zaks Date: Wed, 26 Oct 2011 21:06:22 +0000 (+0000) Subject: [analyzer] GenericNodeBuilder -> NodeBuilder. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=c03a39e16762627b421247b12a2658be630a3300;p=clang [analyzer] GenericNodeBuilder -> NodeBuilder. Remove GenericNodeBuilder and use a class inherited from NodeBuilder instead. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@143057 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h index 5fddb75d1f..192e1e4bee 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h @@ -168,6 +168,7 @@ public: void enqueue(ExplodedNodeSet &NB); }; +// TODO: Turn into a calss. struct NodeBuilderContext { CoreEngine &Eng; const CFGBlock *Block; @@ -175,6 +176,8 @@ struct NodeBuilderContext { NodeBuilderContext(CoreEngine &E, const CFGBlock *B, ExplodedNode *N) : Eng(E), Block(B), Pred(N) { assert(B); assert(!N->isSink()); } + ExplodedNode *getPred() const { return Pred; } + /// \brief Return the CFGBlock associated with this builder. const CFGBlock *getBlock() const { return Block; } @@ -288,6 +291,34 @@ public: void addNodes(ExplodedNode *N) { Frontier.Add(N); } }; +/// \class NodeBuilderWithSinks +/// \brief This node builder keeps track of the generated sink nodes. +class NodeBuilderWithSinks: public NodeBuilder { +protected: + SmallVector sinksGenerated; + ProgramPoint &Location; + +public: + NodeBuilderWithSinks(ExplodedNode *Pred, ExplodedNodeSet &DstSet, + const NodeBuilderContext &Ctx, ProgramPoint &L) + : NodeBuilder(Pred, DstSet, Ctx), Location(L) {} + ExplodedNode *generateNode(const ProgramState *State, + ExplodedNode *Pred, + const ProgramPointTag *Tag = 0, + bool MarkAsSink = false) { + ProgramPoint LocalLoc = (Tag ? Location.withTag(Tag): Location); + + ExplodedNode *N = generateNodeImpl(LocalLoc, State, Pred, MarkAsSink); + if (N && N->isSink()) + sinksGenerated.push_back(N); + return N; + } + + const SmallVectorImpl &getSinks() const { + return sinksGenerated; + } +}; + /// \class StmtNodeBuilder /// \brief This builder class is useful for generating nodes that resulted from /// visiting a statement. The main difference from it's parent NodeBuilder is @@ -467,52 +498,6 @@ public: const ProgramState *getState() const { return Pred->State; } }; -class GenericNodeBuilderImpl { -protected: - CoreEngine &engine; - ExplodedNode *pred; - ProgramPoint pp; - SmallVector sinksGenerated; - - ExplodedNode *generateNodeImpl(const ProgramState *state, - ExplodedNode *pred, - ProgramPoint programPoint, - bool asSink); - - GenericNodeBuilderImpl(CoreEngine &eng, ExplodedNode *pr, ProgramPoint p) - : engine(eng), pred(pr), pp(p), hasGeneratedNode(false) {} - -public: - bool hasGeneratedNode; - - WorkList &getWorkList() { return *engine.WList; } - - ExplodedNode *getPredecessor() const { return pred; } - - BlockCounter getBlockCounter() const { - return engine.WList->getBlockCounter(); - } - - const SmallVectorImpl &sinks() const { - return sinksGenerated; - } -}; - -template -class GenericNodeBuilder : public GenericNodeBuilderImpl { -public: - GenericNodeBuilder(CoreEngine &eng, ExplodedNode *pr, const PP_T &p) - : GenericNodeBuilderImpl(eng, pr, p) {} - - ExplodedNode *generateNode(const ProgramState *state, ExplodedNode *pred, - const ProgramPointTag *tag, bool asSink) { - return generateNodeImpl(state, pred, cast(pp).withTag(tag), - asSink); - } - - const PP_T &getProgramPoint() const { return cast(pp); } -}; - class CallEnterNodeBuilder { CoreEngine &Eng; diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h index 325d824090..7409b19e4e 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h @@ -161,8 +161,7 @@ public: ExplodedNode *Pred, ExplodedNodeSet &Dst); /// Called by CoreEngine when processing the entrance of a CFGBlock. - virtual void processCFGBlockEntrance(ExplodedNodeSet &dstNodes, - GenericNodeBuilder &nodeBuilder); + virtual void processCFGBlockEntrance(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 c35e6cca41..d258b2c807 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h @@ -40,6 +40,7 @@ class SwitchNodeBuilder; class EndOfFunctionNodeBuilder; class CallEnterNodeBuilder; class CallExitNodeBuilder; +class NodeBuilderWithSinks; class MemRegion; class SubEngine { @@ -60,8 +61,7 @@ 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(ExplodedNodeSet &dstNodes, - GenericNodeBuilder &nodeBuilder) = 0; + virtual void processCFGBlockEntrance(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 6b8c7df224..f693917242 100644 --- a/lib/StaticAnalyzer/Core/CoreEngine.cpp +++ b/lib/StaticAnalyzer/Core/CoreEngine.cpp @@ -261,6 +261,7 @@ void CoreEngine::HandleCallExit(const CallExit &L, ExplodedNode *Pred) { void CoreEngine::HandleBlockEdge(const BlockEdge &L, ExplodedNode *Pred) { const CFGBlock *Blk = L.getDst(); + NodeBuilderContext BuilderCtx(*this, Blk, Pred); // Check if we are entering the EXIT block. if (Blk == &(L.getLocationContext()->getCFG()->getExit())) { @@ -269,35 +270,30 @@ void CoreEngine::HandleBlockEdge(const BlockEdge &L, ExplodedNode *Pred) { && "EXIT block cannot contain Stmts."); // Process the final state transition. - NodeBuilderContext BuilderCtx(*this, Blk, Pred); SubEng.processEndOfFunction(BuilderCtx); // This path is done. Don't enqueue any more nodes. return; } - // Call into the subengine to process entering the CFGBlock. + // Call into the SubEngine to process entering the CFGBlock. ExplodedNodeSet dstNodes; BlockEntrance BE(Blk, Pred->getLocationContext()); - GenericNodeBuilder nodeBuilder(*this, Pred, BE); - SubEng.processCFGBlockEntrance(dstNodes, nodeBuilder); + NodeBuilderWithSinks nodeBuilder(Pred, dstNodes, BuilderCtx, BE); + SubEng.processCFGBlockEntrance(nodeBuilder); - if (dstNodes.empty()) { - if (!nodeBuilder.hasGeneratedNode) { - // Auto-generate a node and enqueue it to the worklist. - generateNode(BE, Pred->State, Pred); - } - } - else { - for (ExplodedNodeSet::iterator I = dstNodes.begin(), E = dstNodes.end(); - I != E; ++I) { - WList->enqueue(*I); - } + // Auto-generate a node. + if (!nodeBuilder.hasGeneratedNodes()) { + nodeBuilder.generateNode(Pred->State, Pred); } + // Enqueue nodes onto the worklist. + enqueue(dstNodes); + + // Make sink nodes as exhausted. + const SmallVectorImpl &Sinks = nodeBuilder.getSinks(); for (SmallVectorImpl::const_iterator - I = nodeBuilder.sinks().begin(), E = nodeBuilder.sinks().end(); - I != E; ++I) { + I =Sinks.begin(), E = Sinks.end(); I != E; ++I) { blocksExhausted.push_back(std::make_pair(L, *I)); } } @@ -465,27 +461,6 @@ void CoreEngine::enqueue(ExplodedNodeSet &S) { } } -ExplodedNode * -GenericNodeBuilderImpl::generateNodeImpl(const ProgramState *state, - ExplodedNode *pred, - ProgramPoint programPoint, - bool asSink) { - - hasGeneratedNode = true; - bool isNew; - ExplodedNode *node = engine.getGraph().getNode(programPoint, state, &isNew); - if (pred) - node->addPredecessor(pred, engine.getGraph()); - if (isNew) { - if (asSink) { - node->markAsSink(); - sinksGenerated.push_back(node); - } - return node; - } - return 0; -} - ExplodedNode* NodeBuilder::generateNodeImpl(const ProgramPoint &Loc, const ProgramState *State, ExplodedNode *FromN, diff --git a/lib/StaticAnalyzer/Core/ExprEngine.cpp b/lib/StaticAnalyzer/Core/ExprEngine.cpp index 0eacb31b28..24fa04bd56 100644 --- a/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -909,20 +909,13 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred, } } -//===----------------------------------------------------------------------===// -// Block entrance. (Update counters). -//===----------------------------------------------------------------------===// - -void ExprEngine::processCFGBlockEntrance(ExplodedNodeSet &dstNodes, - GenericNodeBuilder &nodeBuilder){ +/// Block entrance. (Update counters). +void ExprEngine::processCFGBlockEntrance(NodeBuilderWithSinks &nodeBuilder) { // FIXME: Refactor this into a checker. - const CFGBlock *block = nodeBuilder.getProgramPoint().getBlock(); - ExplodedNode *pred = nodeBuilder.getPredecessor(); + ExplodedNode *pred = nodeBuilder.getContext().getPred(); - if (nodeBuilder.getBlockCounter().getNumVisited( - pred->getLocationContext()->getCurrentStackFrame(), - block->getBlockID()) >= AMgr.getMaxVisit()) { + if (nodeBuilder.getContext().getCurrentBlockCount() >= AMgr.getMaxVisit()) { static SimpleProgramPointTag tag("ExprEngine : Block count exceeded"); nodeBuilder.generateNode(pred->getState(), pred, &tag, true); }