summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
Diffstat (limited to 'clang')
-rw-r--r--clang/lib/Sema/SemaExprObjC.cpp24
-rw-r--r--clang/test/SemaObjC/call-super-2.m2
-rw-r--r--clang/test/SemaObjC/class-method-lookup.m46
3 files changed, 68 insertions, 4 deletions
diff --git a/clang/lib/Sema/SemaExprObjC.cpp b/clang/lib/Sema/SemaExprObjC.cpp
index 8705baffcb6..80120a7b7a4 100644
--- a/clang/lib/Sema/SemaExprObjC.cpp
+++ b/clang/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/clang/test/SemaObjC/call-super-2.m b/clang/test/SemaObjC/call-super-2.m
index 98e4e088576..a1f8c8722e1 100644
--- a/clang/test/SemaObjC/call-super-2.m
+++ b/clang/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/clang/test/SemaObjC/class-method-lookup.m b/clang/test/SemaObjC/class-method-lookup.m
new file mode 100644
index 00000000000..a62f0f0047f
--- /dev/null
+++ b/clang/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;
+}
OpenPOWER on IntegriCloud