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">;
InGroup<ImplicitAtomic>, DefaultIgnore;
def warn_unimplemented_selector: Warning<
"creating selector for nonexistent method %0">, InGroup<Selector>, DefaultIgnore;
+def warning_multiple_selectors: Warning<
+ "multiple selectors named %0 found">, InGroup<SelectorTypeMismatch>, DefaultIgnore;
def warn_unimplemented_protocol_method : Warning<
"method %0 in protocol not implemented">, InGroup<Protocol>;
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);
return 0;
}
-/// DiagnoseDuplicateIvars -
+static void
+HelperToDiagnoseMismatchedMethodsInGlobalPool(Sema &S,
+ ObjCMethodList &MethList) {
+ ObjCMethodList *M = &MethList;
+ ObjCMethodDecl *TargetMethod = M->Method;
+ while (TargetMethod &&
+ isa<ObjCImplDecl>(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<ObjCImplDecl>(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
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.
}
}
@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