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

llvm-svn: 154132
This commit is contained in:
Fariborz Jahanian 2012-04-05 22:14:12 +00:00
parent 64aa24e13f
commit c806b90717
4 changed files with 40 additions and 17 deletions

View File

@ -901,14 +901,14 @@ public:
// Lookup a method. First, we search locally. If a method isn't // Lookup a method. First, we search locally. If a method isn't
// found, we search referenced protocols and class categories. // found, we search referenced protocols and class categories.
ObjCMethodDecl *lookupMethod(Selector Sel, bool isInstance, ObjCMethodDecl *lookupMethod(Selector Sel, bool isInstance,
bool noCategoryLookup= false) const; bool shallowCategoryLookup= false) const;
ObjCMethodDecl *lookupInstanceMethod(Selector Sel, ObjCMethodDecl *lookupInstanceMethod(Selector Sel,
bool noCategoryLookup = false) const { bool shallowCategoryLookup = false) const {
return lookupMethod(Sel, true/*isInstance*/, noCategoryLookup); return lookupMethod(Sel, true/*isInstance*/, shallowCategoryLookup);
} }
ObjCMethodDecl *lookupClassMethod(Selector Sel, ObjCMethodDecl *lookupClassMethod(Selector Sel,
bool noCategoryLookup = false) const { bool shallowCategoryLookup = false) const {
return lookupMethod(Sel, false/*isInstance*/, noCategoryLookup); return lookupMethod(Sel, false/*isInstance*/, shallowCategoryLookup);
} }
ObjCInterfaceDecl *lookupInheritedClass(const IdentifierInfo *ICName); ObjCInterfaceDecl *lookupInheritedClass(const IdentifierInfo *ICName);

View File

@ -316,9 +316,9 @@ ObjCInterfaceDecl *ObjCInterfaceDecl::lookupInheritedClass(
/// lookupMethod - This method returns an instance/class method by looking in /// lookupMethod - This method returns an instance/class method by looking in
/// the class, its categories, and its super classes (using a linear search). /// the class, its categories, and its super classes (using a linear search).
ObjCMethodDecl *ObjCInterfaceDecl::lookupMethod(Selector Sel, ObjCMethodDecl *ObjCInterfaceDecl::lookupMethod(Selector Sel,
bool isInstance, bool isInstance,
bool noCategoryLookup) const { bool shallowCategoryLookup) const {
// FIXME: Should make sure no callers ever do this. // FIXME: Should make sure no callers ever do this.
if (!hasDefinition()) if (!hasDefinition())
return 0; return 0;
@ -339,13 +339,14 @@ ObjCMethodDecl *ObjCInterfaceDecl::lookupMethod(Selector Sel,
I != E; ++I) I != E; ++I)
if ((MethodDecl = (*I)->lookupMethod(Sel, isInstance))) if ((MethodDecl = (*I)->lookupMethod(Sel, isInstance)))
return MethodDecl; return MethodDecl;
if (!noCategoryLookup) {
// Didn't find one yet - now look through categories. // Didn't find one yet - now look through categories.
ObjCCategoryDecl *CatDecl = ClassDecl->getCategoryList(); ObjCCategoryDecl *CatDecl = ClassDecl->getCategoryList();
while (CatDecl) { while (CatDecl) {
if ((MethodDecl = CatDecl->getMethod(Sel, isInstance))) if ((MethodDecl = CatDecl->getMethod(Sel, isInstance)))
return MethodDecl; return MethodDecl;
if (!shallowCategoryLookup) {
// Didn't find one yet - look through protocols. // Didn't find one yet - look through protocols.
const ObjCList<ObjCProtocolDecl> &Protocols = const ObjCList<ObjCProtocolDecl> &Protocols =
CatDecl->getReferencedProtocols(); CatDecl->getReferencedProtocols();
@ -353,9 +354,10 @@ ObjCMethodDecl *ObjCInterfaceDecl::lookupMethod(Selector Sel,
E = Protocols.end(); I != E; ++I) E = Protocols.end(); I != E; ++I)
if ((MethodDecl = (*I)->lookupMethod(Sel, isInstance))) if ((MethodDecl = (*I)->lookupMethod(Sel, isInstance)))
return MethodDecl; return MethodDecl;
CatDecl = CatDecl->getNextClassCategory();
} }
CatDecl = CatDecl->getNextClassCategory();
} }
ClassDecl = ClassDecl->getSuperClass(); ClassDecl = ClassDecl->getSuperClass();
} }
return NULL; return NULL;

View File

@ -1537,7 +1537,7 @@ void Sema::CheckProtocolMethodDefs(SourceLocation ImpLoc,
// uses the protocol. // uses the protocol.
if (ObjCMethodDecl *MethodInClass = if (ObjCMethodDecl *MethodInClass =
IDecl->lookupInstanceMethod(method->getSelector(), IDecl->lookupInstanceMethod(method->getSelector(),
true /*noCategoryLookup*/)) true /*shallowCategoryLookup*/))
if (C || MethodInClass->isSynthesized()) if (C || MethodInClass->isSynthesized())
continue; continue;
unsigned DIAG = diag::warn_unimplemented_protocol_method; unsigned DIAG = diag::warn_unimplemented_protocol_method;
@ -1561,7 +1561,7 @@ void Sema::CheckProtocolMethodDefs(SourceLocation ImpLoc,
(!Super || !Super->lookupClassMethod(method->getSelector()))) { (!Super || !Super->lookupClassMethod(method->getSelector()))) {
// See above comment for instance method lookups. // See above comment for instance method lookups.
if (C && IDecl->lookupClassMethod(method->getSelector(), if (C && IDecl->lookupClassMethod(method->getSelector(),
true /*noCategoryLookup*/)) true /*shallowCategoryLookup*/))
continue; continue;
unsigned DIAG = diag::warn_unimplemented_protocol_method; unsigned DIAG = diag::warn_unimplemented_protocol_method;
if (Diags.getDiagnosticLevel(DIAG, ImpLoc) != if (Diags.getDiagnosticLevel(DIAG, ImpLoc) !=

View File

@ -51,3 +51,24 @@
@implementation NSObject (FooConformance) @implementation NSObject (FooConformance)
@end @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) <Collection>
@end
@implementation NSOrderedSet (CollectionConformance)
@end