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

Ted Kremenek kremenek at apple.com
Fri Jul 11 11:37:32 PDT 2008


Author: kremenek
Date: Fri Jul 11 13:37:32 2008
New Revision: 53464

URL: http://llvm.org/viewvc/llvm-project?rev=53464&view=rev
Log:
Refactored auditor interface within GRExprEngine and GRCoreEngine to use a "batch auditor" to dispatch to specialized auditors instead of having a separate vector for each audited Expr*.  This not only provides a much cleaner implementation, but also allows us to install auditors for any expression.

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

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

==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/GRCoreEngine.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/GRCoreEngine.h Fri Jul 11 13:37:32 2008
@@ -165,36 +165,26 @@
   
 template<typename STATE>
 class GRStmtNodeBuilder  {
+public:
   typedef STATE                   StateTy;
   typedef ExplodedNode<StateTy>   NodeTy;
   
+private:
   GRStmtNodeBuilderImpl& NB;
-  const StateTy* CleanedState;
-  
-  GRAuditor<StateTy> **CallExprAuditBeg, **CallExprAuditEnd;
-  GRAuditor<StateTy> **ObjCMsgExprAuditBeg, **ObjCMsgExprAuditEnd;
+  const StateTy* CleanedState;  
+  GRAuditor<StateTy>* Auditor;
   
 public:
   GRStmtNodeBuilder(GRStmtNodeBuilderImpl& nb) : NB(nb),
-    CallExprAuditBeg(0), CallExprAuditEnd(0),
-    ObjCMsgExprAuditBeg(0), ObjCMsgExprAuditEnd(0),
-    PurgingDeadSymbols(false),
+    Auditor(0), PurgingDeadSymbols(false),
     BuildSinks(false), HasGeneratedNode(false) {
       
     CleanedState = getLastNode()->getState();
   }
-  
-  void setObjCMsgExprAuditors(GRAuditor<StateTy> **B,
-                              GRAuditor<StateTy> **E) {
-    ObjCMsgExprAuditBeg = B;
-    ObjCMsgExprAuditEnd = E;
+
+  void setAuditor(GRAuditor<StateTy>* A) {
+    Auditor = A;
   }
-  
-  void setCallExprAuditors(GRAuditor<StateTy> **B,
-                           GRAuditor<StateTy> **E) {
-    CallExprAuditBeg = B;
-    CallExprAuditEnd = E;
-  }  
     
   NodeTy* getLastNode() const {
     return static_cast<NodeTy*>(NB.getLastNode());
@@ -241,23 +231,9 @@
                    NodeTy* Pred, const StateTy* St) {    
     
     const StateTy* PredState = GetState(Pred);
-    
-    GRAuditor<StateTy> **AB = NULL, **AE = NULL;
-    
-    switch (S->getStmtClass()) {
-      default: break;
-      case Stmt::CallExprClass:
-        AB = CallExprAuditBeg;
-        AE = CallExprAuditEnd;
-        break;
-      case Stmt::ObjCMessageExprClass:
-        AB = ObjCMsgExprAuditBeg;
-        AE = ObjCMsgExprAuditEnd;
-        break;
-    }
-    
+        
     // If the state hasn't changed, don't generate a new node.
-    if (!BuildSinks && St == PredState && AB == NULL) {
+    if (!BuildSinks && St == PredState && Auditor == 0) {
       Dst.Add(Pred);
       return NULL;
     }
@@ -268,9 +244,8 @@
       if (BuildSinks)
         N->markAsSink();
       else {
-        for ( ; AB != AE; ++AB)
-          if ((*AB)->Audit(N))
-            N->markAsSink();
+        if (Auditor && Auditor->Audit(N))
+          N->markAsSink();
         
         Dst.Add(N);
       }

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=53464&r1=53463&r2=53464&view=diff

==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h Fri Jul 11 13:37:32 2008
@@ -98,10 +98,7 @@
   Selector* NSExceptionInstanceRaiseSelectors;
   Selector RaiseSel;
   
-  typedef llvm::SmallVector<GRSimpleAPICheck*,2> SimpleChecksTy;
-  
-  SimpleChecksTy CallChecks;
-  SimpleChecksTy MsgExprChecks;
+  llvm::OwningPtr<GRSimpleAPICheck> BatchAuditor;
   
 public:
   typedef llvm::SmallPtrSet<NodeTy*,2> UndefBranchesTy;  
@@ -347,21 +344,7 @@
     return UndefReceivers.end();
   }
   
-  typedef SimpleChecksTy::iterator simple_checks_iterator;
-  
-  simple_checks_iterator call_auditors_begin() { return CallChecks.begin(); }
-  simple_checks_iterator call_auditors_end() { return CallChecks.end(); }
-  
-  simple_checks_iterator msgexpr_auditors_begin() {
-    return MsgExprChecks.begin();
-  }
-  simple_checks_iterator msgexpr_auditors_end() {
-    return MsgExprChecks.end();
-  }
-  
-  void AddCallCheck(GRSimpleAPICheck* A);
-  
-  void AddObjCMessageExprCheck(GRSimpleAPICheck* A);
+  void AddCheck(GRSimpleAPICheck* A, Stmt::StmtClass C);
   
   /// ProcessStmt - Called by GRCoreEngine. Used to generate new successor
   ///  nodes by processing the 'effects' of a block-level statement.  

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

==============================================================================
--- cfe/trunk/lib/Analysis/GRExprEngine.cpp (original)
+++ cfe/trunk/lib/Analysis/GRExprEngine.cpp Fri Jul 11 13:37:32 2008
@@ -13,12 +13,13 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "clang/Analysis/PathSensitive/BasicStore.h"
 #include "clang/Analysis/PathSensitive/GRExprEngine.h"
 #include "clang/Analysis/PathSensitive/BugReporter.h"
 #include "clang/Basic/SourceManager.h"
 #include "llvm/Support/Streams.h"
-
-#include "clang/Analysis/PathSensitive/BasicStore.h"
+#include "llvm/ADT/ImmutableList.h"
+#include "llvm/Support/Compiler.h"
 
 #ifndef NDEBUG
 #include "llvm/Support/GraphWriter.h"
@@ -34,6 +35,79 @@
 // Engine construction and deletion.
 //===----------------------------------------------------------------------===//
 
+namespace {
+
+class VISIBILITY_HIDDEN MappedBatchAuditor : public GRSimpleAPICheck {
+  typedef llvm::ImmutableList<GRSimpleAPICheck*> Checks;
+  typedef llvm::DenseMap<void*,Checks> MapTy;
+  
+  MapTy M;
+  Checks::Factory F;
+
+public:
+  MappedBatchAuditor(llvm::BumpPtrAllocator& Alloc) : F(Alloc) {}
+  
+  virtual ~MappedBatchAuditor() {
+    llvm::DenseSet<GRSimpleAPICheck*> AlreadyVisited;
+    
+    for (MapTy::iterator MI = M.begin(), ME = M.end(); MI != ME; ++MI)
+      for (Checks::iterator I=MI->second.begin(), E=MI->second.end(); I!=E;++I){
+
+        GRSimpleAPICheck* check = *I;
+        
+        if (AlreadyVisited.count(check))
+          continue;
+        
+        AlreadyVisited.insert(check);
+        delete check;
+      }
+  }
+
+  void AddCheck(GRSimpleAPICheck* A, Stmt::StmtClass C) {
+    assert (A && "Check cannot be null.");
+    void* key = reinterpret_cast<void*>((uintptr_t) C);
+    MapTy::iterator I = M.find(key);
+    M[key] = F.Concat(A, I == M.end() ? F.GetEmptyList() : I->second);
+  }
+  
+  virtual void EmitWarnings(BugReporter& BR) {
+    llvm::DenseSet<GRSimpleAPICheck*> AlreadyVisited;
+    
+    for (MapTy::iterator MI = M.begin(), ME = M.end(); MI != ME; ++MI)
+      for (Checks::iterator I=MI->second.begin(), E=MI->second.end(); I!=E;++I){
+        
+        GRSimpleAPICheck* check = *I;
+        
+        if (AlreadyVisited.count(check))
+          continue;
+        
+        check->EmitWarnings(BR);
+      }
+  }
+  
+  virtual bool Audit(NodeTy* N) {
+    Stmt* S = cast<PostStmt>(N->getLocation()).getStmt();
+    void* key = reinterpret_cast<void*>((uintptr_t) S->getStmtClass());
+    MapTy::iterator MI = M.find(key);
+
+    if (MI == M.end())
+      return false;
+    
+    bool isSink = false;
+    
+    for (Checks::iterator I=MI->second.begin(), E=MI->second.end(); I!=E; ++I)
+      isSink |= (*I)->Audit(N);
+
+    return isSink;    
+  }
+};
+
+} // end anonymous namespace
+
+//===----------------------------------------------------------------------===//
+// Engine construction and deletion.
+//===----------------------------------------------------------------------===//
+
 static inline Selector GetNullarySelector(const char* name, ASTContext& Ctx) {
   IdentifierInfo* II = &Ctx.Idents.get(name);
   return Ctx.Selectors.getSelector(0, &II);
@@ -58,14 +132,7 @@
 GRExprEngine::~GRExprEngine() {    
   for (BugTypeSet::iterator I = BugTypes.begin(), E = BugTypes.end(); I!=E; ++I)
     delete *I;
-    
-  for (SimpleChecksTy::iterator I = CallChecks.begin(), E = CallChecks.end();
-       I != E; ++I)
-    delete *I;
-  
-  for (SimpleChecksTy::iterator I=MsgExprChecks.begin(), E=MsgExprChecks.end();
-       I != E; ++I)
-    delete *I;  
+
   
   delete [] NSExceptionInstanceRaiseSelectors;
 }
@@ -104,16 +171,9 @@
     (*I)->EmitWarnings(BR);
   }
   
-  for (SimpleChecksTy::iterator I = CallChecks.begin(), E = CallChecks.end();
-       I != E; ++I) {
-    GRBugReporter BR(BRData, *this);
-    (*I)->EmitWarnings(BR);
-  }
-  
-  for (SimpleChecksTy::iterator I=MsgExprChecks.begin(), E=MsgExprChecks.end();
-       I != E; ++I) {
+  if (BatchAuditor) {
     GRBugReporter BR(BRData, *this);
-    (*I)->EmitWarnings(BR);
+    BatchAuditor->EmitWarnings(BR);
   }
 }
 
@@ -122,12 +182,11 @@
   TF->RegisterChecks(*this);
 }
 
-void GRExprEngine::AddCallCheck(GRSimpleAPICheck* A) {
-  CallChecks.push_back(A);
-}
-
-void GRExprEngine::AddObjCMessageExprCheck(GRSimpleAPICheck* A) {
-  MsgExprChecks.push_back(A);
+void GRExprEngine::AddCheck(GRSimpleAPICheck* A, Stmt::StmtClass C) {
+  if (!BatchAuditor)
+    BatchAuditor.reset(new MappedBatchAuditor(getGraph().getAllocator()));
+  
+  ((MappedBatchAuditor*) BatchAuditor.get())->AddCheck(A, C);
 }
 
 const ValueState* GRExprEngine::getInitialState() {
@@ -186,26 +245,14 @@
   CurrentStmt = S;
   
   // Set up our simple checks.
+  if (BatchAuditor)
+    Builder->setAuditor(BatchAuditor.get());
   
-  // FIXME: This can probably be installed directly in GRCoreEngine, obviating
-  //  the need to do a copy every time we hit a block-level statement.
-  
-  if (!MsgExprChecks.empty())
-    Builder->setObjCMsgExprAuditors((GRAuditor<ValueState>**) &MsgExprChecks[0],
-         (GRAuditor<ValueState>**) (&MsgExprChecks[0] + MsgExprChecks.size()));
-  
-  
-  if (!CallChecks.empty())
-    Builder->setCallExprAuditors((GRAuditor<ValueState>**) &CallChecks[0],
-         (GRAuditor<ValueState>**) (&CallChecks[0] + CallChecks.size()));
-  
-  // Create the cleaned state.
-  
+  // Create the cleaned state.  
   CleanedState = StateMgr.RemoveDeadBindings(EntryNode->getState(), CurrentStmt,
                                              Liveness, DeadSymbols);
   
   // Process any special transfer function for dead symbols.
-  
   NodeSet Tmp;
   
   if (DeadSymbols.empty())

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

==============================================================================
--- cfe/trunk/lib/Analysis/GRSimpleVals.cpp (original)
+++ cfe/trunk/lib/Analysis/GRSimpleVals.cpp Fri Jul 11 13:37:32 2008
@@ -354,11 +354,11 @@
   ASTContext& Ctx = Eng.getContext();
   ValueStateManager* VMgr = &Eng.getStateManager();
 
-  GRSimpleAPICheck* Check = CreateBasicObjCFoundationChecks(Ctx, VMgr);  
-  Eng.AddObjCMessageExprCheck(Check);
+  GRSimpleAPICheck* Check = CreateBasicObjCFoundationChecks(Ctx, VMgr);
+  Eng.AddCheck(Check, Stmt::ObjCMessageExprClass);
   
-  Check = CreateAuditCFNumberCreate(Ctx, VMgr);  
-  Eng.AddCallCheck(Check);
+  Check = CreateAuditCFNumberCreate(Ctx, VMgr);
+  Eng.AddCheck(Check, Stmt::CallExprClass);
   
 }
 





More information about the cfe-commits mailing list