]> granicus.if.org Git - clang/commitdiff
Hooked up initial reference-count checks to the BugReporter interface.
authorTed Kremenek <kremenek@apple.com>
Wed, 9 Apr 2008 23:49:11 +0000 (23:49 +0000)
committerTed Kremenek <kremenek@apple.com>
Wed, 9 Apr 2008 23:49:11 +0000 (23:49 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@49455 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Analysis/CFRefCount.cpp

index 501a3f5a05663a27e66d36cd64c41721eb5cc6db..2a7886ba046522aacb1cc694854e1d2f3549ea50 100644 (file)
 
 using namespace clang;
 
+//===----------------------------------------------------------------------===//
+// Symbolic Evaluation of Reference Counting Logic
+//===----------------------------------------------------------------------===//
+
 namespace {  
   enum ArgEffect { IncRef, DecRef, DoNothing };
   typedef std::vector<ArgEffect> ArgEffects;
@@ -382,13 +386,63 @@ CFRefSummaryManager::getCFSummaryGetRule(FunctionTypeProto* FT) {
   return getPersistentSummary(getArgEffects(), RetEffect::MakeNotOwned());
 }
 
+//===----------------------------------------------------------------------===//
+// 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);
+  };
+  
+} // end anonymous namespace
+
 //===----------------------------------------------------------------------===//
 // Transfer functions.
 //===----------------------------------------------------------------------===//
 
 namespace {
   
-class RefVal {
+class VISIBILITY_HIDDEN RefVal {
   unsigned Data;
   
   RefVal(unsigned K, unsigned D) : Data((D << 3) | K) {
@@ -455,7 +509,7 @@ void RefVal::print(std::ostream& Out) const {
   }
 }
   
-class CFRefCount : public GRSimpleVals {
+class VISIBILITY_HIDDEN CFRefCount : public GRSimpleVals {
   
   // Type definitions.
   
@@ -502,6 +556,8 @@ class CFRefCount : public GRSimpleVals {
 public:
   CFRefCount() {}
   virtual ~CFRefCount() {}
+  
+  virtual void RegisterChecks(GRExprEngine& Eng);
  
   virtual ValueState::CheckerStatePrinter* getCheckerStatePrinter() {
     return &Printer;
@@ -520,15 +576,22 @@ public:
   typedef UseAfterReleasesTy::iterator use_after_iterator;  
   typedef ReleasesNotOwnedTy::iterator bad_release_iterator;
   
-  use_after_iterator begin_use_after() { return UseAfterReleases.begin(); }
-  use_after_iterator end_use_after() { return UseAfterReleases.end(); }
+  use_after_iterator use_after_begin() { return UseAfterReleases.begin(); }
+  use_after_iterator use_after_end() { return UseAfterReleases.end(); }
   
-  bad_release_iterator begin_bad_release() { return ReleasesNotOwned.begin(); }
-  bad_release_iterator end_bad_release() { return ReleasesNotOwned.end(); }
+  bad_release_iterator bad_release_begin() { return ReleasesNotOwned.begin(); }
+  bad_release_iterator bad_release_end() { return ReleasesNotOwned.end(); }
 };
 
 } // end anonymous namespace
 
+void CFRefCount::RegisterChecks(GRExprEngine& Eng) {
+  GRSimpleVals::RegisterChecks(Eng);
+  Eng.Register(new UseAfterRelease(*this));
+  Eng.Register(new BadRelease(*this));
+}
+
+
 void CFRefCount::BindingsPrinter::PrintCheckerState(std::ostream& Out,
                                                     void* State, const char* nl,
                                                     const char* sep) {
@@ -787,36 +850,28 @@ CFRefCount::RefBindings CFRefCount::Update(RefBindings B, SymbolID sym,
 
 
 //===----------------------------------------------------------------------===//
-// Bug Descriptions.
+// Error reporting.
 //===----------------------------------------------------------------------===//
 
-namespace {
-  
-class VISIBILITY_HIDDEN UseAfterRelease : public BugType {
+void UseAfterRelease::EmitWarnings(BugReporter& BR) {
 
-public:
-  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.";
-  }
-};
-  
-class VISIBILITY_HIDDEN BadRelease : public BugType {
-  
-public:
-  virtual const char* getName() const {
-    return "(CoreFoundation) release of non-owned object";
-  }
-  virtual const char* getDescription() const {
-    return "Incorrect decrement of reference count of CoreFoundation object:\n"
-           "The object is not owned at this point by the caller.";
+  for (CFRefCount::use_after_iterator I = TF.use_after_begin(),
+        E = TF.use_after_end(); I != E; ++I) {
+    
+    BugReport report(*this);
+    BR.EmitPathWarning(report, *I);    
   }
-};
+}
+
+void BadRelease::EmitWarnings(BugReporter& BR) {
   
-} // end anonymous namespace
+  for (CFRefCount::bad_release_iterator I = TF.bad_release_begin(),
+       E = TF.bad_release_end(); I != E; ++I) {
+    
+    BugReport report(*this);
+    BR.EmitPathWarning(report, *I);    
+  }  
+}
 
 //===----------------------------------------------------------------------===//
 // Driver for the CFRefCount Checker.