From: Daniel Dunbar Date: Thu, 4 Sep 2008 20:01:15 +0000 (+0000) Subject: Prevent invalid warnings about incomplete implementations for methods X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=7ad1b1fa075e5cd4160d5b357b2a8d3f8a131984;p=clang Prevent invalid warnings about incomplete implementations for methods which are inherited from base clases or protocols. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@55790 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index ce749e3f9a..f5a85a5fc9 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -322,13 +322,16 @@ private: void WarnUndefinedMethod(SourceLocation ImpLoc, ObjCMethodDecl *method, bool &IncompleteImpl); - /// CheckProtocolMethodDefs - This routine checks unimpletented methods - /// Declared in protocol, and those referenced by it. + /// CheckProtocolMethodDefs - This routine checks unimpletented + /// methods declared in protocol, and those referenced by it. + /// \param IDecl - Used for checking for methods which may have been + /// inherited. void CheckProtocolMethodDefs(SourceLocation ImpLoc, ObjCProtocolDecl *PDecl, bool& IncompleteImpl, const llvm::DenseSet &InsMap, - const llvm::DenseSet &ClsMap); + const llvm::DenseSet &ClsMap, + ObjCInterfaceDecl *IDecl); /// CheckImplementationIvars - This routine checks if the instance variables /// listed in the implelementation match those listed in the interface. diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index 3562ba9f09..240d760b75 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -128,7 +128,7 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc, } /// ActOnCompatiblityAlias - this action is called after complete parsing of -/// @compaatibility_alias declaration. It sets up the alias relationships. +/// @compatibility_alias declaration. It sets up the alias relationships. Sema::DeclTy *Sema::ActOnCompatiblityAlias(SourceLocation AtLoc, IdentifierInfo *AliasName, SourceLocation AliasLocation, @@ -203,8 +203,8 @@ Sema::ActOnStartProtocolInterface(SourceLocation AtProtoInterfaceLoc, } /// FindProtocolDeclaration - This routine looks up protocols and -/// issuer error if they are not declared. It returns list of protocol -/// declarations in its 'Protocols' argument. +/// issues an error if they are not declared. It returns list of +/// protocol declarations in its 'Protocols' argument. void Sema::FindProtocolDeclaration(bool WarnOnDeclarations, const IdentifierLocPair *ProtocolId, @@ -582,27 +582,37 @@ void Sema::CheckProtocolMethodDefs(SourceLocation ImpLoc, ObjCProtocolDecl *PDecl, bool& IncompleteImpl, const llvm::DenseSet &InsMap, - const llvm::DenseSet &ClsMap) { + const llvm::DenseSet &ClsMap, + ObjCInterfaceDecl *IDecl) { + ObjCInterfaceDecl *Super = IDecl->getSuperClass(); + + // If a method lookup fails locally we still need to look and see if + // the method was implemented by a base class or an inherited + // protocol. This lookup is slow, but occurs rarely in correct code + // and otherwise would terminate in a warning. + // check unimplemented instance methods. for (ObjCProtocolDecl::instmeth_iterator I = PDecl->instmeth_begin(), E = PDecl->instmeth_end(); I != E; ++I) { ObjCMethodDecl *method = *I; - if (!InsMap.count(method->getSelector()) && - method->getImplementationControl() != ObjCMethodDecl::Optional) + if (method->getImplementationControl() != ObjCMethodDecl::Optional && + !InsMap.count(method->getSelector()) && + (!Super || !Super->lookupInstanceMethod(method->getSelector()))) WarnUndefinedMethod(ImpLoc, method, IncompleteImpl); } // check unimplemented class methods for (ObjCProtocolDecl::classmeth_iterator I = PDecl->classmeth_begin(), E = PDecl->classmeth_end(); I != E; ++I) { ObjCMethodDecl *method = *I; - if (!ClsMap.count(method->getSelector()) && - method->getImplementationControl() != ObjCMethodDecl::Optional) + if (method->getImplementationControl() != ObjCMethodDecl::Optional && + !ClsMap.count(method->getSelector()) && + (!Super || !Super->lookupClassMethod(method->getSelector()))) WarnUndefinedMethod(ImpLoc, method, IncompleteImpl); } // Check on this protocols's referenced protocols, recursively. for (ObjCProtocolDecl::protocol_iterator PI = PDecl->protocol_begin(), E = PDecl->protocol_end(); PI != E; ++PI) - CheckProtocolMethodDefs(ImpLoc, *PI, IncompleteImpl, InsMap, ClsMap); + CheckProtocolMethodDefs(ImpLoc, *PI, IncompleteImpl, InsMap, ClsMap, IDecl); } void Sema::ImplMethodsVsClassMethods(ObjCImplementationDecl* IMPDecl, @@ -639,11 +649,11 @@ void Sema::ImplMethodsVsClassMethods(ObjCImplementationDecl* IMPDecl, for (ObjCList::iterator I = Protocols.begin(), E = Protocols.end(); I != E; ++I) CheckProtocolMethodDefs(IMPDecl->getLocation(), *I, - IncompleteImpl, InsMap, ClsMap); + IncompleteImpl, InsMap, ClsMap, IDecl); } /// ImplCategoryMethodsVsIntfMethods - Checks that methods declared in the -/// category interface is implemented in the category @implementation. +/// category interface are implemented in the category @implementation. void Sema::ImplCategoryMethodsVsIntfMethods(ObjCCategoryImplDecl *CatImplDecl, ObjCCategoryDecl *CatClassDecl) { llvm::DenseSet InsMap; @@ -677,7 +687,7 @@ void Sema::ImplCategoryMethodsVsIntfMethods(ObjCCategoryImplDecl *CatImplDecl, for (ObjCCategoryDecl::protocol_iterator PI = CatClassDecl->protocol_begin(), E = CatClassDecl->protocol_end(); PI != E; ++PI) CheckProtocolMethodDefs(CatImplDecl->getLocation(), *PI, IncompleteImpl, - InsMap, ClsMap); + InsMap, ClsMap, CatClassDecl->getClassInterface()); } /// ActOnForwardClassDeclaration - diff --git a/test/SemaObjC/protocol-implementation-inherited.m b/test/SemaObjC/protocol-implementation-inherited.m new file mode 100644 index 0000000000..1e26c663c2 --- /dev/null +++ b/test/SemaObjC/protocol-implementation-inherited.m @@ -0,0 +1,56 @@ +// RUN: clang -fsyntax-only -verify %s + +@protocol P0 +-bar; +@end + +@interface A +@end + +/// Interface conforms to inherited protocol + +@interface B0 : A +@end + +@implementation B0 +@end + +/// Interface conforms to a protocol which extends another. The other +/// protocol is inherited, and extended methods are implemented. + +@protocol P1 +-foo; +@end + +@interface B1 : A +@end + +@implementation B1 +-foo {}; +@end + +/// Interface conforms to a protocol whose methods are provided by an +/// alternate inherited protocol. + +@protocol P2 +-bar; +@end + +@interface B2 : A +@end + +@implementation B2 +@end + +/// Interface conforms to a protocol whose methods are provided by a base class. + +@interface A1 +-bar; +@end + +@interface B3 : A1 +@end + +@implementation B3 +@end +