]> granicus.if.org Git - clang/commitdiff
Inter-procedural analysis: now we can return from the callee.
authorZhongxing Xu <xuzhongxing@gmail.com>
Thu, 24 Dec 2009 02:25:21 +0000 (02:25 +0000)
committerZhongxing Xu <xuzhongxing@gmail.com>
Thu, 24 Dec 2009 02:25:21 +0000 (02:25 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@92116 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Analysis/PathSensitive/GRCoreEngine.h
lib/Analysis/CallInliner.cpp

index e2a03a21ebf82110e80f9b826c45c69009135815..74f7a147b841f6173a279c1ec7f84f4b6ceda6c7 100644 (file)
@@ -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 {
-  GRCoreEngineEng;
+  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 {
index 2f748bd8bd5226da940377cf319874e9f7d6f3c5..618d82354ed7d36d48db485834cb748653fc2b94 100644 (file)
@@ -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;
+}