]> granicus.if.org Git - clang/commitdiff
Check for method type conflict between declaration in
authorFariborz Jahanian <fjahanian@apple.com>
Fri, 1 May 2009 20:07:12 +0000 (20:07 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Fri, 1 May 2009 20:07:12 +0000 (20:07 +0000)
class/protocol and implementation which could be
an imm. implementation or down in the inheritance
hierarchy.

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

lib/Sema/Sema.h
lib/Sema/SemaDeclObjC.cpp
test/Analysis/PR2978.m
test/SemaObjC/method-typecheck-2.m [new file with mode: 0644]
test/SemaObjC/props-on-prots.m
test/SemaObjC/protocol-lookup.m
test/SemaObjCXX/protocol-lookup.mm

index e4746372a51aa525ba761d19f129c6257333db67..b323d0ebe957aea83ca8423f01c4de46c6a45e8e 100644 (file)
@@ -1114,6 +1114,17 @@ public:
                                   const ObjCMethodDecl *PrevMethod,
                                   bool matchBasedOnSizeAndAlignment = false); 
 
+  /// MatchAllMethodDeclarations - Check methods declaraed in interface or
+  /// or protocol against those declared in their implementations.
+  void MatchAllMethodDeclarations(const llvm::DenseSet<Selector> &InsMap,
+                                  const llvm::DenseSet<Selector> &ClsMap,
+                                  llvm::DenseSet<Selector> &InsMapSeen,
+                                  llvm::DenseSet<Selector> &ClsMapSeen,
+                                  ObjCImplDecl* IMPDecl,
+                                  ObjCContainerDecl* IDecl,
+                                  bool &IncompleteImpl,
+                                  bool ImmediateClass);
+
   /// AddInstanceMethodToGlobalPool - All instance methods in a translation
   /// unit are added to a global pool. This allows us to efficiently associate
   /// a selector with a method declaraation for purposes of typechecking
index 0c98a5f44b453e275eda79191313aab2bbc82c7f..80b30bdb74c223787c0ac08183c6f3e32e72e6a3 100644 (file)
@@ -885,6 +885,79 @@ void Sema::CheckProtocolMethodDefs(SourceLocation ImpLoc,
     CheckProtocolMethodDefs(ImpLoc, *PI, IncompleteImpl, InsMap, ClsMap, IDecl);
 }
 
+/// MatchAllMethodDeclarations - Check methods declaraed in interface or
+/// or protocol against those declared in their implementations.
+///
+void Sema::MatchAllMethodDeclarations(const llvm::DenseSet<Selector> &InsMap,
+                                      const llvm::DenseSet<Selector> &ClsMap,
+                                      llvm::DenseSet<Selector> &InsMapSeen,
+                                      llvm::DenseSet<Selector> &ClsMapSeen,
+                                      ObjCImplDecl* IMPDecl,
+                                      ObjCContainerDecl* CDecl,
+                                      bool &IncompleteImpl,
+                                      bool ImmediateClass)
+{
+  // Check and see if instance methods in class interface have been
+  // implemented in the implementation class. If so, their types match.
+  for (ObjCInterfaceDecl::instmeth_iterator I = CDecl->instmeth_begin(Context),
+       E = CDecl->instmeth_end(Context); I != E; ++I) {
+    if (InsMapSeen.count((*I)->getSelector()))
+        continue;
+    InsMapSeen.insert((*I)->getSelector());
+    if (!(*I)->isSynthesized() && 
+        !InsMap.count((*I)->getSelector())) {
+      if (ImmediateClass)
+        WarnUndefinedMethod(IMPDecl->getLocation(), *I, IncompleteImpl);
+      continue;
+    }
+    else {
+      ObjCMethodDecl *ImpMethodDecl = 
+      IMPDecl->getInstanceMethod(Context, (*I)->getSelector());
+      ObjCMethodDecl *IntfMethodDecl = 
+      CDecl->getInstanceMethod(Context, (*I)->getSelector());
+      assert(IntfMethodDecl && 
+             "IntfMethodDecl is null in ImplMethodsVsClassMethods");
+      // ImpMethodDecl may be null as in a @dynamic property.
+      if (ImpMethodDecl)
+        WarnConflictingTypedMethods(ImpMethodDecl, IntfMethodDecl);
+    }
+  }
+  
+  // Check and see if class methods in class interface have been
+  // implemented in the implementation class. If so, their types match.
+   for (ObjCInterfaceDecl::classmeth_iterator 
+       I = CDecl->classmeth_begin(Context),
+       E = CDecl->classmeth_end(Context);
+        I != E; ++I) {
+     if (ClsMapSeen.count((*I)->getSelector()))
+       continue;
+     ClsMapSeen.insert((*I)->getSelector());
+    if (!ClsMap.count((*I)->getSelector())) {
+      if (ImmediateClass)
+        WarnUndefinedMethod(IMPDecl->getLocation(), *I, IncompleteImpl);
+    }
+    else {
+      ObjCMethodDecl *ImpMethodDecl = 
+      IMPDecl->getClassMethod(Context, (*I)->getSelector());
+      ObjCMethodDecl *IntfMethodDecl = 
+      CDecl->getClassMethod(Context, (*I)->getSelector());
+      WarnConflictingTypedMethods(ImpMethodDecl, IntfMethodDecl);
+    }
+  }
+  if (ObjCInterfaceDecl *I = dyn_cast<ObjCInterfaceDecl> (CDecl)) {
+    // Check for any implementation of a methods declared in protocol.
+    for (ObjCInterfaceDecl::protocol_iterator PI = I->protocol_begin(),
+         E = I->protocol_end(); PI != E; ++PI)
+      MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen, 
+                                 IMPDecl, 
+                                 (*PI), IncompleteImpl, false);
+    if (I->getSuperClass())
+      MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen,
+                                 IMPDecl, 
+                                 I->getSuperClass(), IncompleteImpl, false);
+  }
+}
+
 void Sema::ImplMethodsVsClassMethods(ObjCImplDecl* IMPDecl, 
                                      ObjCContainerDecl* CDecl, 
                                      bool IncompleteImpl) {
@@ -933,51 +1006,26 @@ void Sema::ImplMethodsVsClassMethods(ObjCImplDecl* IMPDecl,
         }
       }
   
-  for (ObjCInterfaceDecl::instmeth_iterator I = CDecl->instmeth_begin(Context),
-       E = CDecl->instmeth_end(Context); I != E; ++I) {
-    if (!(*I)->isSynthesized() && !InsMap.count((*I)->getSelector())) {
-      WarnUndefinedMethod(IMPDecl->getLocation(), *I, IncompleteImpl);
-      continue;
-    }
-    
-    ObjCMethodDecl *ImpMethodDecl = 
-      IMPDecl->getInstanceMethod(Context, (*I)->getSelector());
-    ObjCMethodDecl *IntfMethodDecl = 
-      CDecl->getInstanceMethod(Context, (*I)->getSelector());
-    assert(IntfMethodDecl && 
-           "IntfMethodDecl is null in ImplMethodsVsClassMethods");
-    // ImpMethodDecl may be null as in a @dynamic property.
-    if (ImpMethodDecl)
-      WarnConflictingTypedMethods(ImpMethodDecl, IntfMethodDecl);
-  }
-      
   llvm::DenseSet<Selector> ClsMap;
-  // Check and see if class methods in class interface have been
-  // implemented in the implementation class.
   for (ObjCImplementationDecl::classmeth_iterator 
-         I = IMPDecl->classmeth_begin(Context),
-         E = IMPDecl->classmeth_end(Context); I != E; ++I)
+       I = IMPDecl->classmeth_begin(Context),
+       E = IMPDecl->classmeth_end(Context); I != E; ++I)
     ClsMap.insert((*I)->getSelector());
   
-  for (ObjCInterfaceDecl::classmeth_iterator 
-         I = CDecl->classmeth_begin(Context),
-         E = CDecl->classmeth_end(Context);
-       I != E; ++I)
-    if (!ClsMap.count((*I)->getSelector()))
-      WarnUndefinedMethod(IMPDecl->getLocation(), *I, IncompleteImpl);
-    else {
-      ObjCMethodDecl *ImpMethodDecl = 
-        IMPDecl->getClassMethod(Context, (*I)->getSelector());
-      ObjCMethodDecl *IntfMethodDecl = 
-        CDecl->getClassMethod(Context, (*I)->getSelector());
-      WarnConflictingTypedMethods(ImpMethodDecl, IntfMethodDecl);
-    }
-  
+  // Check for type conflict of methods declared in a class/protocol and
+  // its implementation; if any.
+  llvm::DenseSet<Selector> InsMapSeen, ClsMapSeen;
+  MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen, 
+                             IMPDecl, CDecl, 
+                             IncompleteImpl, true);
   
   // Check the protocol list for unimplemented methods in the @implementation
   // class.
+  // Check and see if class methods in class interface have been
+  // implemented in the implementation class.
+  
   if (ObjCInterfaceDecl *I = dyn_cast<ObjCInterfaceDecl> (CDecl)) {
-    for (ObjCCategoryDecl::protocol_iterator PI = I->protocol_begin(),
+    for (ObjCInterfaceDecl::protocol_iterator PI = I->protocol_begin(),
          E = I->protocol_end(); PI != E; ++PI)
       CheckProtocolMethodDefs(IMPDecl->getLocation(), *PI, IncompleteImpl, 
                               InsMap, ClsMap, I);
index 2b4c9177745b232dab002372336d8c340b552d67..7bc90b8d03e0ae299ab448a3721d106cc741d4a4 100644 (file)
@@ -44,7 +44,7 @@
 -(id) O{ return 0; }
 -(void) setO:(id)arg { }
 
-- (void)dealloc
+- (id)dealloc
 {
   [_X release];
   [_Z release];
diff --git a/test/SemaObjC/method-typecheck-2.m b/test/SemaObjC/method-typecheck-2.m
new file mode 100644 (file)
index 0000000..d0a091d
--- /dev/null
@@ -0,0 +1,25 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+@protocol P
+- (void) doSomethingInProtocol: (float) x; // expected-note {{previous definition is here}}
++ (void) doSomethingClassyInProtocol: (float) x; // expected-note {{previous definition is here}}
+- (void) doNothingInProtocol : (float) x;
++ (void) doNothingClassyInProtocol : (float) x;
+@end
+
+@interface I <P>
+- (void) doSomething: (float) x; // expected-note {{previous definition is here}}
++ (void) doSomethingClassy: (int) x; // expected-note {{previous definition is here}}
+@end
+
+@interface Bar : I
+@end
+
+@implementation Bar
+- (void) doSomething: (int) x {} // expected-warning {{conflicting parameter types}}
++ (void) doSomethingClassy: (float) x{}  // expected-warning {{conflicting parameter types}}
+- (void) doSomethingInProtocol: (id) x {}  // expected-warning {{conflicting parameter types}}
++ (void) doSomethingClassyInProtocol: (id) x {}  // expected-warning {{conflicting parameter types}}
+@end
+
+
index a0c6e41f9d38c733fbaa3d3a0d6e015dd8670d79..7bee8a0bc319780edd82612ecef0025cf4013920 100644 (file)
@@ -21,7 +21,7 @@ typedef float CGFloat;
 typedef struct _XCElementInset {} XCElementInset;
 
 @protocol XCElementP < NSObject >
--(BOOL) vertical;
+-(id) vertical;
 @end
 
 @protocol XCElementDisplayDelegateP;
@@ -60,6 +60,6 @@ typedef NSObject < XCElementJustifierP > XCElementJustifier;
   if (_marker && _marker.variableSized) {
   }
 }
-- vertical { return self; }
+- (id)vertical { return self; }
 - (BOOL)isEqual:x { return 1; }
 @end
index 4f928229cd1c5a79691f06203d9d831f5f1913bf..0f1860d2c88edf0e4bfd99bf4ab7637ed28bbae9 100644 (file)
@@ -39,7 +39,7 @@
        return self;
 }
 
-- (void)dealloc
+- dealloc
 {
        [_foo release];
        [_bar release];
index 4f928229cd1c5a79691f06203d9d831f5f1913bf..0f1860d2c88edf0e4bfd99bf4ab7637ed28bbae9 100644 (file)
@@ -39,7 +39,7 @@
        return self;
 }
 
-- (void)dealloc
+- dealloc
 {
        [_foo release];
        [_bar release];