[cfe-commits] r138538 - /cfe/trunk/lib/StaticAnalyzer/Core/CFRefCount.cpp

Jordy Rose jediknil at belkadan.com
Wed Aug 24 18:14:38 PDT 2011


Author: jrose
Date: Wed Aug 24 20:14:38 2011
New Revision: 138538

URL: http://llvm.org/viewvc/llvm-project?rev=138538&view=rev
Log:
[analyzer] Move the leak bugs from CFRefCount to RetainReleaseChecker, with a level of indirection to handle GC vs. non-GC.

Modified:
    cfe/trunk/lib/StaticAnalyzer/Core/CFRefCount.cpp

Modified: cfe/trunk/lib/StaticAnalyzer/Core/CFRefCount.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/CFRefCount.cpp?rev=138538&r1=138537&r2=138538&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/CFRefCount.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/CFRefCount.cpp Wed Aug 24 20:14:38 2011
@@ -1640,12 +1640,9 @@
   const LangOptions&   LOpts;
   const bool GCEnabled;
 
-  BugType *leakWithinFunction, *leakAtReturn;
-
 public:
   CFRefCount(ASTContext &Ctx, bool gcenabled, const LangOptions& lopts)
-    : LOpts(lopts), GCEnabled(gcenabled),
-      leakWithinFunction(0), leakAtReturn(0) {}
+    : LOpts(lopts), GCEnabled(gcenabled) {}
 
   void RegisterChecks(ExprEngine &Eng);
 
@@ -1811,7 +1808,10 @@
     const bool isReturn;
   protected:
     Leak(StringRef name, bool isRet)
-    : CFRefBug(name), isReturn(isRet) {}
+    : CFRefBug(name), isReturn(isRet) {
+      // Leaks should not be reported if they are post-dominated by a sink.
+      setSuppressOnSink(true);
+    }
   public:
 
     const char *getDescription() const { return ""; }
@@ -2619,6 +2619,8 @@
   mutable llvm::OwningPtr<CFRefBug> useAfterRelease, releaseNotOwned;
   mutable llvm::OwningPtr<CFRefBug> deallocGC, deallocNotOwned;
   mutable llvm::OwningPtr<CFRefBug> overAutorelease, returnNotOwnedForOwned;
+  mutable llvm::OwningPtr<CFRefBug> leakWithinFunction, leakAtReturn;
+  mutable llvm::OwningPtr<CFRefBug> leakWithinFunctionGC, leakAtReturnGC;
 
   typedef llvm::DenseMap<SymbolRef, const SimpleProgramPointTag *> SymbolTagMap;
 
@@ -2706,6 +2708,49 @@
     return isGCEnabled() || Ctx.getLangOptions().ObjCAutoRefCount;
   }
 
+  CFRefBug *getLeakWithinFunctionBug(ASTContext &Ctx) const {
+    if (isGCEnabled()) {
+      if (!leakWithinFunctionGC)
+        leakWithinFunctionGC.reset(new LeakWithinFunction("Leak of object when "
+                                                          "using garbage "
+                                                          "collection"));
+      return &*leakWithinFunctionGC;
+    } else {
+      if (!leakWithinFunction) {
+        if (Ctx.getLangOptions().getGCMode() == LangOptions::HybridGC) {
+          leakWithinFunction.reset(new LeakWithinFunction("Leak of object when "
+                                                          "not using garbage "
+                                                          "collection (GC) in "
+                                                          "dual GC/non-GC "
+                                                          "code"));
+        } else {
+          leakWithinFunction.reset(new LeakWithinFunction("Leak"));
+        }
+      }
+      return &*leakWithinFunction;
+    }
+  }
+
+  CFRefBug *getLeakAtReturnBug(ASTContext &Ctx) const {
+    if (isGCEnabled()) {
+      if (!leakAtReturnGC)
+        leakAtReturnGC.reset(new LeakAtReturn("Leak of returned object when "
+                                              "using garbage collection"));
+      return &*leakAtReturnGC;
+    } else {
+      if (!leakAtReturn) {
+        if (Ctx.getLangOptions().getGCMode() == LangOptions::HybridGC) {
+          leakAtReturn.reset(new LeakAtReturn("Leak of returned object when "
+                                              "not using garbage collection "
+                                              "(GC) in dual GC/non-GC code"));
+        } else {
+          leakAtReturn.reset(new LeakAtReturn("Leak of returned object"));
+        }
+      }
+      return &*leakAtReturn;
+    }
+  }
+
   RetainSummaryManager &getSummaryManager(ASTContext &Ctx) const {
     if (isGCEnabled()) {
       if (!SummariesGC) {
@@ -3533,11 +3578,9 @@
         ExplodedNode *N = Builder.generateNode(S, state, Pred,
                                                &ReturnOwnLeakTag);
         if (N) {
-          // FIXME: This goes away once this bug type moves to the checker.
-          CFRefCount &TF = static_cast<CFRefCount&>(C.getEngine().getTF());
+          ASTContext &Ctx = C.getASTContext();
           CFRefReport *report =
-            new CFRefLeakReport(*static_cast<CFRefBug*>(TF.leakAtReturn),
-                                C.getASTContext().getLangOptions(),
+            new CFRefLeakReport(*getLeakAtReturnBug(Ctx), Ctx.getLangOptions(),
                                 isGCEnabled(), SummaryLog, N, Sym, 
                                 C.getEngine());
           C.EmitReport(report);
@@ -3673,13 +3716,12 @@
     for (SmallVectorImpl<SymbolRef>::iterator
          I = Leaked.begin(), E = Leaked.end(); I != E; ++I) {
 
-      // FIXME: This goes away once these bug types move to the checker.
-      CFRefCount &TF = static_cast<CFRefCount&>(Eng.getTF());
-      CFRefBug *BT = static_cast<CFRefBug*>(Pred ? TF.leakWithinFunction
-                                                 : TF.leakAtReturn);
+      ASTContext &Ctx = Eng.getContext();
+      CFRefBug *BT = Pred ? getLeakWithinFunctionBug(Ctx)
+                          : getLeakAtReturnBug(Ctx);
       assert(BT && "BugType not initialized.");
 
-      const LangOptions &LOpts = Eng.getContext().getLangOptions();
+      const LangOptions &LOpts = Ctx.getLangOptions();
       CFRefLeakReport *report = new CFRefLeakReport(*BT, LOpts, isGCEnabled(), 
                                                     SummaryLog, N, *I, Eng);
       Eng.getBugReporter().EmitReport(report);
@@ -3783,42 +3825,6 @@
 //===----------------------------------------------------------------------===//
 
 void CFRefCount::RegisterChecks(ExprEngine& Eng) {
-  BugReporter &BR = Eng.getBugReporter();
-
-  // First register "return" leaks.
-  const char *name = 0;
-
-  if (GCEnabled)
-    name = "Leak of returned object when using garbage collection";
-  else if (getLangOptions().getGCMode() == LangOptions::HybridGC)
-    name = "Leak of returned object when not using garbage collection (GC) in "
-    "dual GC/non-GC code";
-  else {
-    assert(getLangOptions().getGCMode() == LangOptions::NonGC);
-    name = "Leak of returned object";
-  }
-
-  // Leaks should not be reported if they are post-dominated by a sink.
-  leakAtReturn = new LeakAtReturn(name);
-  leakAtReturn->setSuppressOnSink(true);
-  BR.Register(leakAtReturn);
-
-  // Second, register leaks within a function/method.
-  if (GCEnabled)
-    name = "Leak of object when using garbage collection";
-  else if (getLangOptions().getGCMode() == LangOptions::HybridGC)
-    name = "Leak of object when not using garbage collection (GC) in "
-    "dual GC/non-GC code";
-  else {
-    assert(getLangOptions().getGCMode() == LangOptions::NonGC);
-    name = "Leak";
-  }
-
-  // Leaks should not be reported if they are post-dominated by sinks.
-  leakWithinFunction = new LeakWithinFunction(name);
-  leakWithinFunction->setSuppressOnSink(true);
-  BR.Register(leakWithinFunction);
-
   // Register the RetainReleaseChecker with the ExprEngine object.
   // Functionality in CFRefCount will be migrated to RetainReleaseChecker
   // over time.





More information about the cfe-commits mailing list