From b1006c7f5647025541b1b1cc64a196a417e6c6ac Mon Sep 17 00:00:00 2001 From: Fariborz Jahanian Date: Wed, 4 Mar 2009 17:50:39 +0000 Subject: [PATCH] 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! git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@66040 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaExprObjC.cpp | 24 +++++++++++++-- test/SemaObjC/call-super-2.m | 2 +- test/SemaObjC/class-method-lookup.m | 46 +++++++++++++++++++++++++++++ 3 files changed, 68 insertions(+), 4 deletions(-) create mode 100644 test/SemaObjC/class-method-lookup.m diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp index 8705baffcb..80120a7b7a 100644 --- a/lib/Sema/SemaExprObjC.cpp +++ b/lib/Sema/SemaExprObjC.cpp @@ -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, diff --git a/test/SemaObjC/call-super-2.m b/test/SemaObjC/call-super-2.m index 98e4e08857..a1f8c8722e 100644 --- a/test/SemaObjC/call-super-2.m +++ b/test/SemaObjC/call-super-2.m @@ -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 diff --git a/test/SemaObjC/class-method-lookup.m b/test/SemaObjC/class-method-lookup.m new file mode 100644 index 0000000000..a62f0f0047 --- /dev/null +++ b/test/SemaObjC/class-method-lookup.m @@ -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; +} -- 2.40.0