[analyzer] Re-instate support for MakeCollectable is RetainCountChecker

Differential Revision: https://reviews.llvm.org/D50872

llvm-svn: 340097
diff --git a/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp
index a0ffe30..89b487a 100644
--- a/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp
@@ -581,6 +581,8 @@
   case DecRefMsgAndStopTrackingHard:
     E = IgnoreRetainMsg ? StopTracking : DecRefAndStopTrackingHard;
     break;
+  case MakeCollectable:
+    E = DoNothing;
   }
 
   // Handle all use-after-releases.
@@ -593,8 +595,9 @@
   switch (E) {
     case DecRefMsg:
     case IncRefMsg:
+    case MakeCollectable:
     case DecRefMsgAndStopTrackingHard:
-      llvm_unreachable("DecRefMsg/IncRefMsg already converted");
+      llvm_unreachable("DecRefMsg/IncRefMsg/MakeCollectable already converted");
 
     case UnretainedOutParameter:
     case RetainedOutParameter:
diff --git a/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountSummaries.cpp b/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountSummaries.cpp
index d5d56e3..77699cc 100644
--- a/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountSummaries.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountSummaries.cpp
@@ -78,6 +78,10 @@
          FName.endswith_lower("autorelease");
 }
 
+static bool isMakeCollectable(StringRef FName) {
+  return FName.contains_lower("MakeCollectable");
+}
+
 const RetainSummary *
 RetainSummaryManager::generateSummary(const FunctionDecl *FD,
                                       bool &AllowAnnotations) {
@@ -111,6 +115,11 @@
     // Part of: <rdar://problem/7299394> and <rdar://problem/11282706>.
     // This will be addressed better with IPA.
     return getPersistentStopSummary();
+  } else if(FName == "NSMakeCollectable") {
+    // Handle: id NSMakeCollectable(CFTypeRef)
+    AllowAnnotations = false;
+    return RetTy->isObjCIdType() ? getUnarySummary(FT, cfmakecollectable)
+                                 : getPersistentStopSummary();
   } else if (FName == "CFPlugInInstanceCreate") {
     return getPersistentSummary(RetEffect::MakeNoRet());
   } else if (FName == "IORegistryEntrySearchCFProperty" ||
@@ -207,6 +216,9 @@
         AllowAnnotations = false;
 
         return getUnarySummary(FT, cfautorelease);
+      } else if (isMakeCollectable(FName)) {
+        AllowAnnotations = false;
+        return getUnarySummary(FT, cfmakecollectable);
       } else {
         return getCFCreateGetRuleSummary(FD);
       }
@@ -301,7 +313,6 @@
 // Summary creation for functions (largely uses of Core Foundation).
 //===----------------------------------------------------------------------===//
 
-
 static ArgEffect getStopTrackingHardEquivalent(ArgEffect E) {
   switch (E) {
   case DoNothing:
@@ -309,6 +320,7 @@
   case DecRefBridgedTransferred:
   case IncRef:
   case IncRefMsg:
+  case MakeCollectable:
   case UnretainedOutParameter:
   case RetainedOutParameter:
   case MayEscape:
@@ -458,14 +470,17 @@
   FName = FName.substr(FName.find_first_not_of('_'));
 
   QualType ResultTy = CE->getCallReturnType(Ctx);
-  if (ResultTy->isPointerType()) {
+  if (ResultTy->isObjCIdType()) {
+    return II->isStr("NSMakeCollectable");
+  } else if (ResultTy->isPointerType()) {
     // Handle: (CF|CG|CV)Retain
     //         CFAutorelease
     // It's okay to be a little sloppy here.
     if (cocoa::isRefType(ResultTy, "CF", FName) ||
         cocoa::isRefType(ResultTy, "CG", FName) ||
         cocoa::isRefType(ResultTy, "CV", FName))
-      return isRetain(FD, FName) || isAutorelease(FD, FName);
+      return isRetain(FD, FName) || isAutorelease(FD, FName) ||
+             isMakeCollectable(FName);
 
     if (FD->getDefinition()) {
       bool out = isTrustedReferenceCountImplementation(FD->getDefinition());
@@ -495,6 +510,7 @@
   case cfretain: Effect = IncRef; break;
   case cfrelease: Effect = DecRef; break;
   case cfautorelease: Effect = Autorelease; break;
+  case cfmakecollectable: Effect = MakeCollectable; break;
   }
 
   ScratchArgs = AF.add(ScratchArgs, 0, Effect);
diff --git a/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountSummaries.h b/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountSummaries.h
index 3161b9c..dd56a44 100644
--- a/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountSummaries.h
+++ b/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountSummaries.h
@@ -315,7 +315,7 @@
   ///  data in ScratchArgs.
   ArgEffects getArgEffects();
 
-  enum UnaryFuncKind { cfretain, cfrelease, cfautorelease };
+  enum UnaryFuncKind { cfretain, cfrelease, cfautorelease, cfmakecollectable };
 
   const RetainSummary *getUnarySummary(const FunctionType* FT,
                                        UnaryFuncKind func);