From: Fariborz Jahanian Date: Thu, 30 May 2013 21:48:58 +0000 (+0000) Subject: Objective-C: Implements gcc's -Wselector option X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f98c688968777214bfff7a6cc9bbd4ff78e9c1d3;p=clang Objective-C: Implements gcc's -Wselector option which diagnoses type mismatches of identical selectors declared in classes throughout. // rdar://14007194 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@182964 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td index 565a01745f..8259e2e368 100644 --- a/include/clang/Basic/DiagnosticGroups.td +++ b/include/clang/Basic/DiagnosticGroups.td @@ -338,7 +338,8 @@ def AutomaticReferenceCounting : DiagGroup<"arc", def ARCRepeatedUseOfWeakMaybe : DiagGroup<"arc-maybe-repeated-use-of-weak">; def ARCRepeatedUseOfWeak : DiagGroup<"arc-repeated-use-of-weak", [ARCRepeatedUseOfWeakMaybe]>; -def Selector : DiagGroup<"selector">; +def SelectorTypeMismatch : DiagGroup<"selector-type-mismatch">; +def Selector : DiagGroup<"selector", [SelectorTypeMismatch]>; def Protocol : DiagGroup<"protocol">; def SuperSubClassMismatch : DiagGroup<"super-class-method-mismatch">; def OverridingMethodMismatch : DiagGroup<"overriding-method-mismatch">; diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index aff02f30fc..d49457b1a5 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -824,6 +824,8 @@ def warn_auto_implicit_atomic_property : Warning< InGroup, DefaultIgnore; def warn_unimplemented_selector: Warning< "creating selector for nonexistent method %0">, InGroup, DefaultIgnore; +def warning_multiple_selectors: Warning< + "multiple selectors named %0 found">, InGroup, DefaultIgnore; def warn_unimplemented_protocol_method : Warning< "method %0 in protocol not implemented">, InGroup; diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 3b4c213e94..22490171c8 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -2669,6 +2669,11 @@ public: warn, /*instance*/false); } + /// DiagnoseMismatchedMethodsInGlobalPool - This routine goes through list of + /// methods in global pool and issues diagnostic on identical selectors which + /// have mismathched types. + void DiagnoseMismatchedMethodsInGlobalPool(); + /// LookupImplementedMethodInGlobalPool - Returns the method which has an /// implementation. ObjCMethodDecl *LookupImplementedMethodInGlobalPool(Selector Sel); diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index 687cdf114a..58ea014784 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -2271,7 +2271,52 @@ ObjCMethodDecl *Sema::LookupImplementedMethodInGlobalPool(Selector Sel) { return 0; } -/// DiagnoseDuplicateIvars - +static void +HelperToDiagnoseMismatchedMethodsInGlobalPool(Sema &S, + ObjCMethodList &MethList) { + ObjCMethodList *M = &MethList; + ObjCMethodDecl *TargetMethod = M->Method; + while (TargetMethod && + isa(TargetMethod->getDeclContext())) { + M = M->getNext(); + TargetMethod = M ? M->Method : 0; + } + if (!TargetMethod) + return; + bool FirstTime = true; + for (M = M->getNext(); M; M=M->getNext()) { + ObjCMethodDecl *MatchingMethodDecl = M->Method; + if (isa(MatchingMethodDecl->getDeclContext())) + continue; + if (!S.MatchTwoMethodDeclarations(TargetMethod, + MatchingMethodDecl, Sema::MMS_loose)) { + if (FirstTime) { + FirstTime = false; + S.Diag(TargetMethod->getLocation(), diag::warning_multiple_selectors) + << TargetMethod->getSelector(); + } + S.Diag(MatchingMethodDecl->getLocation(), diag::note_also_found); + } + } +} + +void Sema::DiagnoseMismatchedMethodsInGlobalPool() { + unsigned DIAG = diag::warning_multiple_selectors; + if (Diags.getDiagnosticLevel(DIAG, SourceLocation()) + == DiagnosticsEngine::Ignored) + return; + for (GlobalMethodPool::iterator b = MethodPool.begin(), + e = MethodPool.end(); b != e; b++) { + // first, instance methods + ObjCMethodList &InstMethList = b->second.first; + HelperToDiagnoseMismatchedMethodsInGlobalPool(*this, InstMethList); + // second, instance methods + ObjCMethodList &ClsMethList = b->second.second; + HelperToDiagnoseMismatchedMethodsInGlobalPool(*this, ClsMethList); + } +} + +/// DiagnoseDuplicateIvars - /// Check for duplicate ivars in the entire class at the start of /// \@implementation. This becomes necesssary because class extension can /// add ivars to a class in random order which will not be known until @@ -3294,6 +3339,8 @@ void Sema::DiagnoseUseOfUnimplementedSelectors() { ReferencedSelectors[Sels[I].first] = Sels[I].second; } + DiagnoseMismatchedMethodsInGlobalPool(); + // Warning will be issued only when selector table is // generated (which means there is at lease one implementation // in the TU). This is to match gcc's behavior. diff --git a/test/PCH/Inputs/chain-selectors2.h b/test/PCH/Inputs/chain-selectors2.h index 973fc107e9..d54244de61 100644 --- a/test/PCH/Inputs/chain-selectors2.h +++ b/test/PCH/Inputs/chain-selectors2.h @@ -1,6 +1,6 @@ @interface Y -(void)f; - -(double)f2; + -(void)f2; -(void)e; @end diff --git a/test/SemaObjC/selector-3.m b/test/SemaObjC/selector-3.m index 92117db7bc..d782c784f1 100644 --- a/test/SemaObjC/selector-3.m +++ b/test/SemaObjC/selector-3.m @@ -81,3 +81,32 @@ extern SEL MySelector(SEL s); } } @end + +// rdar://14007194 +@interface UxTechTest : NSObject +- (int) invalidate : (id)Arg; // expected-warning {{multiple selectors named 'invalidate:' found}} ++ (int) C_invalidate : (int)arg; // expected-warning {{multiple selectors named 'C_invalidate:' found}} +@end + +@interface UxTechTest(CAT) +- (char) invalidate : (int)arg; // expected-note {{also found}} ++ (int) C_invalidate : (char)arg; // expected-note {{also found}} +@end + +@interface NSPort : NSObject +- (double) invalidate : (void*)Arg1; // expected-note {{also found}} ++ (int) C_invalidate : (id*)arg; // expected-note {{also found}} +@end + + +@interface USEText : NSPort +- (int) invalidate : (int)arg; // expected-note {{also found}} +@end + +@implementation USEText +- (int) invalidate :(int) arg { return 0; } +@end + +@interface USETextSub : USEText +- (int) invalidate : (id)arg; +@end