Added "GetErrorNodes()" to BugType so that -trim-egraph can recognize errors
from registered BugTypes.  This helps with debugging.

Add detection of NULL values in ref count checker; this suppresses false positives.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@49912 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Analysis/CFRefCount.cpp b/lib/Analysis/CFRefCount.cpp
index 1618f04..3eb0379 100644
--- a/lib/Analysis/CFRefCount.cpp
+++ b/lib/Analysis/CFRefCount.cpp
@@ -693,7 +693,12 @@
                           GRStmtNodeBuilder<ValueState>& Builder,
                           ReturnStmt* S,
                           ExplodedNode<ValueState>* Pred);
-  
+
+  // Assumptions.
+
+  virtual ValueState* EvalAssume(GRExprEngine& Engine, ValueState* St,
+                                 RVal Cond, bool Assumption, bool& isFeasible);
+
   // Error iterators.
 
   typedef UseAfterReleasesTy::iterator use_after_iterator;  
@@ -1029,8 +1034,6 @@
 
 // End-of-path.
 
-
-
 ValueState* CFRefCount::HandleSymbolDeath(ValueStateManager& VMgr,
                                           ValueState* St, SymbolID sid,
                                           RefVal V, bool& hasLeak) {
@@ -1066,9 +1069,9 @@
       
   ExplodedNode<ValueState>* N = Builder.MakeNode(St);  
   
-  if (!N)
+  if (!N || Leaked.empty())
     return;
-  
+    
   std::vector<SymbolID>*& LeaksAtNode = Leaks[N];
   assert (!LeaksAtNode);
   LeaksAtNode = new std::vector<SymbolID>();
@@ -1138,6 +1141,44 @@
   Builder.MakeNode(Dst, S, Pred, StateMgr.getPersistentState(StImpl));
 }
 
+// Assumptions.
+
+ValueState* CFRefCount::EvalAssume(GRExprEngine& Eng, ValueState* St,
+                                   RVal Cond, bool Assumption,
+                                   bool& isFeasible) {
+
+  // FIXME: We may add to the interface of EvalAssume the list of symbols
+  //  whose assumptions have changed.  For now we just iterate through the
+  //  bindings and check if any of the tracked symbols are NULL.  This isn't
+  //  too bad since the number of symbols we will track in practice are 
+  //  probably small and EvalAssume is only called at branches and a few
+  //  other places.
+    
+  RefBindings B = GetRefBindings(*St);
+  
+  if (B.isEmpty())
+    return St;
+  
+  bool changed = false;
+
+  for (RefBindings::iterator I=B.begin(), E=B.end(); I!=E; ++I) {    
+
+    // Check if the symbol is null (or equal to any constant).
+    // If this is the case, stop tracking the symbol.
+  
+    if (St->getSymVal(I.getKey())) {
+      changed = true;
+      B = RefBFactory.Remove(B, I.getKey());
+    }
+  }
+  
+  if (!changed)
+    return St;
+  
+  ValueState StImpl = *St;
+  StImpl.CheckerState = B.getRoot();
+  return Eng.getStateManager().getPersistentState(StImpl);
+}
 
 CFRefCount::RefBindings CFRefCount::Update(RefBindings B, SymbolID sym,
                                            RefVal V, ArgEffect E,
@@ -1280,6 +1321,7 @@
     }
     
     virtual void EmitWarnings(BugReporter& BR);
+    virtual void GetErrorNodes(std::vector<ExplodedNode<ValueState>*>& Nodes);    
   };
   
   //===---------===//
@@ -1465,6 +1507,12 @@
   }  
 }
 
+void Leak::GetErrorNodes(std::vector<ExplodedNode<ValueState>*>& Nodes) {
+  for (CFRefCount::leaks_iterator I=TF.leaks_begin(), E=TF.leaks_end();
+       I!=E; ++I)
+    Nodes.push_back(I->first);
+}
+
 //===----------------------------------------------------------------------===//
 // Transfer function creation for external clients.
 //===----------------------------------------------------------------------===//