r265877 - ObjC kindof: check the context when inserting methods to global pool.

Manman Ren via cfe-commits cfe-commits at lists.llvm.org
Sat Apr 9 11:59:50 PDT 2016


Author: mren
Date: Sat Apr  9 13:59:48 2016
New Revision: 265877

URL: http://llvm.org/viewvc/llvm-project?rev=265877&view=rev
Log:
ObjC kindof: check the context when inserting methods to global pool.

To make kindof lookup work, we need to insert methods with different
context into the global pool, even though they have the same siganture.

Since diagnosis of availability is performed on the best candidate,
which is often the first candidate from the global pool, we prioritize
the methods that are unavaible or deprecated to the head of the list.

Since we now have more methods in the global pool, we need to watch
out for performance impact.

rdar://25635831

Modified:
    cfe/trunk/include/clang/Sema/ObjCMethodList.h
    cfe/trunk/lib/Sema/SemaDeclObjC.cpp
    cfe/trunk/test/FixIt/typo.m
    cfe/trunk/test/SemaObjC/kindof.m
    cfe/trunk/test/SemaObjC/multiple-method-names.m
    cfe/trunk/test/SemaObjC/warn-strict-selector-match.m

Modified: cfe/trunk/include/clang/Sema/ObjCMethodList.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/ObjCMethodList.h?rev=265877&r1=265876&r2=265877&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/ObjCMethodList.h (original)
+++ cfe/trunk/include/clang/Sema/ObjCMethodList.h Sat Apr  9 13:59:48 2016
@@ -33,6 +33,9 @@ struct ObjCMethodList {
   ObjCMethodList() { }
   ObjCMethodList(ObjCMethodDecl *M)
       : MethodAndHasMoreThanOneDecl(M, 0) {}
+  ObjCMethodList(const ObjCMethodList &L)
+      : MethodAndHasMoreThanOneDecl(L.MethodAndHasMoreThanOneDecl),
+        NextAndExtraBits(L.NextAndExtraBits) {}
 
   ObjCMethodList *getNext() const { return NextAndExtraBits.getPointer(); }
   unsigned getBits() const { return NextAndExtraBits.getInt(); }

Modified: cfe/trunk/lib/Sema/SemaDeclObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclObjC.cpp?rev=265877&r1=265876&r2=265877&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclObjC.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclObjC.cpp Sat Apr  9 13:59:48 2016
@@ -3167,6 +3167,26 @@ bool Sema::MatchTwoMethodDeclarations(co
   return true;
 }
 
+static bool isMethodContextSameForKindofLookup(ObjCMethodDecl *Method,
+                                               ObjCMethodDecl *MethodInList) {
+  auto *MethodProtocol = dyn_cast<ObjCProtocolDecl>(Method->getDeclContext());
+  auto *MethodInListProtocol =
+      dyn_cast<ObjCProtocolDecl>(MethodInList->getDeclContext());
+  // If this method belongs to a protocol but the method in list does not, or
+  // vice versa, we say the context is not the same.
+  if ((MethodProtocol && !MethodInListProtocol) ||
+      (!MethodProtocol && MethodInListProtocol))
+    return false;
+
+  if (MethodProtocol && MethodInListProtocol)
+    return true;
+
+  ObjCInterfaceDecl *MethodInterface = Method->getClassInterface();
+  ObjCInterfaceDecl *MethodInListInterface =
+      MethodInList->getClassInterface();
+  return MethodInterface == MethodInListInterface;
+}
+
 void Sema::addMethodToGlobalList(ObjCMethodList *List,
                                  ObjCMethodDecl *Method) {
   // Record at the head of the list whether there were 0, 1, or >= 2 methods
@@ -3185,13 +3205,17 @@ void Sema::addMethodToGlobalList(ObjCMet
 
   // We've seen a method with this name, see if we have already seen this type
   // signature.
+  ObjCMethodList *Head = List;
   ObjCMethodList *Previous = List;
   for (; List; Previous = List, List = List->getNext()) {
     // If we are building a module, keep all of the methods.
     if (getLangOpts().CompilingModule)
       continue;
 
-    if (!MatchTwoMethodDeclarations(Method, List->getMethod())) {
+    // Looking for method with a type bound requires the correct context exists.
+    // We need to insert this method into the list if the context is different.
+    if (!MatchTwoMethodDeclarations(Method, List->getMethod()) ||
+        !isMethodContextSameForKindofLookup(Method, List->getMethod())) {
       // Even if two method types do not match, we would like to say
       // there is more than one declaration so unavailability/deprecated
       // warning is not too noisy.
@@ -3232,6 +3256,19 @@ void Sema::addMethodToGlobalList(ObjCMet
   // We have a new signature for an existing method - add it.
   // This is extremely rare. Only 1% of Cocoa selectors are "overloaded".
   ObjCMethodList *Mem = BumpAlloc.Allocate<ObjCMethodList>();
+
+  // We tried to prioritize the list by putting deprecated and unavailable
+  // methods in the front.
+  if ((Method->isDeprecated() && !Head->getMethod()->isDeprecated()) ||
+      (Method->isUnavailable() &&
+       Head->getMethod()->getAvailability() < AR_Deprecated)) {
+    auto *List = new (Mem) ObjCMethodList(*Head);
+    // FIXME: should we clear the other bits in Head?
+    Head->setMethod(Method);
+    Head->setNext(List);
+    return;
+  }
+
   Previous->setNext(new (Mem) ObjCMethodList(Method));
 }
 

Modified: cfe/trunk/test/FixIt/typo.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/FixIt/typo.m?rev=265877&r1=265876&r2=265877&view=diff
==============================================================================
--- cfe/trunk/test/FixIt/typo.m (original)
+++ cfe/trunk/test/FixIt/typo.m Sat Apr  9 13:59:48 2016
@@ -103,7 +103,7 @@ void test2(Collide *a) {
 @end
 
 @interface Sub : Super
-- (int)method;
+- (int)method; // expected-note{{also found}}
 @end
 
 @implementation Sub

Modified: cfe/trunk/test/SemaObjC/kindof.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/kindof.m?rev=265877&r1=265876&r2=265877&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/kindof.m (original)
+++ cfe/trunk/test/SemaObjC/kindof.m Sat Apr  9 13:59:48 2016
@@ -275,6 +275,20 @@ void test(__kindof Bar *kBar) {
     [kBar test];
 }
 
+// Make sure we don't emit warning about no method found.
+typedef signed char BOOL;
+ at interface A : NSObject
+ at property (readonly, getter=isActive) BOOL active;
+ at end
+ at interface B : NSObject
+ at property (getter=isActive, readonly) BOOL active;
+ at end
+void foo() {
+  __kindof B *NSApp;
+  if ([NSApp isActive]) {
+  }
+}
+
 // ---------------------------------------------------------------------------
 // __kindof within specialized types
 // ---------------------------------------------------------------------------

Modified: cfe/trunk/test/SemaObjC/multiple-method-names.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/multiple-method-names.m?rev=265877&r1=265876&r2=265877&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/multiple-method-names.m (original)
+++ cfe/trunk/test/SemaObjC/multiple-method-names.m Sat Apr  9 13:59:48 2016
@@ -2,11 +2,11 @@
 // PR22047
 
 @interface Face0
-- (void)foo:(float)i; // expected-note {{using}}
+- (void)foo:(float)i; // expected-note {{also found}}
 @end
 
 @interface Face1
-- (void)foo:(int)i __attribute__((unavailable));
+- (void)foo:(int)i __attribute__((unavailable)); // expected-note {{using}}
 @end
 
 @interface Face2

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=265877&r1=265876&r2=265877&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/warn-strict-selector-match.m (original)
+++ cfe/trunk/test/SemaObjC/warn-strict-selector-match.m Sat Apr  9 13:59:48 2016
@@ -49,7 +49,7 @@ id foo(void) {
 @end
 
 @implementation NTGridDataObject
-- (id)initWithData:(id<MyObject, MyCoding>)data {
+- (id)initWithData:(id<MyObject, MyCoding>)data { // expected-note {{also found}}
   return data;
 }
 + (NTGridDataObject*)dataObject:(id<MyObject, MyCoding>)data




More information about the cfe-commits mailing list