From b7f95f5b29ea4ba4231cbcbe581502ece5033795 Mon Sep 17 00:00:00 2001 From: Fariborz Jahanian Date: Mon, 2 Mar 2009 19:05:07 +0000 Subject: [PATCH] Check for duplicate declaration of method of a class in its extension. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@65854 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/Sema.h | 3 ++ lib/Sema/SemaDeclObjC.cpp | 31 +++++++++++++++++++++ test/SemaObjC/class-extension-dup-methods.m | 15 ++++++++++ 3 files changed, 49 insertions(+) create mode 100644 test/SemaObjC/class-extension-dup-methods.m diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 30550c423d..b9cce4b215 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -1709,6 +1709,9 @@ public: void MergeProtocolPropertiesIntoClass(Decl *CDecl, DeclTy *MergeProtocols); + void DiagnoseClassExtensionDupMethods(ObjCCategoryDecl *CAT, + ObjCInterfaceDecl *ID); + void MergeOneProtocolPropertiesIntoClass(Decl *CDecl, ObjCProtocolDecl *PDecl); diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index f1f03844a2..fe26090a17 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -443,6 +443,35 @@ void Sema::MergeProtocolPropertiesIntoClass(Decl *CDecl, } } +/// DiagnoseClassExtensionDupMethods - Check for duplicate declartation of +/// a class method in its extension. +/// +void Sema::DiagnoseClassExtensionDupMethods(ObjCCategoryDecl *CAT, + ObjCInterfaceDecl *ID) { + if (!ID) + return; // Possibly due to previous error + + llvm::DenseMap MethodMap; + for (ObjCInterfaceDecl::method_iterator i = ID->meth_begin(), + e = ID->meth_end(); i != e; ++i) { + ObjCMethodDecl *MD = *i; + MethodMap[MD->getSelector()] = MD; + } + + if (MethodMap.empty()) + return; + for (ObjCCategoryDecl::method_iterator i = CAT->meth_begin(), + e = CAT->meth_end(); i != e; ++i) { + ObjCMethodDecl *Method = *i; + const ObjCMethodDecl *&PrevMethod = MethodMap[Method->getSelector()]; + if (PrevMethod && !MatchTwoMethodDeclarations(Method, PrevMethod)) { + Diag(Method->getLocation(), diag::err_duplicate_method_decl) + << Method->getDeclName(); + Diag(PrevMethod->getLocation(), diag::note_previous_declaration); + } + } +} + /// ActOnForwardProtocolDeclaration - Action::DeclTy * Sema::ActOnForwardProtocolDeclaration(SourceLocation AtProtocolLoc, @@ -1237,6 +1266,8 @@ void Sema::ActOnAtEnd(SourceLocation AtEndLoc, DeclTy *classDecl, // Merge protocol properties into category MergeProtocolPropertiesIntoClass(C, C); + if (C->getIdentifier() == 0) + DiagnoseClassExtensionDupMethods(C, C->getClassInterface()); } if (ObjCContainerDecl *CDecl = dyn_cast(ClassDecl)) { // ProcessPropertyDecl is responsible for diagnosing conflicts with any diff --git a/test/SemaObjC/class-extension-dup-methods.m b/test/SemaObjC/class-extension-dup-methods.m new file mode 100644 index 0000000000..d13b218cc7 --- /dev/null +++ b/test/SemaObjC/class-extension-dup-methods.m @@ -0,0 +1,15 @@ +// RUN: clang -fsyntax-only -verify %s + +@interface Foo +- (int) garf; // expected-note {{ previous declaration is here}} +- (int) OK; ++ (int) cgarf; // expected-note {{ previous declaration is here}} +- (int) InstMeth; +@end + +@interface Foo() +- (void) garf; // expected-error {{duplicate declaration of method 'garf'}} ++ (void) cgarf; // expected-error {{duplicate declaration of method 'cgarf'}} ++ (int) InstMeth; +- (int) OK; +@end -- 2.40.0