From: Fariborz Jahanian Date: Mon, 21 Feb 2011 23:49:15 +0000 (+0000) Subject: Warn when type modifiers on objc method declarations in X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=21761c8378a493c32ab0f7d2b8880986a0ba73a3;p=clang Warn when type modifiers on objc method declarations in protocols do not match with method implementation. // rdar://7076235 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@126162 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 979ffb28da..30a35af8a9 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -351,12 +351,18 @@ def note_required_for_protocol_at : def warn_conflicting_ret_types : Warning< "conflicting return type in implementation of %0: %1 vs %2">; +def warn_conflicting_ret_type_modifiers : Warning< + "conflicting distributed object modifiers on return type " + "in implementation of %0">; def warn_non_covariant_ret_types : Warning< "conflicting return type in implementation of %0: %1 vs %2">, InGroup>, DefaultIgnore; def warn_conflicting_param_types : Warning< "conflicting parameter types in implementation of %0: %1 vs %2">; +def warn_conflicting_param_modifiers : Warning< + "conflicting distributed object modifiers on patameter type " + "in implementation of %0">; def warn_non_contravariant_param_types : Warning< "conflicting parameter types in implementation of %0: %1 vs %2">, InGroup>, DefaultIgnore; diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index d25c0c3e97..2644b0f4c7 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -1523,7 +1523,8 @@ public: void WarnUndefinedMethod(SourceLocation ImpLoc, ObjCMethodDecl *method, bool &IncompleteImpl, unsigned DiagID); void WarnConflictingTypedMethods(ObjCMethodDecl *ImpMethod, - ObjCMethodDecl *IntfMethod); + ObjCMethodDecl *MethodDecl, + bool IsProtocolMethodDecl); bool isPropertyReadonly(ObjCPropertyDecl *PropertyDecl, ObjCInterfaceDecl *IDecl); diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index 66f6f2b960..652318f720 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -856,9 +856,21 @@ static SourceRange getTypeRange(TypeSourceInfo *TSI) { static void CheckMethodOverrideReturn(Sema &S, ObjCMethodDecl *MethodImpl, - ObjCMethodDecl *MethodIface) { + ObjCMethodDecl *MethodDecl, + bool IsProtocolMethodDecl) { + if (IsProtocolMethodDecl && + (MethodDecl->getObjCDeclQualifier() != + MethodImpl->getObjCDeclQualifier())) { + S.Diag(MethodImpl->getLocation(), + diag::warn_conflicting_ret_type_modifiers) + << MethodImpl->getDeclName() + << getTypeRange(MethodImpl->getResultTypeSourceInfo()); + S.Diag(MethodDecl->getLocation(), diag::note_previous_declaration) + << getTypeRange(MethodDecl->getResultTypeSourceInfo()); + } + if (S.Context.hasSameUnqualifiedType(MethodImpl->getResultType(), - MethodIface->getResultType())) + MethodDecl->getResultType())) return; unsigned DiagID = diag::warn_conflicting_ret_types; @@ -868,7 +880,7 @@ static void CheckMethodOverrideReturn(Sema &S, if (const ObjCObjectPointerType *ImplPtrTy = MethodImpl->getResultType()->getAs()) { if (const ObjCObjectPointerType *IfacePtrTy = - MethodIface->getResultType()->getAs()) { + MethodDecl->getResultType()->getAs()) { // Allow non-matching return types as long as they don't violate // the principle of substitutability. Specifically, we permit // return types that are subclasses of the declared return type, @@ -882,20 +894,33 @@ static void CheckMethodOverrideReturn(Sema &S, S.Diag(MethodImpl->getLocation(), DiagID) << MethodImpl->getDeclName() - << MethodIface->getResultType() + << MethodDecl->getResultType() << MethodImpl->getResultType() << getTypeRange(MethodImpl->getResultTypeSourceInfo()); - S.Diag(MethodIface->getLocation(), diag::note_previous_definition) - << getTypeRange(MethodIface->getResultTypeSourceInfo()); + S.Diag(MethodDecl->getLocation(), diag::note_previous_definition) + << getTypeRange(MethodDecl->getResultTypeSourceInfo()); } static void CheckMethodOverrideParam(Sema &S, ObjCMethodDecl *MethodImpl, - ObjCMethodDecl *MethodIface, + ObjCMethodDecl *MethodDecl, ParmVarDecl *ImplVar, - ParmVarDecl *IfaceVar) { + ParmVarDecl *IfaceVar, + bool IsProtocolMethodDecl) { + if (IsProtocolMethodDecl && + (ImplVar->getObjCDeclQualifier() != + IfaceVar->getObjCDeclQualifier())) { + S.Diag(ImplVar->getLocation(), + diag::warn_conflicting_param_modifiers) + << getTypeRange(ImplVar->getTypeSourceInfo()) + << MethodImpl->getDeclName(); + S.Diag(IfaceVar->getLocation(), diag::note_previous_declaration) + << getTypeRange(IfaceVar->getTypeSourceInfo()); + } + QualType ImplTy = ImplVar->getType(); QualType IfaceTy = IfaceVar->getType(); + if (S.Context.hasSameUnqualifiedType(ImplTy, IfaceTy)) return; @@ -927,17 +952,20 @@ static void CheckMethodOverrideParam(Sema &S, void Sema::WarnConflictingTypedMethods(ObjCMethodDecl *ImpMethodDecl, - ObjCMethodDecl *IntfMethodDecl) { - CheckMethodOverrideReturn(*this, ImpMethodDecl, IntfMethodDecl); + ObjCMethodDecl *MethodDecl, + bool IsProtocolMethodDecl) { + CheckMethodOverrideReturn(*this, ImpMethodDecl, MethodDecl, + IsProtocolMethodDecl); for (ObjCMethodDecl::param_iterator IM = ImpMethodDecl->param_begin(), - IF = IntfMethodDecl->param_begin(), EM = ImpMethodDecl->param_end(); + IF = MethodDecl->param_begin(), EM = ImpMethodDecl->param_end(); IM != EM; ++IM, ++IF) - CheckMethodOverrideParam(*this, ImpMethodDecl, IntfMethodDecl, *IM, *IF); + CheckMethodOverrideParam(*this, ImpMethodDecl, MethodDecl, *IM, *IF, + IsProtocolMethodDecl); - if (ImpMethodDecl->isVariadic() != IntfMethodDecl->isVariadic()) { + if (ImpMethodDecl->isVariadic() != MethodDecl->isVariadic()) { Diag(ImpMethodDecl->getLocation(), diag::warn_conflicting_variadic); - Diag(IntfMethodDecl->getLocation(), diag::note_previous_declaration); + Diag(MethodDecl->getLocation(), diag::note_previous_declaration); } } @@ -1061,13 +1089,14 @@ void Sema::MatchAllMethodDeclarations(const llvm::DenseSet &InsMap, } else { ObjCMethodDecl *ImpMethodDecl = IMPDecl->getInstanceMethod((*I)->getSelector()); - ObjCMethodDecl *IntfMethodDecl = + ObjCMethodDecl *MethodDecl = CDecl->getInstanceMethod((*I)->getSelector()); - assert(IntfMethodDecl && - "IntfMethodDecl is null in ImplMethodsVsClassMethods"); + assert(MethodDecl && + "MethodDecl is null in ImplMethodsVsClassMethods"); // ImpMethodDecl may be null as in a @dynamic property. if (ImpMethodDecl) - WarnConflictingTypedMethods(ImpMethodDecl, IntfMethodDecl); + WarnConflictingTypedMethods(ImpMethodDecl, MethodDecl, + isa(CDecl)); } } @@ -1085,9 +1114,10 @@ void Sema::MatchAllMethodDeclarations(const llvm::DenseSet &InsMap, } else { ObjCMethodDecl *ImpMethodDecl = IMPDecl->getClassMethod((*I)->getSelector()); - ObjCMethodDecl *IntfMethodDecl = + ObjCMethodDecl *MethodDecl = CDecl->getClassMethod((*I)->getSelector()); - WarnConflictingTypedMethods(ImpMethodDecl, IntfMethodDecl); + WarnConflictingTypedMethods(ImpMethodDecl, MethodDecl, + isa(CDecl)); } } diff --git a/test/SemaObjC/dist-object-modifiers.m b/test/SemaObjC/dist-object-modifiers.m new file mode 100644 index 0000000000..f758b3f332 --- /dev/null +++ b/test/SemaObjC/dist-object-modifiers.m @@ -0,0 +1,21 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +// rdar://7076235 + +@protocol P +- (bycopy id)serverPID; // expected-note {{previous declaration is here}} +- (void)doStuff:(bycopy id)clientId; // expected-note {{previous declaration is here}} +- (bycopy id)Ok; ++ (oneway id) stillMore : (byref id)Arg : (bycopy oneway id)Arg1; // expected-note 3 {{previous declaration is here}} +@end + +@interface I

+- (id)Ok; +@end + +@implementation I +- (id)serverPID { return 0; } // expected-warning {{conflicting distributed object modifiers on return type in implementation of 'serverPID'}} +- (void)doStuff:(id)clientId { } // expected-warning {{conflicting distributed object modifiers on patameter type in implementation of 'doStuff:'}} +- (bycopy id)Ok { return 0; } ++ (id) stillMore : (id)Arg : (bycopy id)Arg1 { return Arg; } // expected-warning {{conflicting distributed object modifiers on return type in implementation of 'stillMore::'}} \ + // expected-warning 2{{conflicting distributed object modifiers on patameter type in implementation of 'stillMore::'}} +@end