Fix a corner case of message lookup looking for class methods.

If all else failed, find the message in class's root's
list of instacne methods!

llvm-svn: 66040
This commit is contained in:
Fariborz Jahanian 2009-03-04 17:50:39 +00:00
parent 5b15d01ff3
commit c2371eadd6
3 changed files with 68 additions and 4 deletions

View File

@ -314,8 +314,14 @@ Sema::ExprResult Sema::ActOnClassMessage(
Method = LookupPrivateMethod(Sel, ClassDecl);
// Before we give up, check if the selector is an instance method.
if (!Method)
Method = ClassDecl->lookupInstanceMethod(Sel);
// 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);
}
if (Method && DiagnoseUseOfDecl(Method, receiverLoc))
return true;
@ -400,6 +406,15 @@ Sema::ExprResult Sema::ActOnInstanceMessage(ExprTy *receiver, Selector Sel,
if (!Method)
Method = LookupPrivateMethod(Sel, ClassDecl);
// 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);
}
}
if (Method && DiagnoseUseOfDecl(Method, receiverLoc))
return true;
@ -408,9 +423,12 @@ Sema::ExprResult Sema::ActOnInstanceMessage(ExprTy *receiver, Selector Sel,
// If not messaging 'self', look for any factory method named 'Sel'.
if (!isSelfExpr(RExpr)) {
Method = FactoryMethodPool[Sel].Method;
if (!Method)
if (!Method) {
Method = LookupInstanceMethodInGlobalPool(
Sel, SourceRange(lbrac,rbrac));
if (Method)
Diag(receiverLoc, diag::warn_maynot_respond) << Sel;
}
}
}
if (CheckMessageArgumentTypes(ArgExprs, NumArgs, Sel, Method, false,

View File

@ -83,7 +83,7 @@ id objc_getClass(const char *s);
}
- (int) instance_func5
{
int i = (size_t)[Derived instance_func1]; // GCC currently warns.
int i = (size_t)[Derived instance_func1]; // expected-warning {{method '+instance_func1' not found (return type defaults to 'id')}}
return i + (size_t)[Object instance_func1]; // expected-warning {{method '+instance_func1' not found (return type defaults to 'id')}}
}
- (int) instance_func6

View File

@ -0,0 +1,46 @@
// RUN: clang -fsyntax-only -verify %s
@interface MyBase
- (void) rootInstanceMethod;
@end
@interface MyIntermediate: MyBase
@end
@interface MyDerived: MyIntermediate
- (void) instanceMethod;
+ (void) classMethod;
@end
@implementation MyDerived
- (void) instanceMethod {
}
+ (void) classMethod { /* If a class method is not found, the root */
[self rootInstanceMethod]; /* class is searched for an instance method */
[MyIntermediate rootInstanceMethod]; /* with the same name. */
[self instanceMethod];// expected-warning {{'-instanceMethod' not found (return type defaults to 'id')}}
[MyDerived instanceMethod];// expected-warning {{'+instanceMethod' not found (return type defaults to 'id')}}
}
@end
@interface Object @end
@interface Class1
- (void)setWindow:(Object *)wdw;
@end
@interface Class2
- (void)setWindow:(Class1 *)window;
@end
#define nil (void*)0
id foo(void) {
Object *obj;
id obj2 = obj;
[obj setWindow:nil]; // expected-warning {{Object may not respond to 'setWindow:'}}
return obj;
}