diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td index fcdd88b7cdd7..e69312e37a24 100644 --- a/clang/include/clang/Basic/DiagnosticGroups.td +++ b/clang/include/clang/Basic/DiagnosticGroups.td @@ -174,6 +174,7 @@ def : DiagGroup<"strict-overflow">; def InvalidOffsetof : DiagGroup<"invalid-offsetof">; def : DiagGroup<"strict-prototypes">; def StrictSelector : DiagGroup<"strict-selector-match">; +def MethodDuplicate : DiagGroup<"duplicate-method-match">; def SwitchEnum : DiagGroup<"switch-enum">; def Switch : DiagGroup<"switch", [SwitchEnum]>; def Trigraphs : DiagGroup<"trigraphs">; diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 71fd2ee65371..941944c8a467 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -488,6 +488,9 @@ def warn_accessor_property_type_mismatch : Warning< def note_method_declared_at : Note<"method declared here">; def err_setter_type_void : Error<"type of setter must be void">; def err_duplicate_method_decl : Error<"duplicate declaration of method %0">; +def warn_duplicate_method_decl : + Warning<"multiple declarations of method %0 found and ignored">, + InGroup; def err_objc_var_decl_inclass : Error<"cannot declare variable inside @interface or @protocol">; def error_missing_method_context : Error< diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp index 8dd484a3b559..5b8f749db784 100644 --- a/clang/lib/Sema/SemaDeclObjC.cpp +++ b/clang/lib/Sema/SemaDeclObjC.cpp @@ -2210,8 +2210,14 @@ Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, Diag(PrevMethod->getLocation(), diag::note_previous_declaration); Method->setInvalidDecl(); } else { - if (PrevMethod) + if (PrevMethod) { Method->setAsRedeclaration(PrevMethod); + if (!Context.getSourceManager().isInSystemHeader( + Method->getLocation())) + Diag(Method->getLocation(), diag::warn_duplicate_method_decl) + << Method->getDeclName(); + Diag(PrevMethod->getLocation(), diag::note_previous_declaration); + } InsMap[Method->getSelector()] = Method; /// The following allows us to typecheck messages to "id". AddInstanceMethodToGlobalPool(Method); @@ -2231,8 +2237,14 @@ Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, Diag(PrevMethod->getLocation(), diag::note_previous_declaration); Method->setInvalidDecl(); } else { - if (PrevMethod) + if (PrevMethod) { Method->setAsRedeclaration(PrevMethod); + if (!Context.getSourceManager().isInSystemHeader( + Method->getLocation())) + Diag(Method->getLocation(), diag::warn_duplicate_method_decl) + << Method->getDeclName(); + Diag(PrevMethod->getLocation(), diag::note_previous_declaration); + } ClsMap[Method->getSelector()] = Method; /// The following allows us to typecheck messages to "Class". AddFactoryMethodToGlobalPool(Method); diff --git a/clang/test/Parser/enhanced-proto-1.m b/clang/test/Parser/enhanced-proto-1.m index a3819f3a1958..fa6e4138f1c1 100644 --- a/clang/test/Parser/enhanced-proto-1.m +++ b/clang/test/Parser/enhanced-proto-1.m @@ -4,7 +4,7 @@ @optional - (void) FOO; @optional -- (void) FOO; +- (void) FOO1; @required - (void) REQ; @optional diff --git a/clang/test/SemaObjC/DoubleMethod.m b/clang/test/SemaObjC/DoubleMethod.m index 98aa699a0fce..6c7e907cb58a 100644 --- a/clang/test/SemaObjC/DoubleMethod.m +++ b/clang/test/SemaObjC/DoubleMethod.m @@ -5,8 +5,8 @@ int ivar; } -- (void) method; -- (void) method; +- (void) method; // expected-note {{previous declaration is here}} +- (void) method; // expected-warning {{multiple declarations of method 'method' found and ignored}} @end @implementation Subclass diff --git a/clang/test/SemaObjC/check-dup-decl-methods-1.m b/clang/test/SemaObjC/check-dup-decl-methods-1.m index 1dd6446e84ca..667c38114564 100644 --- a/clang/test/SemaObjC/check-dup-decl-methods-1.m +++ b/clang/test/SemaObjC/check-dup-decl-methods-1.m @@ -10,8 +10,8 @@ @interface class1 : SUPER - (int) meth; // expected-note {{previous declaration is here}} - (int*) meth; // expected-error {{duplicate declaration of method 'meth'}} -- (T*) meth1; -- (T*) meth1; +- (T*) meth1; // expected-note {{previous declaration is here}} +- (T*) meth1; // expected-warning {{multiple declarations of method 'meth1' found and ignored}} + (T*) meth1; @end diff --git a/clang/test/SemaObjC/class-conforming-protocol-1.m b/clang/test/SemaObjC/class-conforming-protocol-1.m index 43ea6d34d1bb..5d4e86ddfe41 100644 --- a/clang/test/SemaObjC/class-conforming-protocol-1.m +++ b/clang/test/SemaObjC/class-conforming-protocol-1.m @@ -8,12 +8,11 @@ - (INTF*) METH1; // expected-note {{previous declaration is here}} - (INTF*) METH1; // expected-error {{duplicate declaration of method 'METH1'}} -- (INTF*) METH2; - (INTF*) METH2; // expected-note {{previous declaration is here}} - (INTF*) METH2; // expected-error {{duplicate declaration of method 'METH2'}} -- (INTF*) METH3; -- (INTF*) METH3; +- (INTF*) METH3; // expected-note {{previous declaration is here}} +- (INTF*) METH3; // expected-warning {{multiple declarations of method 'METH3' found and ignored}} @end diff --git a/clang/test/SemaObjC/enhanced-proto-2.m b/clang/test/SemaObjC/enhanced-proto-2.m index da7875cfa7c7..de1d56a2d773 100644 --- a/clang/test/SemaObjC/enhanced-proto-2.m +++ b/clang/test/SemaObjC/enhanced-proto-2.m @@ -4,7 +4,7 @@ @optional - (void) FOO; @optional -- (void) FOO; +- (void) FOO1; @optional - (void) REQ; @optional diff --git a/clang/test/SemaObjC/undefined-protocol-type-1.m b/clang/test/SemaObjC/undefined-protocol-type-1.m index 3be4425cdcec..f1a08024b251 100644 --- a/clang/test/SemaObjC/undefined-protocol-type-1.m +++ b/clang/test/SemaObjC/undefined-protocol-type-1.m @@ -5,5 +5,5 @@ @interface T - (T*) meth; // expected-error {{cannot find protocol declaration for 'p3'}} -- (T*) meth; // expected-error {{cannot find protocol declaration for 'p3'}} +- (T*) meth1; // expected-error {{cannot find protocol declaration for 'p3'}} @end