]> granicus.if.org Git - clang/commitdiff
Add preliminary support for flagging leaks around when they happen (doesn't work...
authorTed Kremenek <kremenek@apple.com>
Thu, 24 Apr 2008 23:57:27 +0000 (23:57 +0000)
committerTed Kremenek <kremenek@apple.com>
Thu, 24 Apr 2008 23:57:27 +0000 (23:57 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@50237 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Analysis/CFRefCount.cpp

index 2e0c1aa7605dfabab03f05d22055c1c5ff94752f..a1380af497980ce29456e72bff2a465053f678d4 100644 (file)
@@ -684,6 +684,13 @@ public:
   virtual void EvalEndPath(GRExprEngine& Engine,
                            GREndPathNodeBuilder<ValueState>& Builder);
   
+  virtual void EvalDeadSymbols(ExplodedNodeSet<ValueState>& Dst,
+                               GRExprEngine& Engine,
+                               GRStmtNodeBuilder<ValueState>& Builder,
+                               ProgramPoint P, ExplodedNode<ValueState>* Pred,
+                               ValueState* St,
+                               const ValueStateManager::DeadSymbolsTy& Dead);
+  
   // Return statements.
   
   virtual void EvalReturn(ExplodedNodeSet<ValueState>& Dst,
@@ -1066,10 +1073,13 @@ void CFRefCount::EvalEndPath(GRExprEngine& Eng,
     
     if (hasLeak) Leaked.push_back((*I).first);
   }
-      
+
+  if (Leaked.empty())
+    return;
+  
   ExplodedNode<ValueState>* N = Builder.MakeNode(St);  
   
-  if (!N || Leaked.empty())
+  if (!N)
     return;
     
   std::vector<SymbolID>*& LeaksAtNode = Leaks[N];
@@ -1081,6 +1091,64 @@ void CFRefCount::EvalEndPath(GRExprEngine& Eng,
     (*LeaksAtNode).push_back(*I);
 }
 
+// Dead symbols.
+
+void CFRefCount::EvalDeadSymbols(ExplodedNodeSet<ValueState>& Dst,
+                                 GRExprEngine& Eng,
+                                 GRStmtNodeBuilder<ValueState>& Builder,
+                                 ProgramPoint P, ExplodedNode<ValueState>* Pred,
+                                 ValueState* St,
+                                 const ValueStateManager::DeadSymbolsTy& Dead) {
+  
+  // FIXME: Have GRStmtNodeBuilder handle the case where 'P' is not PostStmt;
+  //  This won't result in missed leaks; we'll just flag these ones at the
+  //  end-of-path.
+  
+  Stmt* S = NULL;
+  
+  if (!isa<PostStmt>(P))
+    return;
+  
+  S = cast<PostStmt>(P).getStmt();
+  
+  // FIXME: a lot of copy-and-paste from EvalEndPath.  Refactor.
+  
+  RefBindings B = GetRefBindings(*St);
+  llvm::SmallVector<SymbolID, 10> Leaked;
+  
+  for (ValueStateManager::DeadSymbolsTy::const_iterator
+       I=Dead.begin(), E=Dead.end(); I!=E; ++I) {
+    
+    RefBindings::TreeTy* T = B.SlimFind(*I);
+
+    if (!T)
+      continue;
+    
+    bool hasLeak = false;
+    
+    St = HandleSymbolDeath(Eng.getStateManager(), St,
+                           *I, T->getValue().second, hasLeak);
+    
+    if (hasLeak) Leaked.push_back(*I);    
+  }
+  
+  if (Leaked.empty())
+    return;    
+  
+  ExplodedNode<ValueState>* N = Builder.MakeNode(Dst, S, Pred, St);  
+  
+  if (!N)
+    return;
+  
+  std::vector<SymbolID>*& LeaksAtNode = Leaks[N];
+  assert (!LeaksAtNode);
+  LeaksAtNode = new std::vector<SymbolID>();
+  
+  for (llvm::SmallVector<SymbolID, 10>::iterator I=Leaked.begin(),
+       E = Leaked.end(); I != E; ++I)
+    (*LeaksAtNode).push_back(*I);    
+}
+
  // Return statements.
 
 void CFRefCount::EvalReturn(ExplodedNodeSet<ValueState>& Dst,