[cfe-commits] r137222 - in /cfe/trunk: include/clang/Basic/DiagnosticGroups.td include/clang/Basic/DiagnosticSemaKinds.td include/clang/Basic/IdentifierTable.h include/clang/Sema/Sema.h lib/Sema/SemaDeclObjC.cpp test/SemaObjC/class-protocol-method-match.m test/SemaObjC/dist-object-modifiers.m test/SemaObjC/qualified-protocol-method-conflicts.m

Fariborz Jahanian fjahanian at apple.com
Wed Aug 10 10:16:30 PDT 2011


Author: fjahanian
Date: Wed Aug 10 12:16:30 2011
New Revision: 137222

URL: http://llvm.org/viewvc/llvm-project?rev=137222&view=rev
Log:
objective-c: Using existing infrastructure for finding 
overridden  methods to diagnose their type mismatch.
This is a general solution for previous fixes
for // rdar://6191214 and // rdar://9352731
and removes lots of duplicate code.

Modified:
    cfe/trunk/include/clang/Basic/DiagnosticGroups.td
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/include/clang/Basic/IdentifierTable.h
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaDeclObjC.cpp
    cfe/trunk/test/SemaObjC/class-protocol-method-match.m
    cfe/trunk/test/SemaObjC/dist-object-modifiers.m
    cfe/trunk/test/SemaObjC/qualified-protocol-method-conflicts.m

Modified: cfe/trunk/include/clang/Basic/DiagnosticGroups.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticGroups.td?rev=137222&r1=137221&r2=137222&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticGroups.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticGroups.td Wed Aug 10 12:16:30 2011
@@ -187,6 +187,7 @@
 def NonfragileAbi2 : DiagGroup<"nonfragile-abi2">;
 def Protocol : DiagGroup<"protocol">;
 def SuperSubClassMismatch : DiagGroup<"super-class-method-mismatch">;
+def OverridingMethodMismatch : DiagGroup<"overriding-method-mismatch">;
 def : DiagGroup<"variadic-macros">;
 def VariadicMacros : DiagGroup<"variadic-macros">;
 def VectorConversions : DiagGroup<"vector-conversions">;      // clang specific

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=137222&r1=137221&r2=137222&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Wed Aug 10 12:16:30 2011
@@ -383,32 +383,72 @@
 def note_required_for_protocol_at : 
   Note<"required for direct or indirect protocol %0">;
 
+def warn_conflicting_overriding_ret_types : Warning<
+  "conflicting return type in "
+  "declaration of %0: %1 vs %2">,
+  InGroup<OverridingMethodMismatch>, DefaultIgnore;
+
 def warn_conflicting_ret_types : Warning<
   "conflicting return type in "
-  "%select{implementation|declaration}3 of %0: %1 vs %2">;
+  "implementation of %0: %1 vs %2">;
+
+def warn_conflicting_overriding_ret_type_modifiers : Warning<
+  "conflicting distributed object modifiers on return type "
+  "in declaration of %0">,
+  InGroup<OverridingMethodMismatch>, DefaultIgnore;
+
 def warn_conflicting_ret_type_modifiers : Warning<
   "conflicting distributed object modifiers on return type "
-  "in %select{implementation|declaration}1 of %0">,
+  "in implementation of %0">,
   InGroup<DiagGroup<"distributed-object-modifiers">>;
+
+def warn_non_covariant_overriding_ret_types : Warning<
+  "conflicting return type in "
+  "declaration of %0: %1 vs %2">,
+  InGroup<OverridingMethodMismatch>, DefaultIgnore;
+
 def warn_non_covariant_ret_types : Warning<
   "conflicting return type in "
-  "%select{implementation|declaration}3 of %0: %1 vs %2">,
+  "implementation of %0: %1 vs %2">,
   InGroup<DiagGroup<"method-signatures">>, DefaultIgnore;
 
+def warn_conflicting_overriding_param_types : Warning<
+  "conflicting parameter types in "
+  "declaration of %0: %1 vs %2">,
+  InGroup<OverridingMethodMismatch>, DefaultIgnore;
+
 def warn_conflicting_param_types : Warning<
   "conflicting parameter types in "
-  "%select{implementation|declaration}3 of %0: %1 vs %2">;
+  "implementation of %0: %1 vs %2">;
 def warn_conflicting_param_modifiers : Warning<
   "conflicting distributed object modifiers on parameter type "
-  "in %select{implementation|declaration}1 of %0">,
+  "in implementation of %0">,
   InGroup<DiagGroup<"distributed-object-modifiers">>;
+
+def warn_conflicting_overriding_param_modifiers : Warning<
+  "conflicting distributed object modifiers on parameter type "
+  "in declaration of %0">,
+  InGroup<OverridingMethodMismatch>, DefaultIgnore;
+
+def warn_non_contravariant_overriding_param_types : Warning<
+  "conflicting parameter types in "
+  "declaration of %0: %1 vs %2">,
+  InGroup<OverridingMethodMismatch>, DefaultIgnore;
+
 def warn_non_contravariant_param_types : Warning<
   "conflicting parameter types in "
-  "%select{implementation|declaration}3 of %0: %1 vs %2">,
+  "implementation of %0: %1 vs %2">,
   InGroup<DiagGroup<"method-signatures">>, DefaultIgnore;
+
+def warn_conflicting_overriding_variadic :Warning<
+  "conflicting variadic declaration of method and its "
+  "implementation">,
+  InGroup<OverridingMethodMismatch>, DefaultIgnore;
+
 def warn_conflicting_variadic :Warning<
   "conflicting variadic declaration of method and its "
-  "%select{implementation|declaration}0">;
+  "implementation">;
+
 def warn_category_method_impl_match:Warning<
   "category is implementing a method which will also be implemented"
   " by its primary class">, InGroup<ObjCProtocolMethodImpl>;

Modified: cfe/trunk/include/clang/Basic/IdentifierTable.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/IdentifierTable.h?rev=137222&r1=137221&r2=137222&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/IdentifierTable.h (original)
+++ cfe/trunk/include/clang/Basic/IdentifierTable.h Wed Aug 10 12:16:30 2011
@@ -557,11 +557,6 @@
   bool operator!=(Selector RHS) const {
     return InfoPtr != RHS.InfoPtr;
   }
-
-  bool operator < (Selector RHS) const {
-    return InfoPtr < RHS.InfoPtr;
-  }
-
   void *getAsOpaquePtr() const {
     return reinterpret_cast<void*>(InfoPtr);
   }

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=137222&r1=137221&r2=137222&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Wed Aug 10 12:16:30 2011
@@ -493,39 +493,6 @@
   /// a potentially evaluated expression.
   typedef SmallVector<std::pair<SourceLocation, Decl *>, 10>
     PotentiallyReferencedDecls;
-    
-  // FIXME. Improve on accessibility.
-  class PROTOCOL_METHODS {
-  public:
-    Selector Sel;
-    ObjCMethodDecl *Method;
-    PROTOCOL_METHODS(Selector S, ObjCMethodDecl *M) 
-        : Sel(S), Method(M) {}
-    // Allow sorting based on selector's opaque pointer.
-    bool operator<(const PROTOCOL_METHODS &b) const {
-          return Sel < b.Sel;
-    }
-  };
-
-  /// \brief The set of protocols declared in protocols qualifying a
-  /// class.
-  typedef SmallVector<PROTOCOL_METHODS, 16> MethodsInProtocols;
-    
-  class IDENTICAL_SELECTOR_METHODS {
-    public:
-        SourceLocation Loc;
-        ObjCMethodDecl *Method;
-        IDENTICAL_SELECTOR_METHODS(SourceLocation L, ObjCMethodDecl *M) 
-        : Loc(L), Method(M) {}
-        // Allow sorting based on selector's source location.
-        bool operator<(const IDENTICAL_SELECTOR_METHODS &i) const {
-            return !(Loc < i.Loc);
-        }
-  };
-
-  /// \brief Methods with identical selectors to be type-matched against
-  /// one another.
-  typedef SmallVector<IDENTICAL_SELECTOR_METHODS, 8> IdenticalSelectorMethods;
 
   /// \brief A set of diagnostics that may be emitted.
   typedef SmallVector<std::pair<SourceLocation, PartialDiagnostic>, 10>
@@ -1813,12 +1780,7 @@
   void WarnExactTypedMethods(ObjCMethodDecl *Method,
                              ObjCMethodDecl *MethodDecl,
                              bool IsProtocolMethodDecl);
-    
-  /// WarnOnMismatchedProtocolMethods - Issues warning on type mismatched 
-  /// protocols methods and then returns true(matched), or false(mismatched).
-  bool WarnOnMismatchedProtocolMethods(ObjCMethodDecl *Method,
-                                       ObjCMethodDecl *MethodDecl);
-                            
+
   bool isPropertyReadonly(ObjCPropertyDecl *PropertyDecl,
                           ObjCInterfaceDecl *IDecl);
 
@@ -1942,17 +1904,6 @@
                                   bool ImmediateClass,
                                   bool WarnExactMatch=false);
 
-  /// MatchIdenticalSelectorsInProtocols - Check that mathods with
-  /// identical selectors in all protocols of this class type match.
-  /// Issue warning if they don't.
-  void MatchIdenticalSelectorsInProtocols(const ObjCInterfaceDecl *CDecl);
-
-  /// MatchMethodsInClassAndItsProtocol - Check that any redeclaration of
-  /// method in protocol in its qualified class match in their type and
-  /// issue warnings otherwise.
-  void MatchMethodsInClassAndItsProtocol(const ObjCInterfaceDecl *CDecl);
-    
-
   /// CheckCategoryVsClassMethodMatches - Checks that methods implemented in
   /// category matches with those implemented in its primary class and
   /// warns each time an exact match is found. 

Modified: cfe/trunk/lib/Sema/SemaDeclObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclObjC.cpp?rev=137222&r1=137221&r2=137222&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclObjC.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclObjC.cpp Wed Aug 10 12:16:30 2011
@@ -1075,15 +1075,17 @@
                                       ObjCMethodDecl *MethodImpl,
                                       ObjCMethodDecl *MethodDecl,
                                       bool IsProtocolMethodDecl,
-                                      bool IsDeclaration,
+                                      bool IsOverridingMode,
                                       bool Warn) {
   if (IsProtocolMethodDecl &&
       (MethodDecl->getObjCDeclQualifier() !=
        MethodImpl->getObjCDeclQualifier())) {
     if (Warn) {
-      S.Diag(MethodImpl->getLocation(), 
-             diag::warn_conflicting_ret_type_modifiers)
-          << MethodImpl->getDeclName() << IsDeclaration
+        S.Diag(MethodImpl->getLocation(), 
+               (IsOverridingMode ? 
+                 diag::warn_conflicting_overriding_ret_type_modifiers 
+                 : diag::warn_conflicting_ret_type_modifiers))
+          << MethodImpl->getDeclName()
           << getTypeRange(MethodImpl->getResultTypeSourceInfo());
         S.Diag(MethodDecl->getLocation(), diag::note_previous_declaration)
           << getTypeRange(MethodDecl->getResultTypeSourceInfo());
@@ -1098,7 +1100,9 @@
   if (!Warn)
     return false;
 
-  unsigned DiagID = diag::warn_conflicting_ret_types;
+  unsigned DiagID = 
+    IsOverridingMode ? diag::warn_conflicting_overriding_ret_types 
+                     : diag::warn_conflicting_ret_types;
 
   // Mismatches between ObjC pointers go into a different warning
   // category, and sometimes they're even completely whitelisted.
@@ -1113,7 +1117,9 @@
       if (isObjCTypeSubstitutable(S.Context, IfacePtrTy, ImplPtrTy, false))
         return false;
 
-      DiagID = diag::warn_non_covariant_ret_types;
+      DiagID = 
+        IsOverridingMode ? diag::warn_non_covariant_overriding_ret_types 
+                          : diag::warn_non_covariant_ret_types;
     }
   }
 
@@ -1121,9 +1127,10 @@
     << MethodImpl->getDeclName()
     << MethodDecl->getResultType()
     << MethodImpl->getResultType()
-    << IsDeclaration
     << getTypeRange(MethodImpl->getResultTypeSourceInfo());
-  S.Diag(MethodDecl->getLocation(), diag::note_previous_definition)
+  S.Diag(MethodDecl->getLocation(), 
+         IsOverridingMode ? diag::note_previous_declaration 
+                          : diag::note_previous_definition)
     << getTypeRange(MethodDecl->getResultTypeSourceInfo());
   return false;
 }
@@ -1134,16 +1141,21 @@
                                      ParmVarDecl *ImplVar,
                                      ParmVarDecl *IfaceVar,
                                      bool IsProtocolMethodDecl,
-                                     bool IsDeclaration,
+                                     bool IsOverridingMode,
                                      bool Warn) {
   if (IsProtocolMethodDecl &&
       (ImplVar->getObjCDeclQualifier() !=
        IfaceVar->getObjCDeclQualifier())) {
     if (Warn) {
-      S.Diag(ImplVar->getLocation(), 
+      if (IsOverridingMode)
+        S.Diag(ImplVar->getLocation(), 
+               diag::warn_conflicting_overriding_param_modifiers)
+            << getTypeRange(ImplVar->getTypeSourceInfo())
+            << MethodImpl->getDeclName();
+      else S.Diag(ImplVar->getLocation(), 
              diag::warn_conflicting_param_modifiers)
           << getTypeRange(ImplVar->getTypeSourceInfo())
-          << MethodImpl->getDeclName() << IsDeclaration;
+          << MethodImpl->getDeclName();
       S.Diag(IfaceVar->getLocation(), diag::note_previous_declaration)
           << getTypeRange(IfaceVar->getTypeSourceInfo());   
     }
@@ -1159,7 +1171,9 @@
   
   if (!Warn)
     return false;
-  unsigned DiagID = diag::warn_conflicting_param_types;
+  unsigned DiagID = 
+    IsOverridingMode ? diag::warn_conflicting_overriding_param_types 
+                     : diag::warn_conflicting_param_types;
 
   // Mismatches between ObjC pointers go into a different warning
   // category, and sometimes they're even completely whitelisted.
@@ -1174,15 +1188,18 @@
       if (isObjCTypeSubstitutable(S.Context, ImplPtrTy, IfacePtrTy, true))
         return false;
 
-      DiagID = diag::warn_non_contravariant_param_types;
+      DiagID = 
+      IsOverridingMode ? diag::warn_non_contravariant_overriding_param_types 
+                       :  diag::warn_non_contravariant_param_types;
     }
   }
 
   S.Diag(ImplVar->getLocation(), DiagID)
     << getTypeRange(ImplVar->getTypeSourceInfo())
-    << MethodImpl->getDeclName() << IfaceTy << ImplTy 
-    << IsDeclaration;
-  S.Diag(IfaceVar->getLocation(), diag::note_previous_definition)
+    << MethodImpl->getDeclName() << IfaceTy << ImplTy;
+  S.Diag(IfaceVar->getLocation(), 
+         (IsOverridingMode ? diag::note_previous_declaration 
+                        : diag::note_previous_definition))
     << getTypeRange(IfaceVar->getTypeSourceInfo());
   return false;
 }
@@ -1260,54 +1277,31 @@
 void Sema::WarnConflictingTypedMethods(ObjCMethodDecl *ImpMethodDecl,
                                        ObjCMethodDecl *MethodDecl,
                                        bool IsProtocolMethodDecl,
-                                       bool IsDeclaration) {
+                                       bool IsOverridingMode) {
   if (getLangOptions().ObjCAutoRefCount &&
+      !IsOverridingMode &&
       checkMethodFamilyMismatch(*this, ImpMethodDecl, MethodDecl))
     return;
 
   CheckMethodOverrideReturn(*this, ImpMethodDecl, MethodDecl, 
-                            IsProtocolMethodDecl, IsDeclaration, true);
+                            IsProtocolMethodDecl, IsOverridingMode, 
+                            true);
 
   for (ObjCMethodDecl::param_iterator IM = ImpMethodDecl->param_begin(),
        IF = MethodDecl->param_begin(), EM = ImpMethodDecl->param_end();
-       IM != EM; ++IM, ++IF)
+       IM != EM; ++IM, ++IF) {
     CheckMethodOverrideParam(*this, ImpMethodDecl, MethodDecl, *IM, *IF,
-                             IsProtocolMethodDecl, IsDeclaration, true);
-
-  if (ImpMethodDecl->isVariadic() != MethodDecl->isVariadic()) {
-    Diag(ImpMethodDecl->getLocation(), diag::warn_conflicting_variadic)
-      << IsDeclaration;
-    Diag(MethodDecl->getLocation(), diag::note_previous_declaration);
+                             IsProtocolMethodDecl, IsOverridingMode, true);
   }
-}
 
-/// WarnOnMismatchedProtocolMethods - Issues warning on type mismatched 
-/// protocols methods and then returns true(matched), or false(mismatched).
-bool Sema::WarnOnMismatchedProtocolMethods(ObjCMethodDecl *ImpMethodDecl,
-                                           ObjCMethodDecl *MethodDecl) {
-  
-  bool match = CheckMethodOverrideReturn(*this, ImpMethodDecl, MethodDecl, 
-                                         true, 
-                                         true, true);
-  if (!match)
-    return false;
-  
-  for (ObjCMethodDecl::param_iterator IM = ImpMethodDecl->param_begin(),
-       IF = MethodDecl->param_begin(), EM = ImpMethodDecl->param_end();
-       IM != EM; ++IM, ++IF) {
-    match = CheckMethodOverrideParam(*this, ImpMethodDecl, MethodDecl, *IM, *IF,
-                                     true, true, true);
-    if (!match)
-      return false;
-  }
-  
   if (ImpMethodDecl->isVariadic() != MethodDecl->isVariadic()) {
-    Diag(ImpMethodDecl->getLocation(), diag::warn_conflicting_variadic)
-    << true;
+    if (IsOverridingMode)
+      Diag(ImpMethodDecl->getLocation(), 
+           diag::warn_conflicting_overriding_variadic);
+    else
+      Diag(ImpMethodDecl->getLocation(), diag::warn_conflicting_variadic);
     Diag(MethodDecl->getLocation(), diag::note_previous_declaration);
-    return false;
   }
-  return true;
 }
 
 /// WarnExactTypedMethods - This routine issues a warning if method
@@ -1539,214 +1533,6 @@
   }
 }
 
-/// MatchMethodsInClassAndProtocols - This routine goes thru list of methods
-/// declared in the class, and its class extensions. For each method which is
-/// also declared in one of its qualifying protocols, they must type match or
-/// it issues a warning.
-static void MatchMethodsInClassAndProtocols(Sema &S, 
-                                              const ObjCContainerDecl *IDecl,
-                              Sema::ProtocolsMethodsMap &InstMethodsInProtocols,
-                              Sema::ProtocolsMethodsMap &ClsMethodsInProtocols) {
-  for (ObjCInterfaceDecl::instmeth_iterator IM = IDecl->instmeth_begin(),
-       E = IDecl->instmeth_end(); IM != E; ++IM) {
-    Selector Sel = (*IM)->getSelector();
-    if (ObjCMethodDecl *ProtoMethodDecl = InstMethodsInProtocols[Sel]) {
-      ObjCMethodDecl *ClsMethodDecl = (*IM);
-      S.WarnConflictingTypedMethods(ClsMethodDecl, 
-                                    ProtoMethodDecl, true, true);
-    }
-  }
-  for (ObjCInterfaceDecl::classmeth_iterator IM = IDecl->classmeth_begin(),
-       E = IDecl->classmeth_end(); IM != E; ++IM) {
-    Selector Sel = (*IM)->getSelector();
-    if (ObjCMethodDecl *ProtoMethodDecl = ClsMethodsInProtocols[Sel]) {
-      ObjCMethodDecl *ClsMethodDecl = (*IM);
-      S.WarnConflictingTypedMethods(ClsMethodDecl, 
-                                    ProtoMethodDecl, true, true);
-    }
-  }
-  
-  if (const ObjCInterfaceDecl *I = dyn_cast<ObjCInterfaceDecl>(IDecl)) {
-    for (const ObjCCategoryDecl *ClsExtDecl = I->getFirstClassExtension();
-         ClsExtDecl; ClsExtDecl = ClsExtDecl->getNextClassExtension()) 
-      MatchMethodsInClassAndProtocols(S, ClsExtDecl, InstMethodsInProtocols,
-                                        ClsMethodsInProtocols);
-  }
-}
-
-/// CollectMethodsInOneProtocol - This routine collects all methods declared
-/// in a given protocol.
-static void CollectMethodsInOneProtocol(const ObjCProtocolDecl *PDecl,
-                              Sema::ProtocolsMethodsMap &InstMethodsInProtocols,
-                              Sema::ProtocolsMethodsMap &ClsMethodsInProtocols) {
-  for (ObjCProtocolDecl::instmeth_iterator I = PDecl->instmeth_begin(),
-       E = PDecl->instmeth_end(); I != E; ++I) {
-    ObjCMethodDecl *method = *I;
-    ObjCMethodDecl *&ProtocolEntry = 
-    InstMethodsInProtocols[method->getSelector()];
-    if (!ProtocolEntry)
-      ProtocolEntry = method;
-  }
-  for (ObjCProtocolDecl::classmeth_iterator I = PDecl->classmeth_begin(),
-       E = PDecl->classmeth_end(); I != E; ++I) {
-    ObjCMethodDecl *method = *I;
-    ObjCMethodDecl *&ProtocolEntry = 
-    ClsMethodsInProtocols[method->getSelector()];
-    if (!ProtocolEntry)
-      ProtocolEntry = method;
-  }
-}
-
-/// CollectAllMethodsInProtocols - Helper routine to collect all methods
-/// declared in given class's immediate and nested protocols.
-static void CollectAllMethodsInProtocols(const ObjCContainerDecl *ContDecl,
-                              Sema::MethodsInProtocols &InstMethodsInProtocols,
-                              Sema::MethodsInProtocols & ClsMethodsInProtocols) {
-  if (const ObjCInterfaceDecl *CDecl = dyn_cast<ObjCInterfaceDecl>(ContDecl)) {
-    for (ObjCInterfaceDecl::all_protocol_iterator
-         PI = CDecl->all_referenced_protocol_begin(),
-         E = CDecl->all_referenced_protocol_end(); PI != E; ++PI)
-      CollectAllMethodsInProtocols(*PI, InstMethodsInProtocols, 
-                                   ClsMethodsInProtocols);
-  }
-  
-  if (const ObjCProtocolDecl *PDecl = dyn_cast<ObjCProtocolDecl>(ContDecl)) {
-    for (ObjCProtocolDecl::instmeth_iterator I = PDecl->instmeth_begin(),
-         E = PDecl->instmeth_end(); I != E; ++I) {
-      ObjCMethodDecl *method = *I;
-      InstMethodsInProtocols.push_back(Sema::PROTOCOL_METHODS(method->getSelector(), 
-                                                        method));
-    }
-    for (ObjCProtocolDecl::classmeth_iterator I = PDecl->classmeth_begin(),
-         E = PDecl->classmeth_end(); I != E; ++I) {
-      ObjCMethodDecl *method = *I;
-      ClsMethodsInProtocols.push_back(Sema::PROTOCOL_METHODS(method->getSelector(), 
-                                                       method));
-    }
-  
-    for (ObjCProtocolDecl::protocol_iterator
-         PI = PDecl->protocol_begin(),
-         E = PDecl->protocol_end(); PI != E; ++PI)
-      CollectAllMethodsInProtocols(*PI, InstMethodsInProtocols, 
-                                   ClsMethodsInProtocols);
-  }
-}
-
-/// CollectMethodsInProtocols - This routine collects all methods declared
-/// in class's list and nested qualified protocols. Instance methods and 
-/// class methods have separate containers as they have identical selectors.
-static void CollectMethodsInProtocols(const ObjCContainerDecl *ContDecl,
-                              Sema::ProtocolsMethodsMap &InstMethodsInProtocols,
-                              Sema::ProtocolsMethodsMap &ClsMethodsInProtocols) {
-  if (const ObjCInterfaceDecl *CDecl = dyn_cast<ObjCInterfaceDecl>(ContDecl)) {
-    for (ObjCInterfaceDecl::all_protocol_iterator
-         PI = CDecl->all_referenced_protocol_begin(),
-         E = CDecl->all_referenced_protocol_end(); PI != E; ++PI) {
-      ObjCProtocolDecl *PDecl = (*PI);
-      CollectMethodsInOneProtocol(PDecl, InstMethodsInProtocols,
-                                  ClsMethodsInProtocols);
-      
-      for (ObjCProtocolDecl::protocol_iterator P = PDecl->protocol_begin(),
-           PE = PDecl->protocol_end(); P != PE; ++P)
-        CollectMethodsInProtocols((*P), InstMethodsInProtocols,
-                                  ClsMethodsInProtocols);
-    }
-    if (CDecl->getSuperClass())
-      CollectMethodsInProtocols(CDecl->getSuperClass(), InstMethodsInProtocols,
-                                ClsMethodsInProtocols);
-  }
-  
-  if (const ObjCProtocolDecl *PDecl = dyn_cast<ObjCProtocolDecl>(ContDecl))
-    CollectMethodsInOneProtocol(PDecl, InstMethodsInProtocols,
-                                ClsMethodsInProtocols);
-    
-}
-
-/// MatchMethodsInClassAndItsProtocol - Check that any redeclaration of
-/// method in protocol in its qualified class match in their type and
-/// issue warnings otherwise.
-void Sema::MatchMethodsInClassAndItsProtocol(const ObjCInterfaceDecl *CDecl) {  
-  ProtocolsMethodsMap InstMethodsInProtocols, ClsMethodsInProtocols;
-  CollectMethodsInProtocols(CDecl, InstMethodsInProtocols,
-                            ClsMethodsInProtocols);
-  
-  if (InstMethodsInProtocols.empty() && ClsMethodsInProtocols.empty())
-    return;
-  MatchMethodsInClassAndProtocols(*this, CDecl, InstMethodsInProtocols,
-                                    ClsMethodsInProtocols);
-}
-
-/// MatchMethodsWithIdenticalSelectors - Helper routine to go through list
-/// of identical selector lists and issue warning for any type mismatche
-/// of these methods.
-static bool MatchMethodsWithIdenticalSelectors(Sema &S,
-                                               const Sema::MethodsInProtocols Methods) {
-  bool res = true;
-  int size = Methods.size();
-  int i = 0;
-  while (i < size) {
-    int upper = i;
-    while (upper < size && 
-           (Methods[i].Sel == Methods[upper].Sel))
-      upper++;
-    if (upper > i) {
-      int lo = i;
-      int hi = upper - 1;
-      
-      if (lo < hi) {
-        Sema::IdenticalSelectorMethods SelectedMethods;
-        for (int l = lo; l <= hi; l++) {
-          ObjCMethodDecl *method = Methods[l].Method;
-          Sema::IDENTICAL_SELECTOR_METHODS 
-            SelectedMethod(method->getLocation(), method);
-          SelectedMethods.push_back(SelectedMethod);
-        }
-        llvm::array_pod_sort(SelectedMethods.begin(), SelectedMethods.end());
-        lo = 0; hi = SelectedMethods.size()-1;
-        while (lo < hi) {
-          ObjCMethodDecl *targetMethod = SelectedMethods[lo].Method;
-          for (int j = lo+1; j <= hi; j++) {
-            // match two methods;
-            ObjCMethodDecl *otherMethod = SelectedMethods[j].Method;
-            if (!S.WarnOnMismatchedProtocolMethods(targetMethod, otherMethod))
-              res = false;
-          }
-          ++lo;
-        }
-      }
-    }
-    i += upper;
-  }
-  return res;
-}
-
-/// MatchIdenticalSelectorsInProtocols - Main routine to go through list of
-/// class's protocols (and their protocols) and make sure that methods
-/// type match across all protocols and issue warnings if they don't.
-/// FIXME. This may move to static analyzer if performance is proven
-/// prohibitive.
-void Sema::MatchIdenticalSelectorsInProtocols(const ObjCInterfaceDecl *CDecl) {
-  Sema::MethodsInProtocols InsMethods;
-  Sema::MethodsInProtocols ClsMethods;
-  CollectAllMethodsInProtocols(CDecl, InsMethods, ClsMethods);
-  
-  bool match = true;
-  if (!InsMethods.empty()) {
-    llvm::array_pod_sort(InsMethods.begin(), InsMethods.end());
-    if (!MatchMethodsWithIdenticalSelectors(*this, InsMethods))
-      match = false;
-  }
-  
-  if (!ClsMethods.empty()) {
-    llvm::array_pod_sort(ClsMethods.begin(), ClsMethods.end());
-    if (!MatchMethodsWithIdenticalSelectors(*this, ClsMethods))
-      match = false;
-  }
-  if (!match)
-    Diag(CDecl->getLocation() ,diag::note_class_declared);
-}
-
-
 /// CheckCategoryVsClassMethodMatches - Checks that methods implemented in
 /// category matches with those implemented in its primary class and
 /// warns each time an exact match is found. 
@@ -1809,14 +1595,6 @@
   MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen,
                              IMPDecl, CDecl,
                              IncompleteImpl, true);
-  // Check for any type mismtch of methods declared in class
-  // and methods declared in protocol. Do this only when the class
-  // is being implementaed.
-  if (isa<ObjCImplementationDecl>(IMPDecl))
-    if (const ObjCInterfaceDecl *I = dyn_cast<ObjCInterfaceDecl>(CDecl)) {
-      MatchIdenticalSelectorsInProtocols(I);
-      MatchMethodsInClassAndItsProtocol(I);
-    }
   
   // check all methods implemented in category against those declared
   // in its primary class.
@@ -2828,6 +2606,13 @@
 
     // Then merge the declarations.
     mergeObjCMethodDecls(ObjCMethod, overridden);
+    
+    // Check for overriding methods
+    if (isa<ObjCInterfaceDecl>(ObjCMethod->getDeclContext()) || 
+        isa<ObjCImplementationDecl>(ObjCMethod->getDeclContext())) {
+      WarnConflictingTypedMethods(ObjCMethod, overridden,
+              isa<ObjCProtocolDecl>(overridden->getDeclContext()), true);
+    }
   }
   
   bool ARCError = false;

Modified: cfe/trunk/test/SemaObjC/class-protocol-method-match.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/class-protocol-method-match.m?rev=137222&r1=137221&r2=137222&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/class-protocol-method-match.m (original)
+++ cfe/trunk/test/SemaObjC/class-protocol-method-match.m Wed Aug 10 12:16:30 2011
@@ -1,64 +1,48 @@
-// RUN: %clang_cc1  -fsyntax-only -verify %s
+// RUN: %clang_cc1  -Woverriding-method-mismatch -fsyntax-only -verify %s
 // rdar://9352731
 
 @protocol Bar 
 @required
-- (unsigned char) baz; // expected-note {{previous definition is here}}
-- (char) ok; // expected-note {{previous definition is here}}
+- (bycopy id)bud; // expected-note {{previous declaration is here}}
+- (unsigned char) baz; // expected-note {{previous declaration is here}}
+- (char) ok;
 - (void) also_ok;
 @end
 
 @protocol Bar1 
 @required
-- (unsigned char) baz;
-- (unsigned char) also_ok;
+- (unsigned char) baz; // expected-note {{previous declaration is here}}
+- (unsigned char) also_ok; // expected-note {{previous declaration is here}}
 - (void) ban : (int) arg, ...; // expected-note {{previous declaration is here}}
 @end
 
 @protocol Baz <Bar, Bar1>
-- (void) bar : (unsigned char)arg; // expected-note {{previous definition is here}}
-- (void) ok; // expected-warning {{conflicting return type in declaration of 'ok': 'char' vs 'void'}}
-- (char) bak; // expected-note {{previous definition is here}}
+- (void) bar : (unsigned char)arg; // expected-note {{previous declaration is here}}
+- (void) ok;
+- (char) bak; // expected-note {{previous declaration is here}}
 @end
 
- at interface Foo <Baz> // expected-note {{class is declared here}}
-- (void) baz;  // expected-warning {{conflicting return type in declaration of 'baz': 'unsigned char' vs 'void'}}
+ at interface Foo <Baz>
+- (id)bud; // expected-warning {{conflicting distributed object modifiers on return type in declaration of 'bud'}}
+- (void) baz; // expected-warning 2 {{conflicting return type in declaration of 'baz': 'unsigned char' vs 'void'}}
 - (void) bar : (unsigned char*)arg; // expected-warning {{conflicting parameter types in declaration of 'bar:': 'unsigned char' vs 'unsigned char *'}}
 - (void) ok;
-- (void) also_ok;
+- (void) also_ok; // expected-warning {{conflicting return type in declaration of 'also_ok': 'unsigned char' vs 'void'}}
 - (void) still_ok;
-- (void) ban : (int) arg; // expected-warning {{conflicting variadic declaration of method and its declaration}}
+- (void) ban : (int) arg; // expected-warning {{conflicting variadic declaration of method and its implementation}}
 @end
 
 @interface Foo()
-- (void) bak; // expected-warning {{conflicting return type in declaration of 'bak': 'char' vs 'void'}}
+- (void) bak;
 @end
 
 @implementation Foo
+- (bycopy id)bud { return 0; }
 - (void) baz {}
 - (void) bar : (unsigned char*)arg {}
 - (void) ok {}
 - (void) also_ok {}
 - (void) still_ok {}
 - (void) ban : (int) arg {}
-- (void) bak {}
- at end
-
-// rdar://6911214
- at protocol Xint
--(void) setX: (int) arg0; // expected-note {{previous definition is here}}
-+(void) setX: (int) arg0; // expected-note {{previous definition is here}}
- at end
-
- at interface A <Xint>
- at end
-
- at interface C : A
--(void) setX: (C*) arg0; // expected-warning {{conflicting parameter types in declaration of 'setX:': 'int' vs 'C *'}}
-+(void) setX: (C*) arg0; // expected-warning {{conflicting parameter types in declaration of 'setX:': 'int' vs 'C *'}}
- at end
-
- at implementation C
--(void) setX: (C*) arg0 {}
-+(void) setX: (C*) arg0 {}
+- (void) bak {} // expected-warning {{conflicting return type in declaration of 'bak': 'char' vs 'void'}}
 @end

Modified: cfe/trunk/test/SemaObjC/dist-object-modifiers.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/dist-object-modifiers.m?rev=137222&r1=137221&r2=137222&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/dist-object-modifiers.m (original)
+++ cfe/trunk/test/SemaObjC/dist-object-modifiers.m Wed Aug 10 12:16:30 2011
@@ -4,12 +4,12 @@
 @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; // 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; // expected-warning {{conflicting distributed object modifiers on return type in declaration of 'Ok'}}
+- (id)Ok;
 @end
 
 @implementation I

Modified: cfe/trunk/test/SemaObjC/qualified-protocol-method-conflicts.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/qualified-protocol-method-conflicts.m?rev=137222&r1=137221&r2=137222&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/qualified-protocol-method-conflicts.m (original)
+++ cfe/trunk/test/SemaObjC/qualified-protocol-method-conflicts.m Wed Aug 10 12:16:30 2011
@@ -1,39 +1,39 @@
-// RUN: %clang_cc1  -fsyntax-only -verify %s
+// RUN: %clang_cc1  -Woverriding-method-mismatch -fsyntax-only -verify %s
 // rdar://6191214
 
 @protocol Xint
--(void) setX: (int) arg0; // expected-note 3 {{previous definition is here}}
-+(int) C; // expected-note 3 {{previous definition is here}}
+-(void) setX: (int) arg0; // expected-note {{previous declaration is here}}
++(int) C; // expected-note {{previous declaration is here}}
 @end
 
 @protocol Xfloat
--(void) setX: (float) arg0; // expected-warning 3 {{conflicting parameter types in declaration of 'setX:': 'int' vs 'float'}}
-+(float) C; // expected-warning 3 {{conflicting return type in declaration of 'C': 'int' vs 'float'}}
+-(void) setX: (float) arg0; // expected-note 2 {{previous declaration is here}}
++(float) C;		    // expected-note 2 {{previous declaration is here}}
 @end
 
- at interface A <Xint, Xfloat> // expected-note {{class is declared here}}
+ at interface A <Xint, Xfloat>
 @end
 
 @implementation A
--(void) setX: (int) arg0 { }
-+(int) C {return 0; }
+-(void) setX: (int) arg0 { } // expected-warning {{conflicting parameter types in declaration of 'setX:': 'float' vs 'int'}}
++(int) C {return 0; } // expected-warning {{conflicting return type in declaration of 'C': 'float' vs 'int'}}
 @end
 
- at interface B <Xfloat, Xint> // expected-note {{class is declared here}}
+ at interface B <Xfloat, Xint>
 @end
 
 @implementation B 
--(void) setX: (float) arg0 { }
-+ (float) C {return 0.0; }
+-(void) setX: (float) arg0 { } // expected-warning {{conflicting parameter types in declaration of 'setX:': 'int' vs 'float'}}
++ (float) C {return 0.0; } // expected-warning {{conflicting return type in declaration of 'C': 'int' vs 'float'}}
 @end
 
 @protocol Xint_float<Xint, Xfloat>
 @end
 
- at interface C<Xint_float> // expected-note {{class is declared here}}
+ at interface C<Xint_float>
 @end
 
 @implementation C
--(void) setX: (int) arg0 { }
-+ (int) C {return 0;}
+-(void) setX: (int) arg0 { } // expected-warning {{conflicting parameter types in declaration of 'setX:': 'float' vs 'int'}}
++ (int) C {return 0;} // expected-warning {{conflicting return type in declaration of 'C': 'float' vs 'int'}}
 @end





More information about the cfe-commits mailing list