]> granicus.if.org Git - clang/commitdiff
Patch to warn on umimplemented methods coming from class's
authorFariborz Jahanian <fjahanian@apple.com>
Fri, 28 Sep 2007 17:40:07 +0000 (17:40 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Fri, 28 Sep 2007 17:40:07 +0000 (17:40 +0000)
protocols.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@42436 91177308-0d34-0410-b5e6-96231b3b80d8

Sema/Sema.h
Sema/SemaDecl.cpp
include/clang/AST/Decl.h
include/clang/Parse/Action.h
test/Sema/undef-protocol-methods-1.m [new file with mode: 0644]

index 45d1a2dc33dc3f7802364dff275ee25754cad6c4..a486d4fa73a25e7ed51280c84865e9114e49b935 100644 (file)
@@ -390,8 +390,6 @@ public:
   virtual void ActOnImpleIvarVsClassIvars(DeclTy *ClassDecl,
                                           DeclTy **Fields, unsigned NumFields);
   
-  virtual void ActOnImplMethodsVsClassMethods(DeclTy *ImplClass, DeclTy *Class);
-
   virtual DeclTy *ObjcBuildMethodDeclaration(SourceLocation MethodLoc, 
     tok::TokenKind MethodType, TypeTy *ReturnType, SelectorInfo *Sel,
     // optional arguments. The number of types/arguments is obtained
index 381003f86afd81622a6f06cc1f68f74c234127aa..45762acd37da5675166a87d2b1a185874d71bca6 100644 (file)
@@ -1174,46 +1174,76 @@ void Sema::ActOnImpleIvarVsClassIvars(DeclTy *ClassDecl,
       
 }
 
-void Sema::ActOnImplMethodsVsClassMethods(DeclTy* ImplClassDecl, 
-                                          DeclTy* ClassDecl) {
-  ObjcImplementationDecl* IMPDecl = 
-    cast<ObjcImplementationDecl>(static_cast<Decl*>(ImplClassDecl));
-  assert(IMPDecl && "missing implmentation class decl");
-  
-  ObjcInterfaceDecl* IDecl = 
-    cast<ObjcInterfaceDecl>(static_cast<Decl*>(ClassDecl));
-  assert(IDecl && "missing interface class decl");
+/// CheckProtocolMethodDefs - This routine checks unimpletented methods
+/// Declared in protocol, and those referenced by it.
+///
+static void CheckProtocolMethodDefs(Sema* objSema, ObjcProtocolDecl *PDecl,
+             const llvm::DenseMap<const SelectorInfo*, char>& InsMap,
+             const llvm::DenseMap<const SelectorInfo*, char>& ClsMap) {
+  // check unimplemented instance methods.
+  ObjcMethodDecl** methods = PDecl->getInsMethods();
+  for (int j = 0; j < PDecl->getNumInsMethods(); j++)
+    if (!InsMap.count(methods[j]->getSelector())) {
+      llvm::SmallString<128> buf;
+      objSema->Diag(methods[j]->getLocation(), diag::warn_undef_method_impl,
+                    methods[j]->getSelector()->getName(buf));
+    }
+  // check unimplemented class methods
+  methods = PDecl->getClsMethods();
+  for (int j = 0; j < PDecl->getNumClsMethods(); j++)
+    if (!ClsMap.count(methods[j]->getSelector())) {
+      llvm::SmallString<128> buf;
+      objSema->Diag(methods[j]->getLocation(), diag::warn_undef_method_impl,
+                    methods[j]->getSelector()->getName(buf));
+    }
   
-  llvm::DenseMap<const SelectorInfo*, char> Map;
+  // Check on this protocols's referenced protocols, recursively
+  ObjcProtocolDecl** RefPDecl = PDecl->getReferencedProtocols();
+  for (int i = 0; i < PDecl->getNumReferencedProtocols(); i++)
+    CheckProtocolMethodDefs(objSema, RefPDecl[i], InsMap, ClsMap);
+}
+
+static void ImplMethodsVsClassMethods(Sema* objSema, 
+                                     ObjcImplementationDecl* IMPDecl, 
+                                      ObjcInterfaceDecl* IDecl) {
+  llvm::DenseMap<const SelectorInfo*, char> InsMap;
   // Check and see if instance methods in class interface have been
   // implemented in the implementation class.
   ObjcMethodDecl **methods = IMPDecl->getInsMethods();
   for (int i=0; i < IMPDecl->getNumInsMethods(); i++) {
-    Map[methods[i]->getSelector()] = 'a';
+    InsMap[methods[i]->getSelector()] = 'a';
   }
   
   methods = IDecl->getInsMethods();
   for (int j = 0; j < IDecl->getNumInsMethods(); j++)
-    if (!Map.count(methods[j]->getSelector())) {
+    if (!InsMap.count(methods[j]->getSelector())) {
       llvm::SmallString<128> buf;
-      Diag(methods[j]->getLocation(), diag::warn_undef_method_impl,
-           methods[j]->getSelector()->getName(buf));
+      objSema->Diag(methods[j]->getLocation(), diag::warn_undef_method_impl,
+                   methods[j]->getSelector()->getName(buf));
     }
-  Map.clear();
+  llvm::DenseMap<const SelectorInfo*, char> ClsMap;
   // Check and see if class methods in class interface have been
   // implemented in the implementation class.
   methods = IMPDecl->getClsMethods();
   for (int i=0; i < IMPDecl->getNumClsMethods(); i++) {
-    Map[methods[i]->getSelector()] = 'a';
+    ClsMap[methods[i]->getSelector()] = 'a';
   }
   
   methods = IDecl->getClsMethods();
   for (int j = 0; j < IDecl->getNumClsMethods(); j++)
-    if (!Map.count(methods[j]->getSelector())) {
+    if (!ClsMap.count(methods[j]->getSelector())) {
       llvm::SmallString<128> buf;
-      Diag(methods[j]->getLocation(), diag::warn_undef_method_impl,
-           methods[j]->getSelector()->getName(buf));
+      objSema->Diag(methods[j]->getLocation(), diag::warn_undef_method_impl,
+                   methods[j]->getSelector()->getName(buf));
     }
+  
+  // Check the protocol list for unimplemented methods in the @implementation
+  // class.
+  ObjcProtocolDecl** protocols = IDecl->getIntfRefProtocols();
+  for (int i = 0; i < IDecl->getNumIntfRefProtocols(); i++) {
+    ObjcProtocolDecl* PDecl = protocols[i];
+    CheckProtocolMethodDefs(objSema, PDecl, InsMap, ClsMap);
+  }
   return;
 }
 
@@ -1612,7 +1642,7 @@ void Sema::ObjcAddMethodsToClass(DeclTy *ClassDecl,
     ObjcInterfaceDecl* IDecl = 
        Context.getObjCInterfaceDecl(ImplClass->getIdentifier());
     if (IDecl)
-      ActOnImplMethodsVsClassMethods(ImplClass, IDecl);
+      ImplMethodsVsClassMethods(this, ImplClass, IDecl);
   }
   else
     assert(0 && "Sema::ObjcAddMethodsToClass(): Unknown DeclTy");
index b3c30e5334988ecef104aec64a88bb021045a8a7..dddd2739625af00d736ab0a60c5bbe77e068f1d6 100644 (file)
@@ -588,6 +588,10 @@ public:
       NumIntfRefProtocols = numRefProtos;
     }
   }
+  
+  ObjcProtocolDecl **getIntfRefProtocols() const { return IntfRefProtocols; }
+  int getNumIntfRefProtocols() const { return NumIntfRefProtocols; }
+  
   ObjcIvarDecl **getIntfDeclIvars() const { return Ivars; }
   int getIntfDeclNumIvars() const { return NumIvars; }
   
@@ -776,6 +780,16 @@ public:
     ReferencedProtocols[idx] = OID;
   }
   
+  ObjcProtocolDecl** getReferencedProtocols() const { 
+    return ReferencedProtocols; 
+  }
+  int getNumReferencedProtocols() const { return NumReferencedProtocols; }
+  
+  ObjcMethodDecl** getInsMethods() const { return ProtoInsMethods; }
+  int getNumInsMethods() const { return NumProtoInsMethods; }
+  
+  ObjcMethodDecl** getClsMethods() const { return ProtoClsMethods; }
+  int getNumClsMethods() const { return NumProtoClsMethods; }
   
   bool getIsForwardProtoDecl() const { return isForwardProtoDecl; }
   void setIsForwardProtoDecl(bool val) { isForwardProtoDecl = val; }
index 48ae4bea844fdd426211647b87e2046234e00138..3e9a687ef4fd97467c456b9d569cd86cb3d99fe7 100644 (file)
@@ -451,10 +451,6 @@ public:
                                           DeclTy **Fields, unsigned NumFields) {
     return;
   }
-  virtual void ActOnImplMethodsVsClassMethods(DeclTy *ImplClassDecl, 
-                                             DeclTy *ClassDecl) {
-    return;
-  }
   virtual DeclTy *ObjcStartProtoInterface(Scope* S,
                    SourceLocation AtProtoInterfaceLoc,
                     IdentifierInfo *ProtocolName, SourceLocation ProtocolLoc,
diff --git a/test/Sema/undef-protocol-methods-1.m b/test/Sema/undef-protocol-methods-1.m
new file mode 100644 (file)
index 0000000..60203fc
--- /dev/null
@@ -0,0 +1,31 @@
+@protocol P1
+- (void) P1proto; // expected-warning {{method definition for 'P1proto' not found}}
++ (void) ClsP1Proto; // expected-warning {{method definition for 'ClsP1Proto' not found}}
+- (void) DefP1proto;
+@end
+@protocol P2
+- (void) P2proto;  // expected-warning {{method definition for 'P2proto' not found}}
++ (void) ClsP2Proto; // expected-warning {{method definition for 'ClsP2Proto' not found}}
+@end
+
+@protocol P3<P2>
+- (void) P3proto; // expected-warning {{method definition for 'P3proto' not found}}
++ (void) ClsP3Proto; // expected-warning {{method definition for 'ClsP3Proto' not found}}
++ (void) DefClsP3Proto;
+@end
+
+@protocol PROTO<P1, P3>
+- (void) meth;                 // expected-warning {{method definition for 'meth' not found
+- (void) meth : (int) arg1;    // expected-warning {{method definition for 'meth:' not found
++ (void) cls_meth : (int) arg1; // expected-warning {{method definition for 'cls_meth:' not found
+@end
+
+@interface INTF <PROTO>
+@end
+
+@implementation INTF
+- (void) DefP1proto{}
+
++ (void) DefClsP3Proto{}
+
+@end