From: Fariborz Jahanian Date: Tue, 4 Aug 2009 17:01:09 +0000 (+0000) Subject: Some code refactoring. Be more generous in issuance of warning X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e198f5d609dda2b6d0435f040ebe2479a4e378ba;p=clang Some code refactoring. Be more generous in issuance of warning 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 --- diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index 0ee0ad730f..809f3ee2a2 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -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(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(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); } } diff --git a/test/SemaObjC/warn-superclass-method-mismatch.m b/test/SemaObjC/warn-superclass-method-mismatch.m index eb75eade0a..5efe3e8d10 100644 --- a/test/SemaObjC/warn-superclass-method-mismatch.m +++ b/test/SemaObjC/warn-superclass-method-mismatch.m @@ -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) {