[cfe-commits] r49889 - in /cfe/trunk: include/clang/Analysis/PathSensitive/BugReporter.h lib/Analysis/BugReporter.cpp lib/Analysis/CFRefCount.cpp

Ted Kremenek kremenek at apple.com
Thu Apr 17 20:39:05 PDT 2008


Author: kremenek
Date: Thu Apr 17 22:39:05 2008
New Revision: 49889

URL: http://llvm.org/viewvc/llvm-project?rev=49889&view=rev
Log:
BugReport::VisitNode now takes BugReporter& instead of ASTContext&.

Shuffled around code in CFRefCount to better pair classes with implementation,
and started adding subclasses of RangedBugReport to handle better diagnostics
for reference count bugs.

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

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

==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/BugReporter.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/BugReporter.h Thu Apr 17 22:39:05 2008
@@ -74,7 +74,7 @@
   virtual PathDiagnosticPiece* VisitNode(ExplodedNode<ValueState>* N,
                                          ExplodedNode<ValueState>* PrevN,
                                          ExplodedGraph<ValueState>& G,
-                                         ASTContext& Ctx);
+                                         BugReporter& BR);
 };
   
 class RangedBugReport : public BugReport {

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

==============================================================================
--- cfe/trunk/lib/Analysis/BugReporter.cpp (original)
+++ cfe/trunk/lib/Analysis/BugReporter.cpp Thu Apr 17 22:39:05 2008
@@ -135,7 +135,7 @@
 PathDiagnosticPiece* BugReport::VisitNode(ExplodedNode<ValueState>* N,
                                           ExplodedNode<ValueState>* PrevN,
                                           ExplodedGraph<ValueState>& G,
-                                          ASTContext& Ctx) {
+                                          BugReporter& BR) {
   return NULL;
 }
 
@@ -352,7 +352,7 @@
       }
     }
     else
-      if (PathDiagnosticPiece* piece = R.VisitNode(N, NextNode, *GTrim, Ctx))
+      if (PathDiagnosticPiece* piece = R.VisitNode(N, NextNode, *GTrim, *this))
         PD.push_front(piece);
   }
 }

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

==============================================================================
--- cfe/trunk/lib/Analysis/CFRefCount.cpp (original)
+++ cfe/trunk/lib/Analysis/CFRefCount.cpp Thu Apr 17 22:39:05 2008
@@ -414,72 +414,6 @@
 }
 
 //===----------------------------------------------------------------------===//
-// Bug Descriptions.
-//===----------------------------------------------------------------------===//
-
-namespace {
-  
-  class CFRefCount;
-  
-  class VISIBILITY_HIDDEN CFRefBug : public BugType {
-  protected:
-    CFRefCount& TF;
-    
-  public:
-    CFRefBug(CFRefCount& tf) : TF(tf) {}
-  };
-  
-  class VISIBILITY_HIDDEN UseAfterRelease : public CFRefBug {
-  public:
-    UseAfterRelease(CFRefCount& tf) : CFRefBug(tf) {}
-    
-    virtual const char* getName() const {
-      return "(CoreFoundation) use-after-release";
-    }
-    virtual const char* getDescription() const {
-      return "(CoreFoundation) Reference-counted object is used"
-             " after it is released.";
-    }
-    
-    virtual void EmitWarnings(BugReporter& BR);
-    
-  };
-  
-  class VISIBILITY_HIDDEN BadRelease : public CFRefBug {
-  public:
-    BadRelease(CFRefCount& tf) : CFRefBug(tf) {}
-    
-    virtual const char* getName() const {
-      return "(CoreFoundation) release of non-owned object";
-    }
-    virtual const char* getDescription() const {
-      return "Incorrect decrement of the reference count of a "
-             "CoreFoundation object:\n"
-             "The object is not owned at this point by the caller.";
-    }
-    
-    virtual void EmitWarnings(BugReporter& BR);
-  };
-  
-  class VISIBILITY_HIDDEN Leak : public CFRefBug {
-  public:
-    Leak(CFRefCount& tf) : CFRefBug(tf) {}
-    
-    virtual const char* getName() const {
-      return "(CoreFoundation) Memory Leak";
-    }
-    
-    virtual const char* getDescription() const {
-      return "The CoreFoundation object has an excessive reference count and"
-             "\nis leaked after this statement.";
-    }
-    
-    virtual void EmitWarnings(BugReporter& BR);
-  };
-  
-} // end anonymous namespace
-
-//===----------------------------------------------------------------------===//
 // Reference-counting logic (typestate + counts).
 //===----------------------------------------------------------------------===//
 
@@ -634,25 +568,27 @@
 //===----------------------------------------------------------------------===//
 
 class VISIBILITY_HIDDEN CFRefCount : public GRSimpleVals {
-  
+public:
   // Type definitions.
   
   typedef llvm::ImmutableMap<SymbolID, RefVal> RefBindings;
   typedef RefBindings::Factory RefBFactoryTy;
   
-  typedef llvm::DenseMap<GRExprEngine::NodeTy*,Expr*> UseAfterReleasesTy;
-  typedef llvm::DenseMap<GRExprEngine::NodeTy*,Expr*> ReleasesNotOwnedTy;
-
-  typedef llvm::SmallVector<std::pair<SymbolID, ExplodedNode<ValueState>*>, 2>
-          LeaksTy;
-  
+  typedef llvm::DenseMap<GRExprEngine::NodeTy*,std::pair<Expr*, SymbolID> >
+          ReleasesNotOwnedTy;
   
+  typedef ReleasesNotOwnedTy UseAfterReleasesTy;
+    
+  typedef llvm::DenseMap<GRExprEngine::NodeTy*, std::vector<SymbolID>*>
+          LeaksTy;
+
   class BindingsPrinter : public ValueState::CheckerStatePrinter {
   public:
     virtual void PrintCheckerState(std::ostream& Out, void* State,
                                    const char* nl, const char* sep);
   };
-  
+
+private:
   // Instance variables.
   
   CFRefSummaryManager Summaries;
@@ -667,12 +603,14 @@
   Selector RetainSelector;
   Selector ReleaseSelector;
 
-  // Private methods.
-
+public:
+  
   static RefBindings GetRefBindings(ValueState& StImpl) {
     return RefBindings((RefBindings::TreeTy*) StImpl.CheckerState);
   }
 
+private:
+  
   static void SetRefBindings(ValueState& StImpl, RefBindings B) {
     StImpl.CheckerState = B.getRoot();
   }
@@ -689,7 +627,7 @@
                            Expr* NodeExpr, Expr* ErrorExpr,                        
                            ExplodedNode<ValueState>* Pred,
                            ValueState* St,
-                           RefVal::Kind hasErr);
+                           RefVal::Kind hasErr, SymbolID Sym);
   
   ValueState* HandleSymbolDeath(ValueStateManager& VMgr, ValueState* St,
                                 SymbolID sid, RefVal V, bool& hasLeak);
@@ -704,7 +642,10 @@
       RetainSelector(GetUnarySelector("retain", Ctx)),
       ReleaseSelector(GetUnarySelector("release", Ctx)) {}
   
-  virtual ~CFRefCount() {}
+  virtual ~CFRefCount() {
+    for (LeaksTy::iterator I = Leaks.begin(), E = Leaks.end(); I!=E; ++I)
+      delete I->second;
+  }
   
   virtual void RegisterChecks(GRExprEngine& Eng);
  
@@ -770,12 +711,7 @@
 
 } // end anonymous namespace
 
-void CFRefCount::RegisterChecks(GRExprEngine& Eng) {
-  GRSimpleVals::RegisterChecks(Eng);
-  Eng.Register(new UseAfterRelease(*this));
-  Eng.Register(new BadRelease(*this));
-  Eng.Register(new Leak(*this));
-}
+
 
 
 void CFRefCount::BindingsPrinter::PrintCheckerState(std::ostream& Out,
@@ -806,7 +742,7 @@
                                      Expr* NodeExpr, Expr* ErrorExpr,                        
                                      ExplodedNode<ValueState>* Pred,
                                      ValueState* St,
-                                     RefVal::Kind hasErr) {
+                                     RefVal::Kind hasErr, SymbolID Sym) {
   Builder.BuildSinks = true;
   GRExprEngine::NodeTy* N  = Builder.MakeNode(Dst, NodeExpr, Pred, St);
 
@@ -815,11 +751,11 @@
   switch (hasErr) {
     default: assert(false);
     case RefVal::ErrorUseAfterRelease:
-      UseAfterReleases[N] = ErrorExpr;
+      UseAfterReleases[N] = std::make_pair(ErrorExpr, Sym);
       break;
       
     case RefVal::ErrorReleaseNotOwned:
-      ReleasesNotOwned[N] = ErrorExpr;
+      ReleasesNotOwned[N] = std::make_pair(ErrorExpr, Sym);
       break;
   }
 }
@@ -856,6 +792,7 @@
   unsigned idx = 0;
   
   Expr* ErrorExpr = NULL;
+  SymbolID ErrorSym = 0;                                        
   
   for (CallExpr::arg_iterator I = CE->arg_begin(), E = CE->arg_end();
         I != E; ++I, ++idx) {
@@ -872,6 +809,7 @@
         
         if (hasErr) {
           ErrorExpr = *I;
+          ErrorSym = T->getValue().first;
           break;
         }
       }
@@ -887,7 +825,8 @@
   St = StateMgr.getPersistentState(StVals);
     
   if (hasErr) {
-    ProcessNonLeakError(Dst, Builder, CE, ErrorExpr, Pred, St, hasErr);
+    ProcessNonLeakError(Dst, Builder, CE, ErrorExpr, Pred, St,
+                        hasErr, ErrorSym);
     return;
   }
     
@@ -1031,7 +970,7 @@
   // Create an error node if it exists.
   
   if (hasErr)
-    ProcessNonLeakError(Dst, Builder, ME, Receiver, Pred, St, hasErr);
+    ProcessNonLeakError(Dst, Builder, ME, Receiver, Pred, St, hasErr, Sym);
   else
     Builder.MakeNode(Dst, ME, Pred, St);
 
@@ -1124,11 +1063,14 @@
     if (hasLeak) Leaked.push_back((*I).first);
   }
       
-  ExplodedNode<ValueState>* N = Builder.MakeNode(St);
+  ExplodedNode<ValueState>* N = Builder.MakeNode(St);  
+  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)
-    Leaks.push_back(std::make_pair(*I, N));
+    (*LeaksAtNode).push_back(*I);
 }
 
  // Return statements.
@@ -1274,13 +1216,123 @@
 // Error reporting.
 //===----------------------------------------------------------------------===//
 
+namespace {
+  
+  //===-------------===//
+  // Bug Descriptions. //
+  //===-------------===//  
+  
+  class VISIBILITY_HIDDEN CFRefBug : public BugType {
+  protected:
+    CFRefCount& TF;
+    
+  public:
+    CFRefBug(CFRefCount& tf) : TF(tf) {}
+  };
+  
+  class VISIBILITY_HIDDEN UseAfterRelease : public CFRefBug {
+  public:
+    UseAfterRelease(CFRefCount& tf) : CFRefBug(tf) {}
+    
+    virtual const char* getName() const {
+      return "(CoreFoundation) use-after-release";
+    }
+    virtual const char* getDescription() const {
+      return "(CoreFoundation) Reference-counted object is used"
+      " after it is released.";
+    }
+    
+    virtual void EmitWarnings(BugReporter& BR);
+    
+  };
+  
+  class VISIBILITY_HIDDEN BadRelease : public CFRefBug {
+  public:
+    BadRelease(CFRefCount& tf) : CFRefBug(tf) {}
+    
+    virtual const char* getName() const {
+      return "(CoreFoundation) release of non-owned object";
+    }
+    virtual const char* getDescription() const {
+      return "Incorrect decrement of the reference count of a "
+      "CoreFoundation object:\n"
+      "The object is not owned at this point by the caller.";
+    }
+    
+    virtual void EmitWarnings(BugReporter& BR);
+  };
+  
+  class VISIBILITY_HIDDEN Leak : public CFRefBug {
+  public:
+    Leak(CFRefCount& tf) : CFRefBug(tf) {}
+    
+    virtual const char* getName() const {
+      return "(CoreFoundation) Memory Leak";
+    }
+    
+    virtual const char* getDescription() const {
+      return "The CoreFoundation object has an excessive reference count and"
+      "\nis leaked after this statement.";
+    }
+    
+    virtual void EmitWarnings(BugReporter& BR);
+  };
+  
+  //===---------===//
+  // Bug Reports.  //
+  //===---------===//
+  
+  class VISIBILITY_HIDDEN CFRefReport : public RangedBugReport {
+    SymbolID Sym;
+  public:
+    CFRefReport(const BugType& D, ExplodedNode<ValueState> *n, SymbolID sym)
+      : RangedBugReport(D, n), Sym(sym) {}
+        
+    virtual ~CFRefReport() {}
+    
+    
+    virtual PathDiagnosticPiece* VisitNode(ExplodedNode<ValueState>* N,
+                                           ExplodedNode<ValueState>* PrevN,
+                                           ExplodedGraph<ValueState>& G,
+                                           BugReporter& BR);
+  };
+  
+  
+} // end anonymous namespace
+
+void CFRefCount::RegisterChecks(GRExprEngine& Eng) {
+  GRSimpleVals::RegisterChecks(Eng);
+  Eng.Register(new UseAfterRelease(*this));
+  Eng.Register(new BadRelease(*this));
+  Eng.Register(new Leak(*this));
+}
+
+PathDiagnosticPiece* CFRefReport::VisitNode(ExplodedNode<ValueState>* N,
+                                            ExplodedNode<ValueState>* PrevN,
+                                            ExplodedGraph<ValueState>& G,
+                                            BugReporter& BR) {
+
+  // Check if the type state has changed.
+  
+  ValueState* PrevSt = PrevN->getState();
+  ValueState* CurrSt = N->getState();
+  
+  CFRefCount::RefBindings PrevB = CFRefCount::GetRefBindings(*PrevSt);
+  CFRefCount::RefBindings CurrB = CFRefCount::GetRefBindings(*CurrSt);
+  
+  
+  
+  
+  return NULL;
+}
+
 void UseAfterRelease::EmitWarnings(BugReporter& BR) {
 
   for (CFRefCount::use_after_iterator I = TF.use_after_begin(),
         E = TF.use_after_end(); I != E; ++I) {
     
-    RangedBugReport report(*this, I->first);
-    report.addRange(I->second->getSourceRange());    
+    CFRefReport report(*this, I->first, I->second.second);
+    report.addRange(I->second.first->getSourceRange());    
     BR.EmitWarning(report);    
   }
 }
@@ -1290,10 +1342,9 @@
   for (CFRefCount::bad_release_iterator I = TF.bad_release_begin(),
        E = TF.bad_release_end(); I != E; ++I) {
     
-    RangedBugReport report(*this, I->first);
-    report.addRange(I->second->getSourceRange());    
-    BR.EmitWarning(report); 
-
+    CFRefReport report(*this, I->first, I->second.second);
+    report.addRange(I->second.first->getSourceRange());    
+    BR.EmitWarning(report);    
   }  
 }
 
@@ -1302,8 +1353,13 @@
   for (CFRefCount::leaks_iterator I = TF.leaks_begin(),
        E = TF.leaks_end(); I != E; ++I) {
     
-    BugReport report(*this, I->second);
-    BR.EmitWarning(report);     
+    std::vector<SymbolID>& SymV = *(I->second);
+    unsigned n = SymV.size();
+    
+    for (unsigned i = 0; i < n; ++i) {
+      CFRefReport report(*this, I->first, SymV[i]);
+      BR.EmitWarning(report);
+    }
   }  
 }
 





More information about the cfe-commits mailing list