]> granicus.if.org Git - clang/commitdiff
Some code refactoring. Be more generous in issuance of warning
authorFariborz Jahanian <fjahanian@apple.com>
Tue, 4 Aug 2009 17:01:09 +0000 (17:01 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Tue, 4 Aug 2009 17:01:09 +0000 (17:01 +0000)
on method type mismatches per Chris's comment.

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

lib/Sema/SemaDeclObjC.cpp
test/SemaObjC/warn-superclass-method-mismatch.m

index 0ee0ad730f38baa617595fcf47d73f138b651170..809f3ee2a21aac11dd536760055e143cc4f90f51 100644 (file)
@@ -1464,35 +1464,41 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property,
     AddInstanceMethodToGlobalPool(SetterMethod);     
 }
 
+/// CompareMethodParamsInBaseAndSuper - This routine compares methods with
+/// identical selector names in current and its super classes and issues
+/// a warning if any of their argument types are incompatible.
 void Sema::CompareMethodParamsInBaseAndSuper(Decl *ClassDecl,
                                              ObjCMethodDecl *Method,
                                              bool IsInstance)  {
-  if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(ClassDecl))
-    while (ObjCInterfaceDecl *SD = ID->getSuperClass()) {
-      if (ObjCMethodDecl *SuperMethodDecl = 
-          SD->lookupMethod(Method->getSelector(), IsInstance)) {
-        ObjCMethodDecl::param_iterator ParamI = Method->param_begin(),
-        E = Method->param_end();
-        ObjCMethodDecl::param_iterator PrevI = 
-        SuperMethodDecl->param_begin();
-        for (; ParamI != E; ++ParamI, ++PrevI) {
-          assert(PrevI != SuperMethodDecl->param_end() && "Param mismatch");
-          QualType T1 = Context.getCanonicalType((*ParamI)->getType());
-          QualType T2 = Context.getCanonicalType((*PrevI)->getType());
-          if (T1 != T2) {
-            AssignConvertType ConvTy = CheckAssignmentConstraints(T1, T2);
-            if (ConvTy == Incompatible || ConvTy == IncompatiblePointer) {
-              Diag((*ParamI)->getLocation(), diag::ext_typecheck_base_super) 
-                << T1 << T2;
-              Diag(SuperMethodDecl->getLocation(), 
-                   diag::note_previous_declaration);
-              return;
-            }
-          }
-        }
-      }
+  ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(ClassDecl);
+  if (ID == 0) return;
+  
+  while (ObjCInterfaceDecl *SD = ID->getSuperClass()) {
+    ObjCMethodDecl *SuperMethodDecl = 
+        SD->lookupMethod(Method->getSelector(), IsInstance);
+    if (SuperMethodDecl == 0) {
       ID = SD;
+      continue;
     }
+    ObjCMethodDecl::param_iterator ParamI = Method->param_begin(),
+      E = Method->param_end();
+    ObjCMethodDecl::param_iterator PrevI = SuperMethodDecl->param_begin();
+    for (; ParamI != E; ++ParamI, ++PrevI) {
+      // Number of parameters are the same and is guaranteed by selector match.
+      assert(PrevI != SuperMethodDecl->param_end() && "Param mismatch");
+      QualType T1 = Context.getCanonicalType((*ParamI)->getType());
+      QualType T2 = Context.getCanonicalType((*PrevI)->getType());
+      // If type of arguement of method in this class does not match its
+      // respective argument type in the super class method, issue warning;
+      if (!Context.typesAreCompatible(T1, T2)) {
+        Diag((*ParamI)->getLocation(), diag::ext_typecheck_base_super) 
+          << T1 << T2;
+        Diag(SuperMethodDecl->getLocation(), diag::note_previous_declaration);
+        return;
+      }
+    }
+    ID = SD;
+  }
 }
 
 // Note: For class/category implemenations, allMethods/allProperties is
@@ -1540,6 +1546,8 @@ void Sema::ActOnAtEnd(SourceLocation AtEndLoc, DeclPtrTy classDecl,
         InsMap[Method->getSelector()] = Method;
         /// The following allows us to typecheck messages to "id".
         AddInstanceMethodToGlobalPool(Method);
+        // verify that the instance method conforms to the same definition of 
+        // parent methods if it shadows one.
         CompareMethodParamsInBaseAndSuper(ClassDecl, Method, true);
       }
     }
@@ -1558,6 +1566,8 @@ void Sema::ActOnAtEnd(SourceLocation AtEndLoc, DeclPtrTy classDecl,
         ClsMap[Method->getSelector()] = Method;
         /// The following allows us to typecheck messages to "Class".
         AddFactoryMethodToGlobalPool(Method);
+        // verify that the class method conforms to the same definition of 
+        // parent methods if it shadows one.
         CompareMethodParamsInBaseAndSuper(ClassDecl, Method, false);
       }
     }
index eb75eade0a1d31c3c6280a88d3ad5006e835c8c4..5efe3e8d10e269a8fd3b4b5da41b51798713ca1c 100644 (file)
@@ -12,6 +12,8 @@
 -(void) method2: (Sub*) x;
 + method3: (int)x1 : (Base *)x2 : (float)x3; // expected-note {{previous declaration is here}}
 + mathod4: (id)x1;
+- method5: (int) x : (double) d; // expected-note {{previous declaration is here}}
+- method6: (int) x : (float) d; // expected-note {{previous declaration is here}}
 @end
 
 struct A {
@@ -25,6 +27,8 @@ struct A {
 + method3: (int)x1 : (Sub *)x2 : (float)x3;    // expected-warning {{method parameter type 'Sub *' does not match super class method parameter type 'Base *'}}
 + mathod4: (Base*)x1;
 -(void) method_r: (char)ch : (float*)f1 : (Sub*) x; // expected-warning {{method parameter type 'Sub *' does not match super class method parameter type 'int *'}}
+- method5: (int) x : (float) d; // expected-warning {{method parameter type 'float' does not match super class method parameter type 'double'}}
+- method6: (int) x : (double) d; // expected-warning {{method parameter type 'double' does not match super class method parameter type 'float'}}
 @end
 
 void f(Base *base, Sub *sub) {