]> granicus.if.org Git - clang/commitdiff
Check for duplicate declaration of method of a class
authorFariborz Jahanian <fjahanian@apple.com>
Mon, 2 Mar 2009 19:05:07 +0000 (19:05 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Mon, 2 Mar 2009 19:05:07 +0000 (19:05 +0000)
in its extension.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@65854 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/Sema.h
lib/Sema/SemaDeclObjC.cpp
test/SemaObjC/class-extension-dup-methods.m [new file with mode: 0644]

index 30550c423d7cd1dbfca5326a31b393c4b44b0c24..b9cce4b215ca3cf3619af45a90727166a8f1434c 100644 (file)
@@ -1709,6 +1709,9 @@ public:
   void MergeProtocolPropertiesIntoClass(Decl *CDecl,
                                         DeclTy *MergeProtocols);
   
+  void DiagnoseClassExtensionDupMethods(ObjCCategoryDecl *CAT, 
+                                        ObjCInterfaceDecl *ID);
+  
   void MergeOneProtocolPropertiesIntoClass(Decl *CDecl,
                                            ObjCProtocolDecl *PDecl);
   
index f1f03844a2439b97794dc539de3af546d642bff6..fe26090a174848821921cddef8f200eaec258b6b 100644 (file)
@@ -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<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 @@ 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<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 (file)
index 0000000..d13b218
--- /dev/null
@@ -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