forked from OSchip/llvm-project
Improvements to private method lookup.
Patch by Jean-Daniel Dupas. Thanks! llvm-svn: 66383
This commit is contained in:
parent
d5ac9d87b4
commit
ed03170d28
|
@ -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
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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
|
Loading…
Reference in New Issue