]> granicus.if.org Git - clang/commitdiff
ObjectiveC: Don't warn when method implemented in
authorFariborz Jahanian <fjahanian@apple.com>
Thu, 5 Dec 2013 20:52:31 +0000 (20:52 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Thu, 5 Dec 2013 20:52:31 +0000 (20:52 +0000)
category is declared in category's primary
class's super class. Because the super class is
expected to implemented the method. // rdar://15580969

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

lib/Sema/SemaDeclObjC.cpp
test/SemaObjC/incomplete-implementation.m

index 6020473e9794f0b2468f53cc3daa8998eb3ccae4..421b797c794f1aa94058adb194b9fbf3b6a13df0 100644 (file)
@@ -1867,27 +1867,39 @@ void Sema::MatchAllMethodDeclarations(const SelectorSet &InsMap,
 /// warns each time an exact match is found. 
 void Sema::CheckCategoryVsClassMethodMatches(
                                   ObjCCategoryImplDecl *CatIMPDecl) {
+  // Get category's primary class.
+  ObjCCategoryDecl *CatDecl = CatIMPDecl->getCategoryDecl();
+  if (!CatDecl)
+    return;
+  ObjCInterfaceDecl *IDecl = CatDecl->getClassInterface();
+  if (!IDecl)
+    return;
+  ObjCInterfaceDecl *SuperIDecl = IDecl->getSuperClass();
   SelectorSet InsMap, ClsMap;
   
   for (ObjCImplementationDecl::instmeth_iterator
        I = CatIMPDecl->instmeth_begin(), 
-       E = CatIMPDecl->instmeth_end(); I!=E; ++I)
-    InsMap.insert((*I)->getSelector());
+       E = CatIMPDecl->instmeth_end(); I!=E; ++I) {
+    Selector Sel = (*I)->getSelector();
+    // When checking for methods implemented in the category, skip over
+    // those declared in category class's super class. This is because
+    // the super class must implement the method.
+    if (SuperIDecl && SuperIDecl->lookupMethod(Sel, true))
+      continue;
+    InsMap.insert(Sel);
+  }
   
   for (ObjCImplementationDecl::classmeth_iterator
        I = CatIMPDecl->classmeth_begin(),
-       E = CatIMPDecl->classmeth_end(); I != E; ++I)
-    ClsMap.insert((*I)->getSelector());
+       E = CatIMPDecl->classmeth_end(); I != E; ++I) {
+    Selector Sel = (*I)->getSelector();
+    if (SuperIDecl && SuperIDecl->lookupMethod(Sel, false))
+      continue;
+    ClsMap.insert(Sel);
+  }
   if (InsMap.empty() && ClsMap.empty())
     return;
   
-  // Get category's primary class.
-  ObjCCategoryDecl *CatDecl = CatIMPDecl->getCategoryDecl();
-  if (!CatDecl)
-    return;
-  ObjCInterfaceDecl *IDecl = CatDecl->getClassInterface();
-  if (!IDecl)
-    return;
   SelectorSet InsMapSeen, ClsMapSeen;
   bool IncompleteImpl = false;
   MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen,
index 4b8d600cb8b49176597350c5716d1e09559c8091..74dea2aa86b9929114fac00682da40095636ba6d 100644 (file)
@@ -39,3 +39,29 @@ __attribute__((visibility("default")))
 
 @end
 
+// rdar://15580969
+typedef char BOOL;
+
+@protocol NSObject
+- (BOOL)isEqual:(id)object;
+@end
+
+@interface NSObject <NSObject>
+@end
+
+@protocol NSApplicationDelegate <NSObject>
+- (void)ImpleThisMethod; // expected-note {{method 'ImpleThisMethod' declared here}}
+@end
+
+@interface AppDelegate : NSObject <NSApplicationDelegate>
+@end
+
+@implementation AppDelegate (MRRCategory)
+
+- (BOOL)isEqual:(id)object
+{
+    return __objc_no;
+}
+
+- (void)ImpleThisMethod {} // expected-warning {{category is implementing a method which will also be implemented by its primary class}}
+@end