]> granicus.if.org Git - clang/commitdiff
Prevent invalid warnings about incomplete implementations for methods
authorDaniel Dunbar <daniel@zuster.org>
Thu, 4 Sep 2008 20:01:15 +0000 (20:01 +0000)
committerDaniel Dunbar <daniel@zuster.org>
Thu, 4 Sep 2008 20:01:15 +0000 (20:01 +0000)
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

lib/Sema/Sema.h
lib/Sema/SemaDeclObjC.cpp
test/SemaObjC/protocol-implementation-inherited.m [new file with mode: 0644]

index ce749e3f9a8c6f0bd36621901d8a39cf392149bf..f5a85a5fc9ed6c8c1114c315791081b7b9d30a76 100644 (file)
@@ -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<Selector> &InsMap,
-                               const llvm::DenseSet<Selector> &ClsMap);
+                               const llvm::DenseSet<Selector> &ClsMap,
+                               ObjCInterfaceDecl *IDecl);
   
   /// CheckImplementationIvars - This routine checks if the instance variables
   /// listed in the implelementation match those listed in the interface. 
index 3562ba9f09a788e8d0b459171088c725e7594d5c..240d760b755d7d1796b973a0e9f255196a9e6df7 100644 (file)
@@ -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<Selector> &InsMap,
-                                   const llvm::DenseSet<Selector> &ClsMap) {
+                                   const llvm::DenseSet<Selector> &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<ObjCProtocolDecl>::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<Selector> 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 (file)
index 0000000..1e26c66
--- /dev/null
@@ -0,0 +1,56 @@
+// RUN: clang -fsyntax-only -verify %s
+
+@protocol P0
+-bar;
+@end
+
+@interface A <P0>
+@end
+
+/// Interface conforms to inherited protocol
+
+@interface B0 : A <P0>
+@end
+
+@implementation B0
+@end
+
+/// Interface conforms to a protocol which extends another. The other
+/// protocol is inherited, and extended methods are implemented.
+
+@protocol P1 <P0>
+-foo;
+@end
+
+@interface B1 : A <P1>
+@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 <P2>
+@end
+
+@implementation B2
+@end
+
+/// Interface conforms to a protocol whose methods are provided by a base class.
+
+@interface A1 
+-bar;
+@end
+
+@interface B3 : A1 <P2>
+@end
+
+@implementation B3
+@end
+