From: Fariborz Jahanian Date: Tue, 3 Mar 2009 22:19:15 +0000 (+0000) Subject: Implement an important missing warning when a selector X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=268bc8c1f3a27d2fbd73c3115e4d633d31422ca5;p=clang Implement an important missing warning when a selector is searched for in the global pool. It already uncovered a clang bug in message selection. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@65974 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticSemaKinds.def b/include/clang/Basic/DiagnosticSemaKinds.def index f1495a2ef4..6c635dae58 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.def +++ b/include/clang/Basic/DiagnosticSemaKinds.def @@ -1454,3 +1454,5 @@ DIAG(error_private_ivar_access, ERROR, "instance variable %0 is private") DIAG(error_protected_ivar_access, ERROR, "instance variable %0 is protected") +DIAG(warn_maynot_respond, WARNING, + "%0 may not respond to %1") diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp index 8b452af9e8..39a89d6d94 100644 --- a/lib/Sema/SemaExprObjC.cpp +++ b/lib/Sema/SemaExprObjC.cpp @@ -450,16 +450,28 @@ Sema::ExprResult Sema::ActOnInstanceMessage(ExprTy *receiver, Selector Sel, } if (!Method) { // If we have an implementation in scope, check "private" methods. - if (ClassDecl) + if (ClassDecl) { if (ObjCImplementationDecl *ImpDecl = ObjCImplementations[ClassDecl->getIdentifier()]) Method = ImpDecl->getInstanceMethod(Sel); - // If we still haven't found a method, look in the global pool. This - // behavior isn't very desirable, however we need it for GCC - // compatibility. FIXME: should we deviate?? - if (!Method && OCIType->qual_empty()) - Method = LookupInstanceMethodInGlobalPool( - Sel, SourceRange(lbrac,rbrac)); + // Look through local category implementations associated with the class. + if (!Method) { + for (unsigned i = 0; i < ObjCCategoryImpls.size() && !Method; i++) { + if (ObjCCategoryImpls[i]->getClassInterface() == ClassDecl) + Method = ObjCCategoryImpls[i]->getInstanceMethod(Sel); + } + } + } + // If we still haven't found a method, look in the global pool. This + // behavior isn't very desirable, however we need it for GCC + // compatibility. FIXME: should we deviate?? + if (!Method && OCIType->qual_empty()) { + Method = LookupInstanceMethodInGlobalPool( + Sel, SourceRange(lbrac,rbrac)); + if (Method && !OCIType->getDecl()->isForwardDecl()) + Diag(lbrac, diag::warn_maynot_respond) + << OCIType->getDecl()->getIdentifier()->getName() << Sel; + } } if (Method && DiagnoseUseOfDecl(Method, receiverLoc)) return true; diff --git a/test/SemaObjC/conditional-expr.m b/test/SemaObjC/conditional-expr.m index c607178a57..76656717e1 100644 --- a/test/SemaObjC/conditional-expr.m +++ b/test/SemaObjC/conditional-expr.m @@ -36,7 +36,7 @@ // No @interface declaration for DTFilterOutputStream3 @implementation DTFilterOutputStream3 // expected-warning {{cannot find interface declaration for 'DTFilterOutputStream3'}} - (id)initWithNextOutputStream:(id ) outputStream { - id nextOutputStream = [self nextOutputStream]; + id nextOutputStream = [self nextOutputStream]; // expected-warning {{DTFilterOutputStream3 may not respond to 'nextOutputStream'}} // GCC warns about both of these as well (no errors). self = nextOutputStream; // expected-warning {{incompatible type assigning 'id', expected 'DTFilterOutputStream3 *'}} return nextOutputStream ? nextOutputStream : self; diff --git a/test/SemaObjC/warn-selector-selection.m b/test/SemaObjC/warn-selector-selection.m new file mode 100644 index 0000000000..777666dfd9 --- /dev/null +++ b/test/SemaObjC/warn-selector-selection.m @@ -0,0 +1,14 @@ +// RUN: clang -fsyntax-only -verify %s + +@interface Object +- (void)foo; +@end + +@interface Class1 +- (void)setWindow:(Object *)wdw; +@end + +void foo(void) { + Object *obj; + [obj setWindow:0]; // expected-warning{{Object may not respond to 'setWindow:'}} +}