]> granicus.if.org Git - clang/commitdiff
retain/release checker: Distinguish in the function summaries between
authorTed Kremenek <kremenek@apple.com>
Wed, 18 Feb 2009 18:54:33 +0000 (18:54 +0000)
committerTed Kremenek <kremenek@apple.com>
Wed, 18 Feb 2009 18:54:33 +0000 (18:54 +0000)
retain/releases performed via [... release] and CFRetain(). The former are
no-ops in GC. The checker already handled this, but now we emit nice diagnostics
to the user telling them that these are no-ops.

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

lib/Analysis/CFRefCount.cpp

index 7bb6e7ce1cbe9ac259dd441244320978d4f9810d..58d8abf8811e81fd782b5583b1847c423f35cb30 100644 (file)
@@ -131,7 +131,9 @@ static bool isRefType(QualType RetTy, const char* prefix,
 namespace {
 /// ArgEffect is used to summarize a function/method call's effect on a
 /// particular argument.
-enum ArgEffect { IncRef, DecRef, DoNothing, DoNothingByRef,
+enum ArgEffect { IncRefMsg, IncRef,  
+                 DecRefMsg, DecRef,
+                 DoNothing, DoNothingByRef,
                  StopTracking, MayEscape, SelfOwn, Autorelease };
 
 /// ArgEffects summarizes the effects of a function/method call on all of
@@ -1025,11 +1027,11 @@ void RetainSummaryManager::InitializeMethodSummaries() {
   
   // Create the "retain" selector.
   E = RetEffect::MakeReceiverAlias();
-  Summ = getPersistentSummary(E, isGCEnabled() ? DoNothing : IncRef);
+  Summ = getPersistentSummary(E, IncRefMsg);
   addNSObjectMethSummary(GetNullarySelector("retain", Ctx), Summ);
   
   // Create the "release" selector.
-  Summ = getPersistentSummary(E, isGCEnabled() ? DoNothing : DecRef);
+  Summ = getPersistentSummary(E, DecRefMsg);
   addNSObjectMethSummary(GetNullarySelector("release", Ctx), Summ);
   
   // Create the "drain" selector.
@@ -1936,9 +1938,13 @@ RefBindings CFRefCount::Update(RefBindings B, SymbolRef sym,
                                RefVal V, ArgEffect E,
                                RefVal::Kind& hasErr,
                                RefBindings::Factory& RefBFactory) {
-  
-  // FIXME: This dispatch can potentially be sped up by unifiying it into
-  //  a single switch statement.  Opt for simplicity for now.
+
+  // In GC mode [... release] and [... retain] do nothing.
+  switch (E) {
+    default: break;
+    case IncRefMsg: E = isGCEnabled() ? DoNothing : IncRef; break;
+    case DecRefMsg: E = isGCEnabled() ? DoNothing : DecRef; break;
+  }
   
   switch (E) {
     default:
@@ -1987,7 +1993,7 @@ RefBindings CFRefCount::Update(RefBindings B, SymbolRef sym,
       
     case SelfOwn:
       V = V ^ RefVal::NotOwned;
-      // Fall-through.      
+      // Fall-through.
     case DecRef:
       switch (V.getKind()) {
         default:
@@ -2344,11 +2350,20 @@ PathDiagnosticPiece* CFRefReport::VisitNode(const ExplodedNode<GRState>* N,
     for (llvm::SmallVectorImpl<ArgEffect>::iterator I=AEffects.begin(),
           E=AEffects.end(); I != E; ++I) {
 
-      // Did we do an 'autorelease' in GC mode?
-      if (TF.isGCEnabled() && *I == Autorelease) {
-        os << "In GC mode an 'autorelease' has no effect.";
-        continue;
-      }
+      // A bunch of things have alternate behavior under GC.
+      if (TF.isGCEnabled())
+        switch (*I) {
+          default: break;
+          case Autorelease:
+            os << "In GC mode an 'autorelease' has no effect.";
+            continue;
+          case IncRefMsg:
+            os << "In GC mode the 'retain' message has no effect.";
+            continue;
+          case DecRefMsg:
+            os << "In GC mode the 'release' message has no effect.";
+            continue;
+        }
     }
   }