]> granicus.if.org Git - clang/commitdiff
Warn when type modifiers on objc method declarations in
authorFariborz Jahanian <fjahanian@apple.com>
Mon, 21 Feb 2011 23:49:15 +0000 (23:49 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Mon, 21 Feb 2011 23:49:15 +0000 (23:49 +0000)
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

include/clang/Basic/DiagnosticSemaKinds.td
include/clang/Sema/Sema.h
lib/Sema/SemaDeclObjC.cpp
test/SemaObjC/dist-object-modifiers.m [new file with mode: 0644]

index 979ffb28dae5772c1d09d822c6b9b83cf67cf002..30a35af8a95a82e9c79d61c1ccd569dac473c896 100644 (file)
@@ -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;
index d25c0c3e978ef512235bf1878c15dfdc6be2678b..2644b0f4c768c35bdacc0ce5ff684de77b762dea 100644 (file)
@@ -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);
index 66f6f2b960d190a0cb9209ca2ebc25db37dae0a1..652318f7204ee621f5bb98ad669a0b1b00392921 100644 (file)
@@ -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/test/SemaObjC/dist-object-modifiers.m b/test/SemaObjC/dist-object-modifiers.m
new file mode 100644 (file)
index 0000000..f758b3f
--- /dev/null
@@ -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