summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/lib/Sema/Sema.h5
-rw-r--r--clang/lib/Sema/SemaExprObjC.cpp94
-rw-r--r--clang/test/SemaObjC/method-lookup-4.m62
3 files changed, 124 insertions, 37 deletions
diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h
index 28cb9bf7153..1ef579f687e 100644
--- a/clang/lib/Sema/Sema.h
+++ b/clang/lib/Sema/Sema.h
@@ -1786,7 +1786,10 @@ public:
// 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
diff --git a/clang/lib/Sema/SemaExprObjC.cpp b/clang/lib/Sema/SemaExprObjC.cpp
index 5c8b7b745df..ef397ca771c 100644
--- a/clang/lib/Sema/SemaExprObjC.cpp
+++ b/clang/lib/Sema/SemaExprObjC.cpp
@@ -213,29 +213,56 @@ bool Sema::isSelfExpr(Expr *RExpr) {
// 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);
+ // 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);
+ // 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();
}
- // 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);
+ 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 @@ Sema::ExprResult Sema::ActOnClassMessage(
// 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 @@ Sema::ExprResult Sema::ActOnInstanceMessage(ExprTy *receiver, Selector Sel,
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 @@ Sema::ExprResult Sema::ActOnInstanceMessage(ExprTy *receiver, Selector Sel,
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 @@ Sema::ExprResult Sema::ActOnInstanceMessage(ExprTy *receiver, Selector Sel,
}
}
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())
diff --git a/clang/test/SemaObjC/method-lookup-4.m b/clang/test/SemaObjC/method-lookup-4.m
new file mode 100644
index 00000000000..f5a20f5a741
--- /dev/null
+++ b/clang/test/SemaObjC/method-lookup-4.m
@@ -0,0 +1,62 @@
+// RUN: clang -fsyntax-only -verify %s
+
+@interface NSObject {}
+
+@end
+
+@interface MyClass : NSObject {}
+
+@end
+
+@interface MyClass (MyCategorie)
+
+@end
+
+@interface MySubClass : MyClass {}
+
+@end
+
+@interface MySubSubClass : MySubClass {}
+
+@end
+
+@implementation NSObject (NSObjectCategory)
+- (void)rootMethod {}
+@end
+
+@implementation MyClass
+
++ (void)myClassMethod { }
+- (void)myMethod { }
+
+@end
+
+@implementation MyClass (MyCategorie)
++ (void)myClassCategoryMethod { }
+- (void)categoryMethod {}
+@end
+
+@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];
+}
+
+@end
OpenPOWER on IntegriCloud