]> granicus.if.org Git - clang/commitdiff
[analyzer] Move the RetainSummaryManager from CFRefCount to RetainReleaseChecker.
authorJordy Rose <jediknil@belkadan.com>
Thu, 25 Aug 2011 00:10:37 +0000 (00:10 +0000)
committerJordy Rose <jediknil@belkadan.com>
Thu, 25 Aug 2011 00:10:37 +0000 (00:10 +0000)
Because Checkers live for an entire translation unit, this persists summary caches across multiple code bodies and avoids repeated initialization (but probably at the cost of memory). This removes the last references from RetainReleaseChecker to CFRefCount.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@138529 91177308-0d34-0410-b5e6-96231b3b80d8

lib/StaticAnalyzer/Core/CFRefCount.cpp

index 3fa211bcb906468bdf07732a45b23b3c515828e5..79acd15c2c734bab72aa6e11384279b0bd1f6104 100644 (file)
@@ -1637,8 +1637,8 @@ public:
                        const char* sep);
   };
 
-  RetainSummaryManager Summaries;
   const LangOptions&   LOpts;
+  const bool GCEnabled;
 
   BugType *useAfterRelease, *releaseNotOwned;
   BugType *deallocGC, *deallocNotOwned;
@@ -1648,9 +1648,8 @@ public:
 
 public:
   CFRefCount(ASTContext &Ctx, bool gcenabled, const LangOptions& lopts)
-    : Summaries(Ctx, gcenabled, (bool)lopts.ObjCAutoRefCount),
-      LOpts(lopts), useAfterRelease(0), releaseNotOwned(0),
-      deallocGC(0), deallocNotOwned(0),
+    : LOpts(lopts), GCEnabled(gcenabled),
+      useAfterRelease(0), releaseNotOwned(0), deallocGC(0), deallocNotOwned(0),
       leakWithinFunction(0), leakAtReturn(0), overAutorelease(0),
       returnNotOwnedForOwned(0) {}
 
@@ -1659,9 +1658,6 @@ public:
   virtual void RegisterPrinters(std::vector<ProgramState::Printer*>& Printers) {
     Printers.push_back(new BindingsPrinter());
   }
-
-  bool isGCEnabled() const { return Summaries.isGCEnabled(); }
-  bool isARCorGCEnabled() const { return Summaries.isARCorGCEnabled(); }
   
   const LangOptions& getLangOptions() const { return LOpts; }
 
@@ -2632,6 +2628,9 @@ class RetainReleaseChecker
   // This map is only used to ensure proper deletion of any allocated tags.
   mutable SymbolTagMap DeadSymbolTags;
 
+  mutable llvm::OwningPtr<RetainSummaryManager> Summaries;
+  mutable llvm::OwningPtr<RetainSummaryManager> SummariesGC;
+
   mutable ARCounts::Factory ARCountFactory;
 
   mutable SummaryLogTy SummaryLog;
@@ -2710,6 +2709,22 @@ public:
     return isGCEnabled() || Ctx.getLangOptions().ObjCAutoRefCount;
   }
 
+  RetainSummaryManager &getSummaryManager(ASTContext &Ctx) const {
+    if (isGCEnabled()) {
+      if (!SummariesGC) {
+        bool ARCEnabled = (bool)Ctx.getLangOptions().ObjCAutoRefCount;
+        SummariesGC.reset(new RetainSummaryManager(Ctx, true, ARCEnabled));
+      }
+      return *SummariesGC;
+    } else {
+      if (!Summaries) {
+        bool ARCEnabled = (bool)Ctx.getLangOptions().ObjCAutoRefCount;
+        Summaries.reset(new RetainSummaryManager(Ctx, false, ARCEnabled));
+      }
+      return *Summaries;
+    }
+  }
+
   void checkBind(SVal loc, SVal val, CheckerContext &C) const;
   void checkPostStmt(const BlockExpr *BE, CheckerContext &C) const;
   void checkPostStmt(const CastExpr *CE, CheckerContext &C) const;
@@ -2954,15 +2969,12 @@ void RetainReleaseChecker::checkPostStmt(const CastExpr *CE,
 
 void RetainReleaseChecker::checkPostStmt(const CallExpr *CE,
                                          CheckerContext &C) const {
-  // FIXME: This goes away once the RetainSummaryManager moves to the checker.
-  CFRefCount &TF = static_cast<CFRefCount&>(C.getEngine().getTF());
-  RetainSummaryManager &Summaries = TF.Summaries;
-
   // Get the callee.
   const ProgramState *state = C.getState();
   const Expr *Callee = CE->getCallee();
   SVal L = state->getSVal(Callee);
 
+  RetainSummaryManager &Summaries = getSummaryManager(C.getASTContext());
   RetainSummary *Summ = 0;
 
   // FIXME: Better support for blocks.  For now we stop tracking anything
@@ -2986,13 +2998,11 @@ void RetainReleaseChecker::checkPostStmt(const CallExpr *CE,
 
 void RetainReleaseChecker::checkPostObjCMessage(const ObjCMessage &Msg, 
                                                 CheckerContext &C) const {
-  // FIXME: This goes away once the RetainSummaryManager moves to the checker.
-  CFRefCount &TF = static_cast<CFRefCount&>(C.getEngine().getTF());
-  RetainSummaryManager &Summaries = TF.Summaries;
-
   const ProgramState *state = C.getState();
   ExplodedNode *Pred = C.getPredecessor();
 
+  RetainSummaryManager &Summaries = getSummaryManager(C.getASTContext());
+
   RetainSummary *Summ;
   if (Msg.isInstanceMessage()) {
     const LocationContext *LC = Pred->getLocationContext();
@@ -3060,13 +3070,10 @@ void RetainReleaseChecker::checkSummary(const RetainSummary &Summ,
   RetEffect RE = Summ.getRetEffect();
 
   if (RE.getKind() == RetEffect::OwnedWhenTrackedReceiver) {
-    if (ReceiverIsTracked) {
-      // FIXME: This goes away if the RetainSummaryManager moves to the checker.
-      CFRefCount &TF = static_cast<CFRefCount&>(C.getEngine().getTF());
-      RE = TF.Summaries.getObjAllocRetEffect();      
-    } else {
+    if (ReceiverIsTracked)
+      RE = getSummaryManager(C.getASTContext()).getObjAllocRetEffect();      
+    else
       RE = RetEffect::MakeNoRet();
-    }
   }
 
   switch (RE.getKind()) {
@@ -3467,23 +3474,21 @@ void RetainReleaseChecker::checkPreStmt(const ReturnStmt *S,
   X = *T;
 
   // Consult the summary of the enclosing method.
+  RetainSummaryManager &Summaries = getSummaryManager(C.getASTContext());
   const Decl *CD = &Pred->getCodeDecl();
 
-  // FIXME: This goes away once the RetainSummariesManager moves to the checker.
-  CFRefCount &TF = static_cast<CFRefCount&>(C.getEngine().getTF());
-
   if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(CD)) {
     // Unlike regular functions, /all/ ObjC methods are assumed to always
     // follow Cocoa retain-count conventions, not just those with special
     // names or attributes.
-    const RetainSummary *Summ = TF.Summaries.getMethodSummary(MD);
+    const RetainSummary *Summ = Summaries.getMethodSummary(MD);
     RetEffect RE = Summ ? Summ->getRetEffect() : RetEffect::MakeNoRet();
     checkReturnWithRetEffect(S, C, Pred, RE, X, Sym, state);
   }
 
   if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CD)) {
     if (!isa<CXXMethodDecl>(FD))
-      if (const RetainSummary *Summ = TF.Summaries.getSummary(FD))
+      if (const RetainSummary *Summ = Summaries.getSummary(FD))
         checkReturnWithRetEffect(S, C, Pred, Summ->getRetEffect(), X,
                                  Sym, state);
   }
@@ -3796,7 +3801,7 @@ void CFRefCount::RegisterChecks(ExprEngine& Eng) {
   // First register "return" leaks.
   const char *name = 0;
 
-  if (isGCEnabled())
+  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 "
@@ -3812,7 +3817,7 @@ void CFRefCount::RegisterChecks(ExprEngine& Eng) {
   BR.Register(leakAtReturn);
 
   // Second, register leaks within a function/method.
-  if (isGCEnabled())
+  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 "
@@ -3835,7 +3840,7 @@ void CFRefCount::RegisterChecks(ExprEngine& Eng) {
   RetainReleaseChecker *checker = 
     Eng.getCheckerManager().registerChecker<RetainReleaseChecker>();
   assert(checker);
-  checker->setGCMode(isGCEnabled() ? LangOptions::GCOnly : LangOptions::NonGC);
+  checker->setGCMode(GCEnabled ? LangOptions::GCOnly : LangOptions::NonGC);
 }
 
 TransferFuncs* ento::MakeCFRefCountTF(ASTContext &Ctx, bool GCEnabled,