diff options
author | Zhongxing Xu <xuzhongxing@gmail.com> | 2009-12-24 02:25:21 +0000 |
---|---|---|
committer | Zhongxing Xu <xuzhongxing@gmail.com> | 2009-12-24 02:25:21 +0000 |
commit | 598278bee8e5797bc73d24d6ac8a1d6ff6413cae (patch) | |
tree | 06c79858615a4bc2b2e87029fc63837701e9cf3d | |
parent | 6281213d87e71b76f64c4ca62fbe7a97f18ae0a0 (diff) |
Inter-procedural analysis: now we can return from the callee.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@92116 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/Analysis/PathSensitive/GRCoreEngine.h | 6 | ||||
-rw-r--r-- | lib/Analysis/CallInliner.cpp | 37 |
2 files changed, 42 insertions, 1 deletions
diff --git a/include/clang/Analysis/PathSensitive/GRCoreEngine.h b/include/clang/Analysis/PathSensitive/GRCoreEngine.h index e2a03a21eb..74f7a147b8 100644 --- a/include/clang/Analysis/PathSensitive/GRCoreEngine.h +++ b/include/clang/Analysis/PathSensitive/GRCoreEngine.h @@ -211,6 +211,8 @@ public: /// of this builder. CFGBlock* getBlock() const { return &B; } + unsigned getIndex() const { return Idx; } + void setAuditor(GRAuditor* A) { Auditor = A; } const GRState* GetState(ExplodedNode* Pred) const { @@ -401,7 +403,7 @@ public: }; class GREndPathNodeBuilder { - GRCoreEngine& Eng; + GRCoreEngine &Eng; CFGBlock& B; ExplodedNode* Pred; @@ -414,6 +416,8 @@ public: ~GREndPathNodeBuilder(); + GRWorkList &getWorkList() { return *Eng.WList; } + ExplodedNode* getPredecessor() const { return Pred; } GRBlockCounter getBlockCounter() const { diff --git a/lib/Analysis/CallInliner.cpp b/lib/Analysis/CallInliner.cpp index 2f748bd8bd..618d82354e 100644 --- a/lib/Analysis/CallInliner.cpp +++ b/lib/Analysis/CallInliner.cpp @@ -19,6 +19,11 @@ using namespace clang; namespace { class CallInliner : public Checker { + + /// CallSitePosition - Map the call site to its CFG block and stmt index. This + /// is used when exiting from a callee. + llvm::DenseMap<const Stmt *, std::pair<CFGBlock*,unsigned> > CallSitePosition; + public: static void *getTag() { static int x; @@ -26,6 +31,7 @@ public: } virtual bool EvalCallExpr(CheckerContext &C, const CallExpr *CE); + virtual void EvalEndPath(GREndPathNodeBuilder &B,void *tag,GRExprEngine &Eng); }; } @@ -77,6 +83,37 @@ bool CallInliner::EvalCallExpr(CheckerContext &C, const CallExpr *CE) { Builder.HasGeneratedNode = true; + // Record the call site position. + CallSitePosition[CE] = std::make_pair(Builder.getBlock(), Builder.getIndex()); return true; } +void CallInliner::EvalEndPath(GREndPathNodeBuilder &B, void *tag, + GRExprEngine &Eng) { + const GRState *state = B.getState(); + ExplodedNode *Pred = B.getPredecessor(); + const StackFrameContext *LocCtx = + cast<StackFrameContext>(Pred->getLocationContext()); + + const Stmt *CE = LocCtx->getCallSite(); + + // Check if this is the top level stack frame. + if (!LocCtx->getParent()) + return; + + PostStmt NodeLoc(CE, LocCtx->getParent()); + + bool isNew; + ExplodedNode *Succ = Eng.getGraph().getNode(NodeLoc, state, &isNew); + Succ->addPredecessor(Pred, Eng.getGraph()); + + assert(CallSitePosition.find(CE) != CallSitePosition.end()); + + // When creating the new work list unit, increment the statement index to + // point to the statement after the CallExpr. + if (isNew) + B.getWorkList().Enqueue(Succ, *CallSitePosition[CE].first, + CallSitePosition[CE].second + 1); + + B.HasGeneratedNode = true; +} |