From bf393be8a0b8b573ceb23ed19ac953832a2a69e4 Mon Sep 17 00:00:00 2001 From: Fariborz Jahanian Date: Thu, 5 Apr 2012 22:14:12 +0000 Subject: [PATCH] objective-c: Don't warn when a category does not implement a method declared in its adopted protocol when another category declares it because that category will implement it. // rdar://11186449 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@154132 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/DeclObjC.h | 10 ++++----- lib/AST/DeclObjC.cpp | 22 +++++++++++--------- lib/Sema/SemaDeclObjC.cpp | 4 ++-- test/SemaObjC/method-undef-category-warn-1.m | 21 +++++++++++++++++++ 4 files changed, 40 insertions(+), 17 deletions(-) diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h index 37a2e9ff8b..4ae073ec46 100644 --- a/include/clang/AST/DeclObjC.h +++ b/include/clang/AST/DeclObjC.h @@ -901,14 +901,14 @@ public: // Lookup a method. First, we search locally. If a method isn't // found, we search referenced protocols and class categories. ObjCMethodDecl *lookupMethod(Selector Sel, bool isInstance, - bool noCategoryLookup= false) const; + bool shallowCategoryLookup= false) const; ObjCMethodDecl *lookupInstanceMethod(Selector Sel, - bool noCategoryLookup = false) const { - return lookupMethod(Sel, true/*isInstance*/, noCategoryLookup); + bool shallowCategoryLookup = false) const { + return lookupMethod(Sel, true/*isInstance*/, shallowCategoryLookup); } ObjCMethodDecl *lookupClassMethod(Selector Sel, - bool noCategoryLookup = false) const { - return lookupMethod(Sel, false/*isInstance*/, noCategoryLookup); + bool shallowCategoryLookup = false) const { + return lookupMethod(Sel, false/*isInstance*/, shallowCategoryLookup); } ObjCInterfaceDecl *lookupInheritedClass(const IdentifierInfo *ICName); diff --git a/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp index a92c624b4c..2370d3c018 100644 --- a/lib/AST/DeclObjC.cpp +++ b/lib/AST/DeclObjC.cpp @@ -316,9 +316,9 @@ ObjCInterfaceDecl *ObjCInterfaceDecl::lookupInheritedClass( /// lookupMethod - This method returns an instance/class method by looking in /// the class, its categories, and its super classes (using a linear search). -ObjCMethodDecl *ObjCInterfaceDecl::lookupMethod(Selector Sel, - bool isInstance, - bool noCategoryLookup) const { +ObjCMethodDecl *ObjCInterfaceDecl::lookupMethod(Selector Sel, + bool isInstance, + bool shallowCategoryLookup) const { // FIXME: Should make sure no callers ever do this. if (!hasDefinition()) return 0; @@ -339,13 +339,14 @@ ObjCMethodDecl *ObjCInterfaceDecl::lookupMethod(Selector Sel, I != E; ++I) if ((MethodDecl = (*I)->lookupMethod(Sel, isInstance))) return MethodDecl; - if (!noCategoryLookup) { - // Didn't find one yet - now look through categories. - ObjCCategoryDecl *CatDecl = ClassDecl->getCategoryList(); - while (CatDecl) { - if ((MethodDecl = CatDecl->getMethod(Sel, isInstance))) - return MethodDecl; + + // Didn't find one yet - now look through categories. + ObjCCategoryDecl *CatDecl = ClassDecl->getCategoryList(); + while (CatDecl) { + if ((MethodDecl = CatDecl->getMethod(Sel, isInstance))) + return MethodDecl; + if (!shallowCategoryLookup) { // Didn't find one yet - look through protocols. const ObjCList &Protocols = CatDecl->getReferencedProtocols(); @@ -353,9 +354,10 @@ ObjCMethodDecl *ObjCInterfaceDecl::lookupMethod(Selector Sel, E = Protocols.end(); I != E; ++I) if ((MethodDecl = (*I)->lookupMethod(Sel, isInstance))) return MethodDecl; - CatDecl = CatDecl->getNextClassCategory(); } + CatDecl = CatDecl->getNextClassCategory(); } + ClassDecl = ClassDecl->getSuperClass(); } return NULL; diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index 27500fcd69..6be9c7ceeb 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -1537,7 +1537,7 @@ void Sema::CheckProtocolMethodDefs(SourceLocation ImpLoc, // uses the protocol. if (ObjCMethodDecl *MethodInClass = IDecl->lookupInstanceMethod(method->getSelector(), - true /*noCategoryLookup*/)) + true /*shallowCategoryLookup*/)) if (C || MethodInClass->isSynthesized()) continue; unsigned DIAG = diag::warn_unimplemented_protocol_method; @@ -1561,7 +1561,7 @@ void Sema::CheckProtocolMethodDefs(SourceLocation ImpLoc, (!Super || !Super->lookupClassMethod(method->getSelector()))) { // See above comment for instance method lookups. if (C && IDecl->lookupClassMethod(method->getSelector(), - true /*noCategoryLookup*/)) + true /*shallowCategoryLookup*/)) continue; unsigned DIAG = diag::warn_unimplemented_protocol_method; if (Diags.getDiagnosticLevel(DIAG, ImpLoc) != diff --git a/test/SemaObjC/method-undef-category-warn-1.m b/test/SemaObjC/method-undef-category-warn-1.m index b390827656..2548cbd241 100644 --- a/test/SemaObjC/method-undef-category-warn-1.m +++ b/test/SemaObjC/method-undef-category-warn-1.m @@ -51,3 +51,24 @@ @implementation NSObject (FooConformance) @end + +// rdar://11186449 +// Don't warn when a category does not implemented a method imported +// by its protocol because another category has its declaration and +// that category will implement it. +@interface NSOrderedSet @end + +@interface NSOrderedSet(CoolectionImplements) +- (unsigned char)containsObject:(id)object; +@end + +@protocol Collection +- (unsigned char)containsObject:(id)object; +@end + +@interface NSOrderedSet (CollectionConformance) +@end + +@implementation NSOrderedSet (CollectionConformance) +@end + -- 2.40.0