]> granicus.if.org Git - clang/commitdiff
Patch to diagnose duplicate method implementations.
authorFariborz Jahanian <fjahanian@apple.com>
Tue, 16 Oct 2007 21:52:23 +0000 (21:52 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Tue, 16 Oct 2007 21:52:23 +0000 (21:52 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@43046 91177308-0d34-0410-b5e6-96231b3b80d8

Sema/SemaDecl.cpp
clang.xcodeproj/project.pbxproj
test/Sema/DoubleMethod.m [new file with mode: 0644]

index bb100c67ce42558d4f2d83a05f91fcd3215f2e4f..76d1628bfc2deec557c4aa81083fb5429ef4dd32 100644 (file)
@@ -1837,6 +1837,7 @@ void Sema::ActOnAddMethodsToObjcDecl(Scope* S, DeclTy *classDecl,
   bool checkDuplicateMethods = 
         (isa<ObjcInterfaceDecl>(ClassDecl) || isa<ObjcCategoryDecl>(ClassDecl)
          || isa<ObjcProtocolDecl>(ClassDecl));
+  bool checkIdenticalMethods = isa<ObjcImplementationDecl>(ClassDecl);
   
   for (unsigned i = 0; i < allNum; i++ ) {
     ObjcMethodDecl *Method =
@@ -1844,41 +1845,38 @@ void Sema::ActOnAddMethodsToObjcDecl(Scope* S, DeclTy *classDecl,
 
     if (!Method) continue;  // Already issued a diagnostic.
     if (Method->isInstance()) {
-      if (checkDuplicateMethods) {
-        /// Check for instance method of the same name with incompatible types
-        const ObjcMethodDecl *&PrevMethod = InsMap[Method->getSelector()];
-        if (PrevMethod && !MatchTwoMethodDeclarations(Method, PrevMethod)) {
+      /// Check for instance method of the same name with incompatible types
+      const ObjcMethodDecl *&PrevMethod = InsMap[Method->getSelector()];
+      bool match = PrevMethod ? MatchTwoMethodDeclarations(Method, PrevMethod) 
+                              : false;
+      if (checkDuplicateMethods && PrevMethod && !match 
+          || checkIdenticalMethods && match) {
           Diag(Method->getLocation(), diag::error_duplicate_method_decl,
                Method->getSelector().getName());
           Diag(PrevMethod->getLocation(), diag::err_previous_declaration);
-        } else {
-          insMethods.push_back(Method);
-          InsMap[Method->getSelector()] = Method;
-        }
-      }
-      else
+      } else {
         insMethods.push_back(Method);
-        
-      /// The following allows us to typecheck messages to "id".
-      AddInstanceMethodToGlobalPool(Method);
-    } else {
-      if (checkDuplicateMethods) {
-        /// Check for class method of the same name with incompatible types
-        const ObjcMethodDecl *&PrevMethod = ClsMap[Method->getSelector()];
-        if (PrevMethod && !MatchTwoMethodDeclarations(Method, PrevMethod)) {
-          Diag(Method->getLocation(), diag::error_duplicate_method_decl,
-               Method->getSelector().getName());
-          Diag(PrevMethod->getLocation(), diag::err_previous_declaration);
-        } else {        
-          clsMethods.push_back(Method);
-          ClsMap[Method->getSelector()] = Method;
-        }
+        InsMap[Method->getSelector()] = Method;
+        /// The following allows us to typecheck messages to "id".
+        AddInstanceMethodToGlobalPool(Method);
       }
-      else
+    }
+    else {
+      /// Check for class method of the same name with incompatible types
+      const ObjcMethodDecl *&PrevMethod = ClsMap[Method->getSelector()];
+      bool match = PrevMethod ? MatchTwoMethodDeclarations(Method, PrevMethod) 
+                              : false;
+      if (checkDuplicateMethods && PrevMethod && !match 
+          || checkIdenticalMethods && match) {
+        Diag(Method->getLocation(), diag::error_duplicate_method_decl,
+             Method->getSelector().getName());
+        Diag(PrevMethod->getLocation(), diag::err_previous_declaration);
+      } else {
         clsMethods.push_back(Method);
-        
-      /// The following allows us to typecheck messages to "id".
-      AddFactoryMethodToGlobalPool(Method);
+        ClsMap[Method->getSelector()] = Method;
+        /// The following allows us to typecheck messages to "id".
+        AddInstanceMethodToGlobalPool(Method);
+      }
     }
   }
   
index 33627a1f29daae1f318dd95b4da2b914de67e111..75d938806b0068e9faf478a9935977559b88f772 100644 (file)
                84AF36A00CB17A3B00C820A5 /* DeclObjC.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = DeclObjC.h; path = clang/AST/DeclObjC.h; sourceTree = "<group>"; };
                84D9A8870C1A57E100AC7ABC /* AttributeList.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = AttributeList.cpp; path = Parse/AttributeList.cpp; sourceTree = "<group>"; };
                84D9A88B0C1A581300AC7ABC /* AttributeList.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = AttributeList.h; path = clang/Parse/AttributeList.h; sourceTree = "<group>"; };
-               8DD76F6C0486A84900D96B5E /* clang */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = "compiled.mach-o.executable"; path = clang; sourceTree = BUILT_PRODUCTS_DIR; };
+               8DD76F6C0486A84900D96B5E /* clang */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = clang; sourceTree = BUILT_PRODUCTS_DIR; };
                DE01DA480B12ADA300AC22CE /* PPCallbacks.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PPCallbacks.h; sourceTree = "<group>"; };
                DE06756B0C051CFE00EBBFD8 /* ParseExprCXX.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ParseExprCXX.cpp; path = Parse/ParseExprCXX.cpp; sourceTree = "<group>"; };
                DE06B73D0A8307640050E87E /* LangOptions.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = LangOptions.h; sourceTree = "<group>"; };
diff --git a/test/Sema/DoubleMethod.m b/test/Sema/DoubleMethod.m
new file mode 100644 (file)
index 0000000..70c7ed5
--- /dev/null
@@ -0,0 +1,19 @@
+// RUN: clang -fsyntax-only -verify %s
+
+@interface Subclass
+{
+    int ivar;
+}
+
+- (void) method;
+- (void) method;
+@end
+
+@implementation Subclass
+- (void) method {;} // expected-error {{previous declaration is here}}
+- (void) method {;} // expected-error {{duplicate declaration of method 'method'}}
+@end
+
+int main (void) {
+    return 0;
+}