r298587 - [ObjC][ARC] Avoid -Warc-performSelector-leaks for performSelector variations

Alex Lorenz via cfe-commits cfe-commits at lists.llvm.org
Thu Mar 23 03:46:05 PDT 2017


Author: arphaman
Date: Thu Mar 23 05:46:05 2017
New Revision: 298587

URL: http://llvm.org/viewvc/llvm-project?rev=298587&view=rev
Log:
[ObjC][ARC] Avoid -Warc-performSelector-leaks for performSelector variations
that became supported after r297019

The commit r297019 expanded the performSelector ObjC method family heuristic
to ensure that -Wobjc-unsafe-perform-selector covers all performSelector
variations. However, this made the -Warc-performSelector-leaks too noisy, as
that warning produces mostly false positives since the selector is unknown.
This commit reverts the ObjC method family heuristics introduced in r297019.
This ensures that -Warc-performSelector-leaks isn't too noisy. The commit still
preserves the coverage of -Wobjc-unsafe-perform-selector.

rdar://31124629

Modified:
    cfe/trunk/lib/AST/DeclObjC.cpp
    cfe/trunk/lib/Sema/SemaExprObjC.cpp
    cfe/trunk/test/SemaObjC/arc-peformselector.m

Modified: cfe/trunk/lib/AST/DeclObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclObjC.cpp?rev=298587&r1=298586&r2=298587&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclObjC.cpp (original)
+++ cfe/trunk/lib/AST/DeclObjC.cpp Thu Mar 23 05:46:05 2017
@@ -979,12 +979,11 @@ ObjCMethodFamily ObjCMethodDecl::getMeth
     break;
       
   case OMF_performSelector:
-    if (!isInstanceMethod() ||
-        !(getReturnType()->isObjCIdType() || getReturnType()->isVoidType()))
+    if (!isInstanceMethod() || !getReturnType()->isObjCIdType())
       family = OMF_None;
     else {
       unsigned noParams = param_size();
-      if (noParams < 1 || noParams > 5)
+      if (noParams < 1 || noParams > 3)
         family = OMF_None;
       else {
         ObjCMethodDecl::param_type_iterator it = param_type_begin();
@@ -993,11 +992,10 @@ ObjCMethodFamily ObjCMethodDecl::getMeth
           family = OMF_None;
           break;
         }
-        // The first type should generally always be 'id' or 'Thread *', the
-        // other types can vary.
-        if (noParams > 1) {
-          ArgT = *(it + 1);
-          if (!ArgT->isObjCObjectPointerType()) {
+        while (--noParams) {
+          it++;
+          ArgT = (*it);
+          if (!ArgT->isObjCIdType()) {
             family = OMF_None;
             break;
           }

Modified: cfe/trunk/lib/Sema/SemaExprObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprObjC.cpp?rev=298587&r1=298586&r2=298587&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprObjC.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprObjC.cpp Thu Mar 23 05:46:05 2017
@@ -2272,7 +2272,8 @@ static void checkFoundationAPI(Sema &S,
                                bool IsClassObjectCall) {
   // Check if this is a performSelector method that uses a selector that returns
   // a record or a vector type.
-  if (Method->getMethodFamily() != OMF_performSelector || Args.empty())
+  if (Method->getSelector().getMethodFamily() != OMF_performSelector ||
+      Args.empty())
     return;
   const auto *SE = dyn_cast<ObjCSelectorExpr>(Args[0]->IgnoreParens());
   if (!SE)

Modified: cfe/trunk/test/SemaObjC/arc-peformselector.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/arc-peformselector.m?rev=298587&r1=298586&r2=298587&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/arc-peformselector.m (original)
+++ cfe/trunk/test/SemaObjC/arc-peformselector.m Thu Mar 23 05:46:05 2017
@@ -18,6 +18,9 @@
 - (id)performSelector:(SEL)aSelector;
 - (id)performSelector:(SEL)aSelector withObject:(id)object;
 - (id)performSelector:(SEL)aSelector withObject:(id)object1 withObject:(id)object2;
+
+- (void)performSelector:(SEL)aSelector withObject:(id)anArgument afterDelay:(double)delay inModes:(I *)modes;
+
 @end
 
 @implementation I
@@ -33,10 +36,15 @@
   return [self performSelector : @selector(PlusZero)];
   return [self performSelector : @selector(PlusOne)]; // expected-error {{performSelector names a selector which retains the object}}
 
+  // Avoid the unkown selector warning for more complicated performSelector
+  // variations because it produces too many false positives.
+  [self performSelector: sel1 withObject:0 afterDelay:0 inModes:0];
+
   return [self performSelector: @selector(self)]; // No error, -self is not +1!
 }
 
 - (id)performSelector:(SEL)aSelector { return 0; }
 - (id)performSelector:(SEL)aSelector withObject:(id)object { return 0; }
 - (id)performSelector:(SEL)aSelector withObject:(id)object1 withObject:(id)object2 { return 0; }
+- (void)performSelector:(SEL)aSelector withObject:(id)anArgument afterDelay:(double)delay inModes:(I *)modes { }
 @end




More information about the cfe-commits mailing list