retain/release checker:
- Fix summary lookup for class methods to now use the (optional)
  ObjCInterfaceDecl associated with a message expression. This removes a
  long-standing FIXME.
- Partial fix for <rdar://problem/6062730> by stop tracking objects that
  are passed to [NSObject performSelector].  These methods are often used
  for delegates, which the analyzer doesn't reason about well yet.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@69982 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Analysis/CFRefCount.cpp b/lib/Analysis/CFRefCount.cpp
index b63078b..564f15b 100644
--- a/lib/Analysis/CFRefCount.cpp
+++ b/lib/Analysis/CFRefCount.cpp
@@ -659,34 +659,51 @@
     Selector S = GetNullarySelector(nullaryName, Ctx);
     ObjCMethodSummaries[ObjCSummaryKey(ClsII, S)]  = Summ;
   }
-    
-  void addInstMethSummary(const char* Cls, RetainSummary* Summ, va_list argp) {
-    
-    IdentifierInfo* ClsII = &Ctx.Idents.get(Cls);
+  
+  Selector generateSelector(va_list argp) {
     llvm::SmallVector<IdentifierInfo*, 10> II;
-    
+
     while (const char* s = va_arg(argp, const char*))
       II.push_back(&Ctx.Idents.get(s));
-    
-    Selector S = Ctx.Selectors.getSelector(II.size(), &II[0]);
-    ObjCMethodSummaries[ObjCSummaryKey(ClsII, S)] = Summ;
+
+    return Ctx.Selectors.getSelector(II.size(), &II[0]);    
+  }
+  
+  void addMethodSummary(IdentifierInfo *ClsII, ObjCMethodSummariesTy& Summaries,
+                        RetainSummary* Summ, va_list argp) {
+    Selector S = generateSelector(argp);
+    Summaries[ObjCSummaryKey(ClsII, S)] = Summ;
   }
   
   void addInstMethSummary(const char* Cls, RetainSummary* Summ, ...) {
     va_list argp;
     va_start(argp, Summ);
-    addInstMethSummary(Cls, Summ, argp);
+    addMethodSummary(&Ctx.Idents.get(Cls), ObjCMethodSummaries, Summ, argp);
     va_end(argp);    
   }
-          
+  
+  void addClsMethSummary(const char* Cls, RetainSummary* Summ, ...) {
+    va_list argp;
+    va_start(argp, Summ);
+    addMethodSummary(&Ctx.Idents.get(Cls),ObjCClassMethodSummaries, Summ, argp);
+    va_end(argp);
+  }
+  
+  void addClsMethSummary(IdentifierInfo *II, RetainSummary* Summ, ...) {
+    va_list argp;
+    va_start(argp, Summ);
+    addMethodSummary(II, ObjCClassMethodSummaries, Summ, argp);
+    va_end(argp);
+  }
+
   void addPanicSummary(const char* Cls, ...) {
     RetainSummary* Summ = getPersistentSummary(0, RetEffect::MakeNoRet(),
                                                DoNothing,  DoNothing, true);
     va_list argp;
     va_start (argp, Cls);
-    addInstMethSummary(Cls, Summ, argp);
+    addMethodSummary(&Ctx.Idents.get(Cls), ObjCMethodSummaries, Summ, argp);
     va_end(argp);
-  }  
+  }
   
 public:
   
@@ -1100,23 +1117,30 @@
 }
 
 RetainSummary*
-RetainSummaryManager::getClassMethodSummary(ObjCMessageExpr* ME) {
-  
-  // FIXME: Eventually we should properly do class method summaries, but
-  // it requires us being able to walk the type hierarchy.  Unfortunately,
-  // we cannot do this with just an IdentifierInfo* for the class name.  
-  IdentifierInfo* ClsName = ME->getClassName();
+RetainSummaryManager::getClassMethodSummary(ObjCMessageExpr *ME) {
+
   Selector S = ME->getSelector();
+  ObjCMethodSummariesTy::iterator I;
   
-  // Look up a summary in our cache of Selectors -> Summaries.
-  ObjCMethodSummariesTy::iterator I = ObjCClassMethodSummaries.find(ClsName, S);
+  if (ObjCInterfaceDecl *ID = ME->getClassInfo().first) {
+    // Lookup the method using the decl for the class @interface.
+    I = ObjCClassMethodSummaries.find(ID, S); 
+  }
+  else {
+    // Fallback to using the class name.
+    IdentifierInfo *ClsName = ME->getClassName();
+  
+    // Look up a summary in our cache of Selectors -> Summaries.
+    I = ObjCClassMethodSummaries.find(ClsName, S);
+  }
   
   if (I != ObjCClassMethodSummaries.end())
     return I->second;
   
   RetainSummary* Summ =
     getCommonMethodSummary(ME, S.getIdentifierInfoForSlot(0)->getName());
-  ObjCClassMethodSummaries[ObjCSummaryKey(ClsName, S)] = Summ;
+
+  ObjCClassMethodSummaries[ObjCSummaryKey(ME->getClassName(), S)] = Summ;
   return Summ;
 }
 
@@ -1146,6 +1170,28 @@
                     GetUnarySelector("addObject", Ctx),
                     getPersistentSummary(RetEffect::MakeNoRet(),
                                          DoNothing, Autorelease));
+  
+  // Create the summaries for [NSObject performSelector...].  We treat
+  // these as 'stop tracking' for the arguments because they are often
+  // used for delegates that can release the object.  When we have better
+  // inter-procedural analysis we can potentially do something better.  This
+  // workaround is to remove false positives.
+  Summ = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, StopTracking);
+  IdentifierInfo *NSObjectII = &Ctx.Idents.get("NSObject");
+  addClsMethSummary(NSObjectII, Summ, "performSelector", "withObject",
+                    "afterDelay", NULL);
+  addClsMethSummary(NSObjectII, Summ, "performSelector", "withObject",
+                    "afterDelay", "inModes", NULL);
+  addClsMethSummary(NSObjectII, Summ, "performSelectorOnMainThread",
+                    "withObject", "waitUntilDone", NULL);
+  addClsMethSummary(NSObjectII, Summ, "performSelectorOnMainThread",
+                    "withObject", "waitUntilDone", "modes", NULL);
+  addClsMethSummary(NSObjectII, Summ, "performSelector", "onThread",
+                    "withObject", "waitUntilDone", NULL);
+  addClsMethSummary(NSObjectII, Summ, "performSelector", "onThread",
+                    "withObject", "waitUntilDone", "modes", NULL);
+  addClsMethSummary(NSObjectII, Summ, "performSelectorInBackground",
+                    "withObject", NULL);
 }
 
 void RetainSummaryManager::InitializeMethodSummaries() {
@@ -2012,6 +2058,7 @@
   else
     Summ = Summaries.getClassMethodSummary(ME);
 
+
   EvalSummary(Dst, Eng, Builder, ME, ME->getReceiver(), Summ,
               ME->arg_begin(), ME->arg_end(), Pred);
 }