]> granicus.if.org Git - clang/commitdiff
(instance/class) Method type checking between class and its implementation.
authorFariborz Jahanian <fjahanian@apple.com>
Fri, 5 Dec 2008 18:18:52 +0000 (18:18 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Fri, 5 Dec 2008 18:18:52 +0000 (18:18 +0000)
(instance/class) Method type checking between category and its implementation.
And a test case for all.

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

include/clang/Basic/DiagnosticKinds.def
lib/Sema/Sema.h
lib/Sema/SemaDeclObjC.cpp
test/SemaObjC/comptypes-a.m
test/SemaObjC/method-typecheck-1.m [new file with mode: 0644]

index eea6fe4b96990f933e2de0cd813dec245ea1e71a..31708b01124181714d7635364cdfe89a8af20ce3 100644 (file)
@@ -573,6 +573,8 @@ DIAG(err_accessor_property_type_mismatch, ERROR,
      "type of property %0 does not match type of accessor %1")
 DIAG(err_setter_type_void, ERROR,
      "type of setter must be void")
+DIAG(warn_conflicting_types, WARNING,
+     "conflicting types for %0")
 
 /// C++ parser diagnostics
 DIAG(err_expected_unqualified_id, ERROR,
index f1d0ee2da01fdf1ca92d315646989da61a6599f9..85cd2c873ba4bd8a1bd52f65ac27ee9766bacfb3 100644 (file)
@@ -490,6 +490,8 @@ public:
 
   void WarnUndefinedMethod(SourceLocation ImpLoc, ObjCMethodDecl *method,
                            bool &IncompleteImpl);
+  void WarnConflictingTypedMethods(ObjCMethodDecl *ImpMethod,
+                                   ObjCMethodDecl *IntfMethod);
 
   NamespaceDecl *GetStdNamespace();
                            
index 01a453d3be67026a2fd49392b1f6d408ecde66e4..a58d1da632270418d274f1a4a7549388bf226700 100644 (file)
@@ -590,6 +590,32 @@ void Sema::WarnUndefinedMethod(SourceLocation ImpLoc, ObjCMethodDecl *method,
   Diag(ImpLoc, diag::warn_undef_method_impl) << method->getDeclName();
 }
 
+void Sema::WarnConflictingTypedMethods(ObjCMethodDecl *ImpMethodDecl,
+                                       ObjCMethodDecl *IntfMethodDecl) {
+  bool err = false;
+  QualType ImpMethodQType = 
+    Context.getCanonicalType(ImpMethodDecl->getResultType());
+  QualType IntfMethodQType = 
+    Context.getCanonicalType(IntfMethodDecl->getResultType());
+  if (!Context.typesAreCompatible(IntfMethodQType, ImpMethodQType))
+    err = true;
+  else for (ObjCMethodDecl::param_iterator IM=ImpMethodDecl->param_begin(),
+            IF=IntfMethodDecl->param_begin(),
+            EM=ImpMethodDecl->param_end(); IM!=EM; ++IM, IF++) {
+    ImpMethodQType = Context.getCanonicalType((*IM)->getType());
+    IntfMethodQType = Context.getCanonicalType((*IF)->getType());
+    if (!Context.typesAreCompatible(IntfMethodQType, ImpMethodQType)) {
+      err = true;
+      break;
+    }
+  }
+  if (err) {
+    Diag(ImpMethodDecl->getLocation(), diag::warn_conflicting_types) 
+    << ImpMethodDecl->getDeclName();
+    Diag(IntfMethodDecl->getLocation(), diag::note_previous_definition);
+  }
+}
+
 /// FIXME: Type hierarchies in Objective-C can be deep. We could most
 /// likely improve the efficiency of selector lookups and type
 /// checking by associating with each protocol / interface / category
@@ -651,32 +677,12 @@ void Sema::ImplMethodsVsClassMethods(ObjCImplementationDecl* IMPDecl,
     if (!(*I)->isSynthesized() && !InsMap.count((*I)->getSelector()))
       WarnUndefinedMethod(IMPDecl->getLocation(), *I, IncompleteImpl);
     else if (!(*I)->isSynthesized()){
-      bool err = false;
       ObjCMethodDecl *ImpMethodDecl = 
         IMPDecl->getInstanceMethod((*I)->getSelector());
       ObjCMethodDecl *IntfMethodDecl = 
         IDecl->getInstanceMethod((*I)->getSelector());
-      QualType ImpMethodQType = 
-        Context.getCanonicalType(ImpMethodDecl->getResultType());
-      QualType IntfMethodQType = 
-        Context.getCanonicalType(IntfMethodDecl->getResultType());
-      if (!Context.typesAreCompatible(IntfMethodQType, ImpMethodQType))
-        err = true;
-      else for (ObjCMethodDecl::param_iterator IM=ImpMethodDecl->param_begin(),
-                IF=IntfMethodDecl->param_begin(),
-                EM=ImpMethodDecl->param_end(); IM!=EM; ++IM, IF++) {
-        ImpMethodQType = Context.getCanonicalType((*IM)->getType());
-        IntfMethodQType = Context.getCanonicalType((*IF)->getType());
-        if (!Context.typesAreCompatible(IntfMethodQType, ImpMethodQType)) {
-          err = true;
-          break;
-        }
-      }
-      if (err) {
-        Diag(ImpMethodDecl->getLocation(), diag::err_conflicting_types) 
-          << ImpMethodDecl->getDeclName();
-        Diag(IntfMethodDecl->getLocation(), diag::note_previous_definition);
-      }
+      WarnConflictingTypedMethods(ImpMethodDecl, IntfMethodDecl);
+      
     }
       
   llvm::DenseSet<Selector> ClsMap;
@@ -690,6 +696,14 @@ void Sema::ImplMethodsVsClassMethods(ObjCImplementationDecl* IMPDecl,
        E = IDecl->classmeth_end(); I != E; ++I)
     if (!ClsMap.count((*I)->getSelector()))
       WarnUndefinedMethod(IMPDecl->getLocation(), *I, IncompleteImpl);
+    else {
+      ObjCMethodDecl *ImpMethodDecl = 
+        IMPDecl->getClassMethod((*I)->getSelector());
+      ObjCMethodDecl *IntfMethodDecl = 
+        IDecl->getClassMethod((*I)->getSelector());
+      WarnConflictingTypedMethods(ImpMethodDecl, IntfMethodDecl);
+    }
+  
   
   // Check the protocol list for unimplemented methods in the @implementation
   // class.
@@ -717,6 +731,13 @@ void Sema::ImplCategoryMethodsVsIntfMethods(ObjCCategoryImplDecl *CatImplDecl,
        E = CatClassDecl->instmeth_end(); I != E; ++I)
     if (!InsMap.count((*I)->getSelector()))
       WarnUndefinedMethod(CatImplDecl->getLocation(), *I, IncompleteImpl);
+    else {
+      ObjCMethodDecl *ImpMethodDecl = 
+        CatImplDecl->getInstanceMethod((*I)->getSelector());
+      ObjCMethodDecl *IntfMethodDecl = 
+        CatClassDecl->getInstanceMethod((*I)->getSelector());
+      WarnConflictingTypedMethods(ImpMethodDecl, IntfMethodDecl);
+    }
 
   llvm::DenseSet<Selector> ClsMap;
   // Check and see if class methods in category interface have been
@@ -730,7 +751,13 @@ void Sema::ImplCategoryMethodsVsIntfMethods(ObjCCategoryImplDecl *CatImplDecl,
        E = CatClassDecl->classmeth_end(); I != E; ++I)
     if (!ClsMap.count((*I)->getSelector()))
       WarnUndefinedMethod(CatImplDecl->getLocation(), *I, IncompleteImpl);
-  
+    else {
+      ObjCMethodDecl *ImpMethodDecl = 
+        CatImplDecl->getClassMethod((*I)->getSelector());
+      ObjCMethodDecl *IntfMethodDecl = 
+        CatClassDecl->getClassMethod((*I)->getSelector());
+      WarnConflictingTypedMethods(ImpMethodDecl, IntfMethodDecl);
+    }
   // Check the protocol list for unimplemented methods in the @implementation
   // class.
   for (ObjCCategoryDecl::protocol_iterator PI = CatClassDecl->protocol_begin(),
index f00369f5cac5ebc870f6a476532ac456dff1a6f7..4abc9fdddbd862d73b0a9ba1478a6cf24031ac85 100644 (file)
@@ -23,7 +23,7 @@ NSInteger codeAssistantCaseCompareItems(id<PBXCompletionItem> a, id<PBXCompletio
 
 @implementation TedWantsToVerifyObjCDoesTheRightThing
 
-- compareThis:(id<PBXCompletionItem>)a withThat:(id<PBXCompletionItem>)b { // expected-error {{conflicting types for 'compareThis:withThat:'}}
+- compareThis:(id<PBXCompletionItem>)a withThat:(id<PBXCompletionItem>)b { // expected-warning {{conflicting types for 'compareThis:withThat:'}}
   return self;
 }
 
diff --git a/test/SemaObjC/method-typecheck-1.m b/test/SemaObjC/method-typecheck-1.m
new file mode 100644 (file)
index 0000000..3b1b0c9
--- /dev/null
@@ -0,0 +1,33 @@
+@interface A
+- (void) setMoo: (int) x;      //  expected-note {{previous definition is here}}
+- (int) setMoo1: (int) x;      //  expected-note {{previous definition is here}}
+- (int) setOk : (int) x : (double) d;
+@end
+
+@implementation A 
+-(void) setMoo: (float) x {}   //  expected-warning {{conflicting types for 'setMoo:'}}
+- (char) setMoo1: (int) x {}   //  expected-warning {{conflicting types for 'setMoo1:'}}
+- (int) setOk : (int) x : (double) d {}
+@end
+
+
+
+@interface C
++ (void) cMoo: (int) x;        //  expected-note {{previous definition is here}}
+@end
+
+@implementation C 
++(float) cMoo: (float) x {}    //  expected-warning {{conflicting types for 'cMoo:'}}
+@end
+
+
+@interface A(CAT)
+- (void) setCat: (int) x;      //  expected-note {{previous definition is here}}
++ (void) cCat: (int) x;        //  expected-note {{previous definition is here}}
+@end
+
+@implementation A(CAT) 
+-(float) setCat: (float) x {}  //  expected-warning {{conflicting types for 'setCat:'}}
++ (int) cCat: (int) x {}       //  expected-warning {{conflicting types for 'cCat:'}}
+@end
+