From: Fariborz Jahanian Date: Wed, 12 Mar 2014 18:34:01 +0000 (+0000) Subject: Objective-C. Issue diagnostics on mismatched methods when their selector is used X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=258ede62c01a3701fa0d4b23ac02306eef795abf;p=clang Objective-C. Issue diagnostics on mismatched methods when their selector is used in an @selector expression. // rdar://15794055 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@203693 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 49d1d676fa..727e229644 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -892,7 +892,9 @@ def warn_unimplemented_selector: Warning< InGroup, DefaultIgnore; def warn_unimplemented_protocol_method : Warning< "method %0 in protocol %1 not implemented">, InGroup; - +def warning_multiple_selectors: Warning< + "several methods with selector %0 of mismatched types are found for the @selector expression">, + InGroup; // C++ declarations def err_static_assert_expression_is_not_constant : Error< "static_assert expression is not an integral constant expression">; diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp index 0d41d2ef81..2e5c132a4d 100644 --- a/lib/Sema/SemaExprObjC.cpp +++ b/lib/Sema/SemaExprObjC.cpp @@ -973,6 +973,58 @@ ExprResult Sema::ParseObjCEncodeExpression(SourceLocation AtLoc, return BuildObjCEncodeExpression(AtLoc, TInfo, RParenLoc); } +static bool HelperToDiagnoseMismatchedMethodsInGlobalPool(Sema &S, + SourceLocation AtLoc, + ObjCMethodDecl *Method, + ObjCMethodList &MethList) { + ObjCMethodList *M = &MethList; + bool Warned = false; + for (M = M->getNext(); M; M=M->getNext()) { + ObjCMethodDecl *MatchingMethodDecl = M->Method; + if (MatchingMethodDecl == Method || + isa(MatchingMethodDecl->getDeclContext()) || + MatchingMethodDecl->getSelector() != Method->getSelector()) + continue; + if (!S.MatchTwoMethodDeclarations(Method, + MatchingMethodDecl, Sema::MMS_loose)) { + if (!Warned) { + Warned = true; + S.Diag(AtLoc, diag::warning_multiple_selectors) + << Method->getSelector(); + S.Diag(Method->getLocation(), diag::note_method_declared_at) + << Method->getDeclName(); + } + S.Diag(MatchingMethodDecl->getLocation(), diag::note_method_declared_at) + << MatchingMethodDecl->getDeclName(); + } + } + return Warned; +} + +static void DiagnoseMismatchedSelectors(Sema &S, SourceLocation AtLoc, + ObjCMethodDecl *Method) { + unsigned DIAG = diag::warning_multiple_selectors; + if (S.Diags.getDiagnosticLevel(DIAG, SourceLocation()) + == DiagnosticsEngine::Ignored) + return; + bool Warned = false; + for (Sema::GlobalMethodPool::iterator b = S.MethodPool.begin(), + e = S.MethodPool.end(); b != e; b++) { + // first, instance methods + ObjCMethodList &InstMethList = b->second.first; + if (HelperToDiagnoseMismatchedMethodsInGlobalPool(S, AtLoc, + Method, InstMethList)) + Warned = true; + + // second, class methods + ObjCMethodList &ClsMethList = b->second.second; + if (HelperToDiagnoseMismatchedMethodsInGlobalPool(S, AtLoc, + Method, ClsMethList) || + Warned) + return; + } +} + ExprResult Sema::ParseObjCSelectorExpression(Selector Sel, SourceLocation AtLoc, SourceLocation SelLoc, @@ -994,7 +1046,8 @@ ExprResult Sema::ParseObjCSelectorExpression(Selector Sel, } else Diag(SelLoc, diag::warn_undeclared_selector) << Sel; - } + } else + DiagnoseMismatchedSelectors(*this, AtLoc, Method); if (!Method || Method->getImplementationControl() != ObjCMethodDecl::Optional) { diff --git a/test/SemaObjC/selector-1.m b/test/SemaObjC/selector-1.m index 33f8a8d36c..faa742616d 100644 --- a/test/SemaObjC/selector-1.m +++ b/test/SemaObjC/selector-1.m @@ -1,18 +1,17 @@ // RUN: %clang_cc1 -verify %s -// expected-no-diagnostics @interface I -- (id) compare: (char) arg1; +- (id) compare: (char) arg1; // expected-note {{method 'compare:' declared here}} - length; @end @interface J -- (id) compare: (id) arg1; +- (id) compare: (id) arg1; // expected-note {{method 'compare:' declared here}} @end SEL func() { - return @selector(compare:); // no warning on multiple selector found. + return @selector(compare:); // expected-warning {{several methods with selector 'compare:' of mismatched types are found for the @selector expression}} } int main() { @@ -27,3 +26,26 @@ int main() { SEL s9 = @selector(:enum:bool:); } + +// rdar://15794055 +@interface NSObject @end + +@class NSNumber; + +@interface XBRecipe : NSObject +@property (nonatomic, assign) float finalVolume; // expected-note {{method 'setFinalVolume:' declared here}} +@end + +@interface XBDocument : NSObject +@end + +@interface XBDocument () +- (void)setFinalVolume:(NSNumber *)finalVolumeNumber; // expected-note {{method 'setFinalVolume:' declared here}} +@end + +@implementation XBDocument +- (void)setFinalVolume:(NSNumber *)finalVolumeNumber +{ + (void)@selector(setFinalVolume:); // expected-warning {{several methods with selector 'setFinalVolume:' of mismatched types are found for the @selector expression}} +} +@end