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
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 30550c4..b9cce4b 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -1709,6 +1709,9 @@
   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 f1f0384..fe26090 100644
--- a/lib/Sema/SemaDeclObjC.cpp
+++ b/lib/Sema/SemaDeclObjC.cpp
@@ -443,6 +443,35 @@
   }
 }
 
+/// 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<Selector, const ObjCMethodDecl*> 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 @@
 
     // Merge protocol properties into category
     MergeProtocolPropertiesIntoClass(C, C);
+    if (C->getIdentifier() == 0)
+      DiagnoseClassExtensionDupMethods(C, C->getClassInterface());
   }
   if (ObjCContainerDecl *CDecl = dyn_cast<ObjCContainerDecl>(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 0000000..d13b218
--- /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