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:
parent
5b15d01ff3
commit
c2371eadd6
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
Loading…
Reference in New Issue