From: Fariborz Jahanian Date: Wed, 27 Aug 2014 20:34:29 +0000 (+0000) Subject: Objective-C. Change to method lookup rules to look X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=c8df8573681a027384d7bec55866f51ae74f8393;p=clang Objective-C. Change to method lookup rules to look into primary class's named categories before looking into their protocols. This is because categories are part of the public interface and , just as primary class, preference should be given to them before class (and category) protocols. // rdar://18013929 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@216610 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp index e753feb3d9..cc6560787c 100644 --- a/lib/AST/DeclObjC.cpp +++ b/lib/AST/DeclObjC.cpp @@ -558,36 +558,39 @@ ObjCMethodDecl *ObjCInterfaceDecl::lookupMethod(Selector Sel, LoadExternalDefinition(); while (ClassDecl) { + // 1. Look through primary class. if ((MethodDecl = ClassDecl->getMethod(Sel, isInstance))) return MethodDecl; - - // Didn't find one yet - look through protocols. - for (const auto *I : ClassDecl->protocols()) - if ((MethodDecl = I->lookupMethod(Sel, isInstance))) - return MethodDecl; - // Didn't find one yet - now look through categories. - for (const auto *Cat : ClassDecl->visible_categories()) { + // 2. Didn't find one yet - now look through categories. + for (const auto *Cat : ClassDecl->visible_categories()) if ((MethodDecl = Cat->getMethod(Sel, isInstance))) if (C != Cat || !MethodDecl->isImplicit()) return MethodDecl; - if (!shallowCategoryLookup) { + // 3. Didn't find one yet - look through primary class's protocols. + for (const auto *I : ClassDecl->protocols()) + if ((MethodDecl = I->lookupMethod(Sel, isInstance))) + return MethodDecl; + + // 4. Didn't find one yet - now look through categories' protocols + if (!shallowCategoryLookup) + for (const auto *Cat : ClassDecl->visible_categories()) { // Didn't find one yet - look through protocols. const ObjCList &Protocols = - Cat->getReferencedProtocols(); + Cat->getReferencedProtocols(); for (ObjCList::iterator I = Protocols.begin(), E = Protocols.end(); I != E; ++I) if ((MethodDecl = (*I)->lookupMethod(Sel, isInstance))) if (C != Cat || !MethodDecl->isImplicit()) return MethodDecl; } - } - + + if (!followSuper) return nullptr; - // Get the super class (if any). + // 5. Get to the super class (if any). ClassDecl = ClassDecl->getSuperClass(); } return nullptr; diff --git a/test/SemaObjC/warn-category-method-deprecated.m b/test/SemaObjC/warn-category-method-deprecated.m new file mode 100644 index 0000000000..349a27a795 --- /dev/null +++ b/test/SemaObjC/warn-category-method-deprecated.m @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -fsyntax-only -Wno-objc-root-class -verify %s +// rdar://18013929 + +@protocol P +- (void)meth; +@end + +@interface I

+@end + +@interface I(cat) +- (void)meth __attribute__((deprecated)); // expected-note {{'meth' has been explicitly marked deprecated here}} +@end + +void foo(I *i) { + [i meth]; // expected-warning {{'meth' is deprecated}} +}