r235023 - [Objective-C Sema]This patch fixes the warning when clang issues

Fariborz Jahanian fjahanian at apple.com
Wed Apr 15 10:26:22 PDT 2015


Author: fjahanian
Date: Wed Apr 15 12:26:21 2015
New Revision: 235023

URL: http://llvm.org/viewvc/llvm-project?rev=235023&view=rev
Log:
[Objective-C Sema]This patch fixes the warning when clang issues
"multiple methods named '<selector>' found" warning by noting 
the method that is actualy used. It also cleans up and refactors
code in this area and selects a method that matches actual arguments
in case of receiver being a forward class object.
rdar://19265430

Modified:
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaDeclObjC.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/lib/Sema/SemaExprObjC.cpp
    cfe/trunk/lib/Sema/SemaPseudoObject.cpp
    cfe/trunk/test/SemaObjC/warn-strict-selector-match.m

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=235023&r1=235022&r2=235023&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Wed Apr 15 12:26:21 2015
@@ -2908,7 +2908,7 @@ private:
   /// optionally warns if there are multiple signatures.
   ObjCMethodDecl *LookupMethodInGlobalPool(Selector Sel, SourceRange R,
                                            bool receiverIdOrClass,
-                                           bool warn, bool instance);
+                                           bool instance);
 
 public:
   /// \brief - Returns instance or factory methods in global method pool for
@@ -2918,8 +2918,13 @@ public:
                                           SmallVectorImpl<ObjCMethodDecl*>& Methods,
                                           bool instance);
     
-  bool AreMultipleMethodsInGlobalPool(Selector Sel,
-                                      bool instance);
+  bool AreMultipleMethodsInGlobalPool(Selector Sel, ObjCMethodDecl *BestMethod,
+                                      SourceRange R,
+                                      bool receiverIdOrClass);
+      
+  void DiagnoseMultipleMethodInGlobalPool(SmallVectorImpl<ObjCMethodDecl*> &Methods,
+                                          Selector Sel, SourceRange R,
+                                          bool receiverIdOrClass);
 
 private:
   /// \brief - Returns a selector which best matches given argument list or
@@ -2957,19 +2962,17 @@ public:
   /// LookupInstanceMethodInGlobalPool - Returns the method and warns if
   /// there are multiple signatures.
   ObjCMethodDecl *LookupInstanceMethodInGlobalPool(Selector Sel, SourceRange R,
-                                                   bool receiverIdOrClass=false,
-                                                   bool warn=true) {
+                                                   bool receiverIdOrClass=false) {
     return LookupMethodInGlobalPool(Sel, R, receiverIdOrClass,
-                                    warn, /*instance*/true);
+                                    /*instance*/true);
   }
 
   /// LookupFactoryMethodInGlobalPool - Returns the method and warns if
   /// there are multiple signatures.
   ObjCMethodDecl *LookupFactoryMethodInGlobalPool(Selector Sel, SourceRange R,
-                                                  bool receiverIdOrClass=false,
-                                                  bool warn=true) {
+                                                  bool receiverIdOrClass=false) {
     return LookupMethodInGlobalPool(Sel, R, receiverIdOrClass,
-                                    warn, /*instance*/false);
+                                    /*instance*/false);
   }
 
   const ObjCMethodDecl *SelectorsForTypoCorrection(Selector Sel,

Modified: cfe/trunk/lib/Sema/SemaDeclObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclObjC.cpp?rev=235023&r1=235022&r2=235023&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclObjC.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclObjC.cpp Wed Apr 15 12:26:21 2015
@@ -2346,19 +2346,33 @@ bool Sema::CollectMultipleMethodsInGloba
   return Methods.size() > 1;
 }
 
-bool Sema::AreMultipleMethodsInGlobalPool(Selector Sel, bool instance) {
+bool Sema::AreMultipleMethodsInGlobalPool(Selector Sel, ObjCMethodDecl *BestMethod,
+                                          SourceRange R,
+                                          bool receiverIdOrClass) {
   GlobalMethodPool::iterator Pos = MethodPool.find(Sel);
   // Test for no method in the pool which should not trigger any warning by
   // caller.
   if (Pos == MethodPool.end())
     return true;
-  ObjCMethodList &MethList = instance ? Pos->second.first : Pos->second.second;
+  ObjCMethodList &MethList =
+    BestMethod->isInstanceMethod() ? Pos->second.first : Pos->second.second;
+  
+  // Diagnose finding more than one method in global pool
+  SmallVector<ObjCMethodDecl *, 4> Methods;
+  Methods.push_back(BestMethod);
+  for (ObjCMethodList *M = &MethList; M; M = M->getNext())
+    if (M->getMethod() && !M->getMethod()->isHidden() &&
+        M->getMethod() != BestMethod)
+      Methods.push_back(M->getMethod());
+  if (Methods.size() > 1)
+    DiagnoseMultipleMethodInGlobalPool(Methods, Sel, R, receiverIdOrClass);
+
   return MethList.hasMoreThanOneDecl();
 }
 
 ObjCMethodDecl *Sema::LookupMethodInGlobalPool(Selector Sel, SourceRange R,
                                                bool receiverIdOrClass,
-                                               bool warn, bool instance) {
+                                               bool instance) {
   if (ExternalSource)
     ReadMethodPool(Sel);
     
@@ -2370,31 +2384,23 @@ ObjCMethodDecl *Sema::LookupMethodInGlob
   ObjCMethodList &MethList = instance ? Pos->second.first : Pos->second.second;
   SmallVector<ObjCMethodDecl *, 4> Methods;
   for (ObjCMethodList *M = &MethList; M; M = M->getNext()) {
-    if (M->getMethod() && !M->getMethod()->isHidden()) {
-      // If we're not supposed to warn about mismatches, we're done.
-      if (!warn)
-        return M->getMethod();
-
-      Methods.push_back(M->getMethod());
-    }
+    if (M->getMethod() && !M->getMethod()->isHidden())
+      return M->getMethod();
   }
+  return nullptr;
+}
 
-  // If there aren't any visible methods, we're done.
-  // FIXME: Recover if there are any known-but-hidden methods?
-  if (Methods.empty())
-    return nullptr;
-
-  if (Methods.size() == 1)
-    return Methods[0];
-
+void Sema::DiagnoseMultipleMethodInGlobalPool(SmallVectorImpl<ObjCMethodDecl*> &Methods,
+                                              Selector Sel, SourceRange R,
+                                              bool receiverIdOrClass) {
   // We found multiple methods, so we may have to complain.
   bool issueDiagnostic = false, issueError = false;
-
+  
   // We support a warning which complains about *any* difference in
   // method signature.
   bool strictSelectorMatch =
-      receiverIdOrClass && warn &&
-      !Diags.isIgnored(diag::warn_strict_multiple_method_decl, R.getBegin());
+  receiverIdOrClass &&
+  !Diags.isIgnored(diag::warn_strict_multiple_method_decl, R.getBegin());
   if (strictSelectorMatch) {
     for (unsigned I = 1, N = Methods.size(); I != N; ++I) {
       if (!MatchTwoMethodDeclarations(Methods[0], Methods[I], MMS_strict)) {
@@ -2403,7 +2409,7 @@ ObjCMethodDecl *Sema::LookupMethodInGlob
       }
     }
   }
-
+  
   // If we didn't see any strict differences, we won't see any loose
   // differences.  In ARC, however, we also need to check for loose
   // mismatches, because most of them are errors.
@@ -2419,7 +2425,7 @@ ObjCMethodDecl *Sema::LookupMethodInGlob
         break;
       }
     }
-
+  
   if (issueDiagnostic) {
     if (issueError)
       Diag(R.getBegin(), diag::err_arc_multiple_method_decl) << Sel << R;
@@ -2427,16 +2433,15 @@ ObjCMethodDecl *Sema::LookupMethodInGlob
       Diag(R.getBegin(), diag::warn_strict_multiple_method_decl) << Sel << R;
     else
       Diag(R.getBegin(), diag::warn_multiple_method_decl) << Sel << R;
-
+    
     Diag(Methods[0]->getLocStart(),
          issueError ? diag::note_possibility : diag::note_using)
-      << Methods[0]->getSourceRange();
+    << Methods[0]->getSourceRange();
     for (unsigned I = 1, N = Methods.size(); I != N; ++I) {
       Diag(Methods[I]->getLocStart(), diag::note_also_found)
-        << Methods[I]->getSourceRange();
-  }
+      << Methods[I]->getSourceRange();
+    }
   }
-  return Methods[0];
 }
 
 ObjCMethodDecl *Sema::LookupImplementedMethodInGlobalPool(Selector Sel) {

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=235023&r1=235022&r2=235023&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Wed Apr 15 12:26:21 2015
@@ -8175,8 +8175,7 @@ static bool hasIsEqualMethod(Sema &S, co
     if (Type->isObjCIdType()) {
       // For 'id', just check the global pool.
       Method = S.LookupInstanceMethodInGlobalPool(IsEqualSel, SourceRange(),
-                                                  /*receiverId=*/true,
-                                                  /*warn=*/false);
+                                                  /*receiverId=*/true);
     } else {
       // Check protocols.
       Method = S.LookupMethodInQualifiedType(IsEqualSel, Type,

Modified: cfe/trunk/lib/Sema/SemaExprObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprObjC.cpp?rev=235023&r1=235022&r2=235023&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprObjC.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprObjC.cpp Wed Apr 15 12:26:21 2015
@@ -1043,7 +1043,7 @@ ExprResult Sema::ParseObjCSelectorExpres
                                              SourceLocation RParenLoc,
                                              bool WarnMultipleSelectors) {
   ObjCMethodDecl *Method = LookupInstanceMethodInGlobalPool(Sel,
-                             SourceRange(LParenLoc, RParenLoc), false, false);
+                             SourceRange(LParenLoc, RParenLoc));
   if (!Method)
     Method = LookupFactoryMethodInGlobalPool(Sel,
                                           SourceRange(LParenLoc, RParenLoc));
@@ -2393,8 +2393,11 @@ ExprResult Sema::BuildInstanceMessage(Ex
         if (ObjCMethodDecl *BestMethod =
               SelectBestMethod(Sel, ArgsIn, Method->isInstanceMethod()))
           Method = BestMethod;
-        if (!AreMultipleMethodsInGlobalPool(Sel, Method->isInstanceMethod()))
+        if (!AreMultipleMethodsInGlobalPool(Sel, Method,
+                                            SourceRange(LBracLoc, RBracLoc),
+                                            receiverIsId)) {
           DiagnoseUseOfDecl(Method, SelLoc);
+        }
       }
     } else if (ReceiverType->isObjCClassType() ||
                ReceiverType->isObjCQualifiedClassType()) {
@@ -2432,14 +2435,12 @@ ExprResult Sema::BuildInstanceMessage(Ex
           // If not messaging 'self', look for any factory method named 'Sel'.
           if (!Receiver || !isSelfExpr(Receiver)) {
             Method = LookupFactoryMethodInGlobalPool(Sel, 
-                                                SourceRange(LBracLoc, RBracLoc),
-                                                     true);
+                                                SourceRange(LBracLoc, RBracLoc));
             if (!Method) {
               // If no class (factory) method was found, check if an _instance_
               // method of the same name exists in the root class only.
               Method = LookupInstanceMethodInGlobalPool(Sel,
-                                               SourceRange(LBracLoc, RBracLoc),
-                                                        true);
+                                               SourceRange(LBracLoc, RBracLoc));
               if (Method)
                   if (const ObjCInterfaceDecl *ID =
                       dyn_cast<ObjCInterfaceDecl>(Method->getDeclContext())) {
@@ -2516,6 +2517,14 @@ ExprResult Sema::BuildInstanceMessage(Ex
             if (OCIType->qual_empty()) {
               Method = LookupInstanceMethodInGlobalPool(Sel,
                                               SourceRange(LBracLoc, RBracLoc));
+              if (Method) {
+                if (auto BestMethod =
+                      SelectBestMethod(Sel, ArgsIn, Method->isInstanceMethod()))
+                  Method = BestMethod;
+                AreMultipleMethodsInGlobalPool(Sel, Method,
+                                               SourceRange(LBracLoc, RBracLoc),
+                                               true);
+              }
               if (Method && !forwardClass)
                 Diag(SelLoc, diag::warn_maynot_respond)
                   << OCIType->getInterfaceDecl()->getIdentifier()

Modified: cfe/trunk/lib/Sema/SemaPseudoObject.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaPseudoObject.cpp?rev=235023&r1=235022&r2=235023&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaPseudoObject.cpp (original)
+++ cfe/trunk/lib/Sema/SemaPseudoObject.cpp Wed Apr 15 12:26:21 2015
@@ -1192,7 +1192,7 @@ bool ObjCSubscriptOpBuilder::findAtIndex
     AtIndexGetter = 
       S.LookupInstanceMethodInGlobalPool(AtIndexGetterSelector, 
                                          RefExpr->getSourceRange(), 
-                                         true, false);
+                                         true);
   }
   
   if (AtIndexGetter) {
@@ -1314,7 +1314,7 @@ bool ObjCSubscriptOpBuilder::findAtIndex
     AtIndexSetter = 
       S.LookupInstanceMethodInGlobalPool(AtIndexSetterSelector, 
                                          RefExpr->getSourceRange(), 
-                                         true, false);
+                                         true);
   }
   
   bool err = false;

Modified: cfe/trunk/test/SemaObjC/warn-strict-selector-match.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/warn-strict-selector-match.m?rev=235023&r1=235022&r2=235023&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/warn-strict-selector-match.m (original)
+++ cfe/trunk/test/SemaObjC/warn-strict-selector-match.m Wed Apr 15 12:26:21 2015
@@ -13,23 +13,24 @@ int main() { [(id)0 method]; } // expect
 @interface Object @end
 
 @interface Class1
-- (void)setWindow:(Object *)wdw;	// expected-note {{using}}
+- (void)setWindow:(Object *)wdw;	// expected-note 2 {{using}}
 @end
 
 @interface Class2
-- (void)setWindow:(Class1 *)window;	// expected-note {{also found}}
+- (void)setWindow:(Class1 *)window;	// expected-note 2 {{also found}}
 @end
 
 id foo(void) {
   Object *obj = 0;
   id obj2 = obj;
-  [obj setWindow:0]; 	// expected-warning {{Object' may not respond to 'setWindow:'}}
+  [obj setWindow:0]; 	// expected-warning {{Object' may not respond to 'setWindow:'}} \
+			// expected-warning {{multiple methods named 'setWindow:' found}}
   [obj2 setWindow:0]; // expected-warning {{multiple methods named 'setWindow:' found}}
   return obj;
 }
 
 @protocol MyObject
-- (id)initWithData:(Object *)data;	// expected-note {{using}} 
+- (id)initWithData:(Object *)data;	// expected-note {{also found}} 
 @end
 
 @protocol SomeOther
@@ -37,7 +38,7 @@ id foo(void) {
 @end
 
 @protocol MyCoding
-- (id)initWithData:(id<MyObject, MyCoding>)data;	// expected-note {{also found}}
+- (id)initWithData:(id<MyObject, MyCoding>)data;	// expected-note {{using}}
 @end
 
 @interface NTGridDataObject: Object <MyCoding>
@@ -71,3 +72,29 @@ void foo1(void) {
   [(Class)0 port]; // OK - gcc issues warning but there is only one Class method so no ambiguity to warn
 }
 
+// rdar://19265430
+ at interface NSObject 
+- (id)class;
+- (id) alloc;
+ at end
+
+ at class NSString;
+
+ at interface A : NSObject
+- (instancetype)initWithType:(NSString *)whatever; // expected-note {{also found}}
+ at end
+
+ at interface Test : NSObject
+ at end
+
+ at implementation Test
++ (instancetype)foo
+{
+    return [[[self class] alloc] initWithType:3]; // expected-warning {{multiple methods named 'initWithType:'}}
+}
+
+- (instancetype)initWithType:(unsigned int)whatever // expected-note {{using}}
+{
+    return 0;
+}
+ at end





More information about the cfe-commits mailing list