[cfe-commits] r76794 - in /cfe/trunk: include/clang/Analysis/PathSensitive/GRExprEngine.h lib/Analysis/GRExprEngine.cpp

Ted Kremenek kremenek at apple.com
Wed Jul 22 14:43:51 PDT 2009


Author: kremenek
Date: Wed Jul 22 16:43:51 2009
New Revision: 76794

URL: http://llvm.org/viewvc/llvm-project?rev=76794&view=rev
Log:
Add support for registering 'Checker' objects with GRExprEngine.
Add a 'previsit' stage (that dispatches to registered Checkers) when evaluating the effects of CallExprs.

Modified:
    cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h
    cfe/trunk/lib/Analysis/GRExprEngine.cpp

Modified: cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h?rev=76794&r1=76793&r2=76794&view=diff

==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h Wed Jul 22 16:43:51 2009
@@ -29,6 +29,7 @@
   class PathDiagnosticClient;
   class Diagnostic;
   class ObjCForCollectionStmt;
+  class Checker;
 
 class GRExprEngine {  
 public:
@@ -88,6 +89,7 @@
   Selector RaiseSel;
   
   llvm::OwningPtr<GRSimpleAPICheck> BatchAuditor;
+  std::vector<Checker*> Checkers;
 
   /// PurgeDead - Remove dead bindings before processing a statement.
   bool PurgeDead;
@@ -261,6 +263,10 @@
 
   void RegisterInternalChecks();
   
+  void registerCheck(Checker *check) {
+    Checkers.push_back(check);
+  }
+  
   bool isRetStackAddr(const NodeTy* N) const {
     return N->isSink() && RetsStackAddr.count(const_cast<NodeTy*>(N)) != 0;
   }
@@ -491,7 +497,10 @@
                    ProgramPoint::Kind K = ProgramPoint::PostStmtKind,
                    const void *tag = 0);
 protected:
-    
+  /// CheckerVisit - Dispatcher for performing checker-specific logic
+  ///  at specific statements.
+  void CheckerVisit(Stmt *S, NodeSet &Dst, NodeSet &Src, bool isPrevisit);
+  
   /// Visit - Transfer function logic for all statements.  Dispatches to
   ///  other functions that handle specific kinds of statements.
   void Visit(Stmt* S, NodeTy* Pred, NodeSet& Dst);

Modified: cfe/trunk/lib/Analysis/GRExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/GRExprEngine.cpp?rev=76794&r1=76793&r2=76794&view=diff

==============================================================================
--- cfe/trunk/lib/Analysis/GRExprEngine.cpp (original)
+++ cfe/trunk/lib/Analysis/GRExprEngine.cpp Wed Jul 22 16:43:51 2009
@@ -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) {





More information about the cfe-commits mailing list