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;
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;
// 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,
--- /dev/null
+// 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;
+}