Add support for registering 'Checker' objects with GRExprEngine.
Add a 'previsit' stage (that dispatches to registered Checkers) when evaluating the effects of CallExprs.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@76794 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Analysis/GRExprEngine.cpp b/lib/Analysis/GRExprEngine.cpp
index 01cc033..24e4cfa 100644
--- a/lib/Analysis/GRExprEngine.cpp
+++ b/lib/Analysis/GRExprEngine.cpp
@@ -15,6 +15,7 @@
 
 #include "clang/Analysis/PathSensitive/GRExprEngine.h"
 #include "clang/Analysis/PathSensitive/GRExprEngineBuilders.h"
+#include "clang/Analysis/PathSensitive/Checker.h"
 #include "clang/AST/ParentMap.h"
 #include "clang/AST/StmtObjC.h"
 #include "clang/Basic/Builtins.h"
@@ -36,7 +37,7 @@
 using llvm::APSInt;
 
 //===----------------------------------------------------------------------===//
-// Engine construction and deletion.
+// Batch auditor.  DEPRECATED.
 //===----------------------------------------------------------------------===//
 
 namespace {
@@ -103,6 +104,40 @@
 } // end anonymous namespace
 
 //===----------------------------------------------------------------------===//
+// Checker worklist routines.
+//===----------------------------------------------------------------------===//
+  
+void GRExprEngine::CheckerVisit(Stmt *S, NodeSet &Dst, NodeSet &Src,
+                                bool isPrevisit) {
+  
+  if (Checkers.empty()) {
+    Dst = Src;
+    return;
+  }
+  
+  NodeSet Tmp;
+  NodeSet *PrevSet = &Src;
+  
+  for (std::vector<Checker*>::iterator I = Checkers.begin(), E = Checkers.end();
+       I != E; ++I) {
+
+    NodeSet *CurrSet = (I+1 == E) ? &Dst : (PrevSet == &Tmp) ? &Src : &Tmp;
+    CurrSet->clear();
+    Checker *checker = *I;
+    
+    for (NodeSet::iterator NI = PrevSet->begin(), NE = PrevSet->end();
+         NI != NE; ++NI)
+      checker->GR_Visit(*CurrSet, *Builder, *this, S, *NI, isPrevisit);
+    
+    // Update which NodeSet is the current one.
+    PrevSet = CurrSet;
+  }
+
+  // Don't autotransition.  The CheckerContext objects should do this
+  // automatically.
+}
+
+//===----------------------------------------------------------------------===//
 // Engine construction and deletion.
 //===----------------------------------------------------------------------===//
 
@@ -135,6 +170,9 @@
 GRExprEngine::~GRExprEngine() {    
   BR.FlushReports();
   delete [] NSExceptionInstanceRaiseSelectors;
+  for (std::vector<Checker*>::iterator I=Checkers.begin(), E=Checkers.end();
+       I!=E; ++I)
+    delete *I;
 }
 
 //===----------------------------------------------------------------------===//
@@ -1436,11 +1474,16 @@
 
   // If we reach here we have processed all of the arguments.  Evaluate
   // the callee expression.
-  
-  NodeSet DstTmp;    
+  NodeSet DstTmp;
   Expr* Callee = CE->getCallee()->IgnoreParens();
-
-  Visit(Callee, Pred, DstTmp);
+  
+  { // Enter new scope to make the lifetime of 'DstTmp2' bounded.
+    NodeSet DstTmp2;
+    Visit(Callee, Pred, DstTmp2);
+    
+    // Perform the previsit of the CallExpr, storing the results in DstTmp.
+    CheckerVisit(CE, DstTmp, DstTmp2, true);
+  }
   
   // Finally, evaluate the function call.
   for (NodeSet::iterator DI = DstTmp.begin(), DE = DstTmp.end(); DI!=DE; ++DI) {