forked from OSchip/llvm-project
[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 llvm-svn: 298587
This commit is contained in:
parent
85436ece89
commit
5ffe4e14f1
|
@ -979,12 +979,11 @@ ObjCMethodFamily ObjCMethodDecl::getMethodFamily() const {
|
|||
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::getMethodFamily() const {
|
|||
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;
|
||||
}
|
||||
|
|
|
@ -2272,7 +2272,8 @@ static void checkFoundationAPI(Sema &S, SourceLocation Loc,
|
|||
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)
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue