diff options
Diffstat (limited to 'clang')
-rw-r--r-- | clang/include/clang/Basic/DiagnosticSemaKinds.td | 6 | ||||
-rw-r--r-- | clang/include/clang/Sema/Sema.h | 3 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclObjC.cpp | 70 | ||||
-rw-r--r-- | clang/test/SemaObjC/dist-object-modifiers.m | 21 |
4 files changed, 79 insertions, 21 deletions
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 979ffb28dae..30a35af8a95 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/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<DiagGroup<"method-signatures">>, 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<DiagGroup<"method-signatures">>, DefaultIgnore; diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index d25c0c3e978..2644b0f4c76 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/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/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp index 66f6f2b960d..652318f7204 100644 --- a/clang/lib/Sema/SemaDeclObjC.cpp +++ b/clang/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<ObjCObjectPointerType>()) { if (const ObjCObjectPointerType *IfacePtrTy = - MethodIface->getResultType()->getAs<ObjCObjectPointerType>()) { + MethodDecl->getResultType()->getAs<ObjCObjectPointerType>()) { // 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<Selector> &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<ObjCProtocolDecl>(CDecl)); } } @@ -1085,9 +1114,10 @@ void Sema::MatchAllMethodDeclarations(const llvm::DenseSet<Selector> &InsMap, } else { ObjCMethodDecl *ImpMethodDecl = IMPDecl->getClassMethod((*I)->getSelector()); - ObjCMethodDecl *IntfMethodDecl = + ObjCMethodDecl *MethodDecl = CDecl->getClassMethod((*I)->getSelector()); - WarnConflictingTypedMethods(ImpMethodDecl, IntfMethodDecl); + WarnConflictingTypedMethods(ImpMethodDecl, MethodDecl, + isa<ObjCProtocolDecl>(CDecl)); } } diff --git a/clang/test/SemaObjC/dist-object-modifiers.m b/clang/test/SemaObjC/dist-object-modifiers.m new file mode 100644 index 00000000000..f758b3f3321 --- /dev/null +++ b/clang/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 <P> +- (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 |