[cfe-commits] r66383 - in /cfe/trunk: lib/Sema/Sema.h lib/Sema/SemaExprObjC.cpp test/SemaObjC/method-lookup-4.m

Steve Naroff snaroff at apple.com
Sun Mar 8 11:56:14 PDT 2009


Author: snaroff
Date: Sun Mar  8 13:56:13 2009
New Revision: 66383

URL: http://llvm.org/viewvc/llvm-project?rev=66383&view=rev
Log:
Improvements to private method lookup.

Patch by Jean-Daniel Dupas. Thanks!

Added:
    cfe/trunk/test/SemaObjC/method-lookup-4.m
Modified:
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaExprObjC.cpp

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=66383&r1=66382&r2=66383&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Sun Mar  8 13:56:13 2009
@@ -1786,7 +1786,10 @@
   // Will search "local" class/category implementations for a method decl.
   // Will also search in class's root looking for instance method.
   // Returns 0 if no method is found.
-  ObjCMethodDecl *LookupPrivateOrRootMethod(Selector Sel, ObjCInterfaceDecl *CDecl);
+  ObjCMethodDecl *LookupPrivateClassMethod(Selector Sel, 
+                                           ObjCInterfaceDecl *CDecl);
+  ObjCMethodDecl *LookupPrivateInstanceMethod(Selector Sel,
+                                              ObjCInterfaceDecl *ClassDecl);
   
   // ActOnClassMessage - used for both unary and keyword messages.
   // ArgExprs is optional - if it is present, the number of expressions

Modified: cfe/trunk/lib/Sema/SemaExprObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprObjC.cpp?rev=66383&r1=66382&r2=66383&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaExprObjC.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprObjC.cpp Sun Mar  8 13:56:13 2009
@@ -213,29 +213,56 @@
 // Will search "local" class/category implementations for a method decl.
 // If failed, then we search in class's root for an instance method.
 // Returns 0 if no method is found.
-ObjCMethodDecl *Sema::LookupPrivateOrRootMethod(Selector Sel,
+ObjCMethodDecl *Sema::LookupPrivateClassMethod(Selector Sel,
                                           ObjCInterfaceDecl *ClassDecl) {
   ObjCMethodDecl *Method = 0;
-  
-  if (ObjCImplementationDecl *ImpDecl = 
-      ObjCImplementations[ClassDecl->getIdentifier()])
-    Method = ImpDecl->getClassMethod(Sel);
-    
-  // Look through local category implementations associated with the class.
-  if (!Method) {
-    for (unsigned i = 0; i < ObjCCategoryImpls.size() && !Method; i++) {
-      if (ObjCCategoryImpls[i]->getClassInterface() == ClassDecl)
-        Method = ObjCCategoryImpls[i]->getClassMethod(Sel);
-    }
-  }
-  // Before we give up, check if the selector is an instance method.
-  // But only in the root. This matches gcc's behaviour and what the
-  // runtime expects.
-  if (!Method) {
-    ObjCInterfaceDecl *Root = ClassDecl;
-    while (Root->getSuperClass())
-      Root = Root->getSuperClass();
-    Method = Root->lookupInstanceMethod(Sel);
+  // lookup in class and all superclasses
+  while (ClassDecl && !Method) {
+    if (ObjCImplementationDecl *ImpDecl = 
+        ObjCImplementations[ClassDecl->getIdentifier()])
+      Method = ImpDecl->getClassMethod(Sel);
+    
+    // Look through local category implementations associated with the class.
+    if (!Method) {
+      for (unsigned i = 0; i < ObjCCategoryImpls.size() && !Method; i++) {
+        if (ObjCCategoryImpls[i]->getClassInterface() == ClassDecl)
+          Method = ObjCCategoryImpls[i]->getClassMethod(Sel);
+      }
+    }
+    
+    // Before we give up, check if the selector is an instance method.
+    // But only in the root. This matches gcc's behaviour and what the
+    // runtime expects.
+    if (!Method && !ClassDecl->getSuperClass()) {
+      Method = ClassDecl->lookupInstanceMethod(Sel);
+      // Look through local category implementations associated 
+      // with the root class.
+      if (!Method) 
+        Method = LookupPrivateInstanceMethod(Sel, ClassDecl);
+    }
+    
+    ClassDecl = ClassDecl->getSuperClass();
+  }
+  return Method;
+}
+
+ObjCMethodDecl *Sema::LookupPrivateInstanceMethod(Selector Sel,
+                                              ObjCInterfaceDecl *ClassDecl) {
+  ObjCMethodDecl *Method = 0;
+  while (ClassDecl && !Method) {
+    // If we have implementations in scope, check "private" methods.
+    if (ObjCImplementationDecl *ImpDecl = 
+        ObjCImplementations[ClassDecl->getIdentifier()])
+      Method = ImpDecl->getInstanceMethod(Sel);
+    
+    // Look through local category implementations associated with the class.
+    if (!Method) {
+      for (unsigned i = 0; i < ObjCCategoryImpls.size() && !Method; i++) {
+        if (ObjCCategoryImpls[i]->getClassInterface() == ClassDecl)
+          Method = ObjCCategoryImpls[i]->getInstanceMethod(Sel);
+      }
+    }
+    ClassDecl = ClassDecl->getSuperClass();
   }
   return Method;
 }
@@ -321,7 +348,7 @@
   
   // If we have an implementation in scope, check "private" methods.
   if (!Method)
-    Method = LookupPrivateOrRootMethod(Sel, ClassDecl);
+    Method = LookupPrivateClassMethod(Sel, ClassDecl);
 
   if (Method && DiagnoseUseOfDecl(Method, receiverLoc))
     return true;
@@ -367,8 +394,13 @@
     if (ObjCMethodDecl *CurMeth = getCurMethodDecl()) {
       // If we have an interface in scope, check 'super' methods.
       if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface())
-        if (ObjCInterfaceDecl *SuperDecl = ClassDecl->getSuperClass())
+        if (ObjCInterfaceDecl *SuperDecl = ClassDecl->getSuperClass()) {
           Method = SuperDecl->lookupInstanceMethod(Sel);
+          
+          if (!Method) 
+            // If we have implementations in scope, check "private" methods.
+            Method = LookupPrivateInstanceMethod(Sel, SuperDecl);
+        }
     }
 
     if (Method && DiagnoseUseOfDecl(Method, receiverLoc))
@@ -405,7 +437,7 @@
         Method = ClassDecl->lookupClassMethod(Sel);
         
         if (!Method)
-          Method = LookupPrivateOrRootMethod(Sel, ClassDecl);
+          Method = LookupPrivateClassMethod(Sel, ClassDecl);
       }
       if (Method && DiagnoseUseOfDecl(Method, receiverLoc))
         return true;
@@ -467,24 +499,14 @@
       }
     }
     if (!Method) {
-      // If we have an implementation in scope, check "private" methods.
-      if (ClassDecl) {
-        if (ObjCImplementationDecl *ImpDecl = 
-              ObjCImplementations[ClassDecl->getIdentifier()])
-          Method = ImpDecl->getInstanceMethod(Sel);
-        // Look through local category implementations associated with the class.
-        if (!Method) {
-          for (unsigned i = 0; i < ObjCCategoryImpls.size() && !Method; i++) {
-            if (ObjCCategoryImpls[i]->getClassInterface() == ClassDecl)
-              Method = ObjCCategoryImpls[i]->getInstanceMethod(Sel);
-          }
-        }
-      }
-      if (!isSelfExpr(RExpr)) {
+      // If we have implementations in scope, check "private" methods.
+      Method = LookupPrivateInstanceMethod(Sel, ClassDecl);
+      
+      if (!Method && !isSelfExpr(RExpr)) {
         // If we still haven't found a method, look in the global pool. This
         // behavior isn't very desirable, however we need it for GCC
         // compatibility. FIXME: should we deviate??
-        if (!Method && OCIType->qual_empty()) {
+        if (OCIType->qual_empty()) {
           Method = LookupInstanceMethodInGlobalPool(
                                Sel, SourceRange(lbrac,rbrac));
           if (Method && !OCIType->getDecl()->isForwardDecl())

Added: cfe/trunk/test/SemaObjC/method-lookup-4.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/method-lookup-4.m?rev=66383&view=auto

==============================================================================
--- cfe/trunk/test/SemaObjC/method-lookup-4.m (added)
+++ cfe/trunk/test/SemaObjC/method-lookup-4.m Sun Mar  8 13:56:13 2009
@@ -0,0 +1,62 @@
+// RUN: clang -fsyntax-only -verify %s
+
+ at interface NSObject {}
+
+ at end
+
+ at interface MyClass : NSObject {}
+
+ at end
+
+ at interface MyClass (MyCategorie)
+
+ at end
+
+ at interface MySubClass : MyClass {}
+
+ at end
+
+ at interface MySubSubClass : MySubClass {}
+
+ at end
+
+ at implementation NSObject (NSObjectCategory)
+- (void)rootMethod {}
+ at end
+
+ at implementation MyClass
+
++ (void)myClassMethod { }
+- (void)myMethod { }
+
+ at end
+
+ at implementation MyClass (MyCategorie)
++ (void)myClassCategoryMethod { }
+- (void)categoryMethod {}
+ at end
+
+ at implementation MySubClass
+
+- (void)mySubMethod {}
+
+- (void)myTest {
+  [self mySubMethod];
+  // should lookup method in superclass implementation if available
+  [self myMethod];
+  [super myMethod];
+  
+  [self categoryMethod];
+  [super categoryMethod];
+  
+  // instance method of root class
+  [MyClass rootMethod];
+  
+  [MyClass myClassMethod];
+  [MySubClass myClassMethod];
+  
+  [MyClass myClassCategoryMethod];
+  [MySubClass myClassCategoryMethod];
+}
+
+ at end





More information about the cfe-commits mailing list