[cfe-commits] r42641 - in /cfe/trunk: Sema/Sema.h Sema/SemaDecl.cpp clang.xcodeproj/project.pbxproj include/clang/AST/DeclObjC.h include/clang/Basic/DiagnosticKinds.def test/Sema/check-dup-decl-methods-1.m

Fariborz Jahanian fjahanian at apple.com
Fri Oct 5 11:00:58 PDT 2007


Author: fjahanian
Date: Fri Oct  5 13:00:57 2007
New Revision: 42641

URL: http://llvm.org/viewvc/llvm-project?rev=42641&view=rev
Log:
Patch for 1) Checking for duplicate methods decls in intterface and category.
2) Use of the new DenseSet<t> abstractions instead of DenseMap<t,char>.

Added:
    cfe/trunk/test/Sema/check-dup-decl-methods-1.m
Modified:
    cfe/trunk/Sema/Sema.h
    cfe/trunk/Sema/SemaDecl.cpp
    cfe/trunk/clang.xcodeproj/project.pbxproj
    cfe/trunk/include/clang/AST/DeclObjC.h
    cfe/trunk/include/clang/Basic/DiagnosticKinds.def

Modified: cfe/trunk/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Sema/Sema.h?rev=42641&r1=42640&r2=42641&view=diff

==============================================================================
--- cfe/trunk/Sema/Sema.h (original)
+++ cfe/trunk/Sema/Sema.h Fri Oct  5 13:00:57 2007
@@ -18,6 +18,7 @@
 #include "clang/Parse/Action.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/DenseSet.h"
 #include <vector>
 #include <string>
 
@@ -52,6 +53,7 @@
   class ObjcCategoryImplDecl;
   class ObjcCategoryDecl;
   class ObjcIvarDecl;
+  class ObjcMethodDecl;
 
 /// Sema - This implements semantic analysis and AST building for C.
 class Sema : public Action {
@@ -214,8 +216,8 @@
   /// Declared in protocol, and those referenced by it.
   void CheckProtocolMethodDefs(ObjcProtocolDecl *PDecl,
                                bool& IncompleteImpl,
-                               const llvm::DenseMap<void *, char>& InsMap,
-                               const llvm::DenseMap<void *, char>& ClsMap);
+                               const llvm::DenseSet<void *>& InsMap,
+                               const llvm::DenseSet<void *>& ClsMap);
   
   /// CheckImplementationIvars - This routine checks if the instance variables
   /// listed in the implelementation match those listed in the interface. 
@@ -231,6 +233,10 @@
   /// category interface is implemented in the category @implementation.
   void ImplCategoryMethodsVsIntfMethods(ObjcCategoryImplDecl *CatImplDecl,
                                         ObjcCategoryDecl *CatClassDecl);
+  /// MatchTwoMethodDeclarations - Checks if two methods' type match and returns
+  /// true, or false, accordingly.
+  bool MatchTwoMethodDeclarations(const ObjcMethodDecl *Method, 
+                                  const ObjcMethodDecl *PrevMethod); 
   
   //===--------------------------------------------------------------------===//
   // Statement Parsing Callbacks: SemaStmt.cpp.

Modified: cfe/trunk/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Sema/SemaDecl.cpp?rev=42641&r1=42640&r2=42641&view=diff

==============================================================================
--- cfe/trunk/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/Sema/SemaDecl.cpp Fri Oct  5 13:00:57 2007
@@ -25,6 +25,7 @@
 #include "clang/Basic/TargetInfo.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/SmallSet.h"
+#include "llvm/ADT/DenseSet.h"
 using namespace clang;
 
 Sema::DeclTy *Sema::isTypeName(const IdentifierInfo &II, Scope *S) const {
@@ -1219,17 +1220,19 @@
 /// Declared in protocol, and those referenced by it.
 void Sema::CheckProtocolMethodDefs(ObjcProtocolDecl *PDecl,
                                    bool& IncompleteImpl,
-             const llvm::DenseMap<void *, char>& InsMap,
-             const llvm::DenseMap<void *, char>& ClsMap) {
+             const llvm::DenseSet<void *>& InsMap,
+             const llvm::DenseSet<void *>& ClsMap) {
   // check unimplemented instance methods.
   ObjcMethodDecl** methods = PDecl->getInstanceMethods();
-  for (int j = 0; j < PDecl->getNumInstanceMethods(); j++)
-    if (!InsMap.count(methods[j]->getSelector().getAsOpaquePtr())) {
+  for (int j = 0; j < PDecl->getNumInstanceMethods(); j++) {
+    void * cpv = methods[j]->getSelector().getAsOpaquePtr();
+    if (!InsMap.count(cpv)) {
       llvm::SmallString<128> buf;
       Diag(methods[j]->getLocation(), diag::warn_undef_method_impl,
            methods[j]->getSelector().getName(buf));
       IncompleteImpl = true;
     }
+  }
   // check unimplemented class methods
   methods = PDecl->getClassMethods();
   for (int j = 0; j < PDecl->getNumClassMethods(); j++)
@@ -1248,13 +1251,12 @@
 
 void Sema::ImplMethodsVsClassMethods(ObjcImplementationDecl* IMPDecl, 
                                      ObjcInterfaceDecl* IDecl) {
-  llvm::DenseMap<void *, char> InsMap;
+  llvm::DenseSet<void *> InsMap;
   // Check and see if instance methods in class interface have been
   // implemented in the implementation class.
   ObjcMethodDecl **methods = IMPDecl->getInstanceMethods();
-  for (int i=0; i < IMPDecl->getNumInstanceMethods(); i++) {
-    InsMap[methods[i]->getSelector().getAsOpaquePtr()] = 'a';
-  }
+  for (int i=0; i < IMPDecl->getNumInstanceMethods(); i++) 
+    InsMap.insert(methods[i]->getSelector().getAsOpaquePtr());
   
   bool IncompleteImpl = false;
   methods = IDecl->getInstanceMethods();
@@ -1265,13 +1267,12 @@
            methods[j]->getSelector().getName(buf));
       IncompleteImpl = true;
     }
-  llvm::DenseMap<void *, char> ClsMap;
+  llvm::DenseSet<void *> ClsMap;
   // Check and see if class methods in class interface have been
   // implemented in the implementation class.
   methods = IMPDecl->getClassMethods();
-  for (int i=0; i < IMPDecl->getNumClassMethods(); i++) {
-    ClsMap[methods[i]->getSelector().getAsOpaquePtr()] = 'a';
-  }
+  for (int i=0; i < IMPDecl->getNumClassMethods(); i++)
+    ClsMap.insert(methods[i]->getSelector().getAsOpaquePtr());
   
   methods = IDecl->getClassMethods();
   for (int j = 0; j < IDecl->getNumClassMethods(); j++)
@@ -1298,13 +1299,12 @@
 /// category interface is implemented in the category @implementation.
 void Sema::ImplCategoryMethodsVsIntfMethods(ObjcCategoryImplDecl *CatImplDecl,
                                             ObjcCategoryDecl *CatClassDecl) {
-  llvm::DenseMap<void *, char> InsMap;
+  llvm::DenseSet<void *> InsMap;
   // Check and see if instance methods in category interface have been
   // implemented in its implementation class.
   ObjcMethodDecl **methods = CatImplDecl->getInstanceMethods();
-  for (int i=0; i < CatImplDecl->getNumInstanceMethods(); i++) {
-    InsMap[methods[i]->getSelector().getAsOpaquePtr()] = 'a';
-  }
+  for (int i=0; i < CatImplDecl->getNumInstanceMethods(); i++)
+    InsMap.insert(methods[i]->getSelector().getAsOpaquePtr());
   
   bool IncompleteImpl = false;
   methods = CatClassDecl->getInstanceMethods();
@@ -1315,13 +1315,12 @@
            methods[j]->getSelector().getName(buf));
       IncompleteImpl = true;
     }
-  llvm::DenseMap<void *, char> ClsMap;
+  llvm::DenseSet<void *> ClsMap;
   // Check and see if class methods in category interface have been
   // implemented in its implementation class.
   methods = CatImplDecl->getClassMethods();
-  for (int i=0; i < CatImplDecl->getNumClassMethods(); i++) {
-    ClsMap[methods[i]->getSelector().getAsOpaquePtr()] = 'a';
-  }
+  for (int i=0; i < CatImplDecl->getNumClassMethods(); i++)
+    ClsMap.insert(methods[i]->getSelector().getAsOpaquePtr());
   
   methods = CatClassDecl->getClassMethods();
   for (int j = 0; j < CatClassDecl->getNumClassMethods(); j++)
@@ -1684,6 +1683,23 @@
   }
 }
 
+/// MatchTwoMethodDeclarations - Checks that two methods have matching type and
+/// returns true, or false, accordingly.
+/// TODO: Handle protocol list; such as id<p1,p2> in type comparisons
+bool Sema:: MatchTwoMethodDeclarations(const ObjcMethodDecl *Method, 
+                                       const ObjcMethodDecl *PrevMethod) {
+  if (Method->getMethodType().getCanonicalType() !=
+      PrevMethod->getMethodType().getCanonicalType())
+    return false;
+  for (int i = 0; i < Method->getNumParams(); i++) {
+    ParmVarDecl *ParamDecl = Method->getParamDecl(i);
+    ParmVarDecl *PrevParamDecl = PrevMethod->getParamDecl(i);
+    if (ParamDecl->getCanonicalType() != PrevParamDecl->getCanonicalType())
+      return false;
+  }
+  return true;
+}
+
 void Sema::ActOnAddMethodsToObjcDecl(Scope* S, DeclTy *ClassDecl,
                                      DeclTy **allMethods, unsigned allNum) {
   // FIXME: Fix this when we can handle methods declared in protocols.
@@ -1692,15 +1708,56 @@
     return;
   llvm::SmallVector<ObjcMethodDecl*, 32> insMethods;
   llvm::SmallVector<ObjcMethodDecl*, 16> clsMethods;
-
+  
+  llvm::DenseMap<void *, const ObjcMethodDecl*> InsMap;
+  llvm::DenseMap<void *, const ObjcMethodDecl*> ClsMap;
+  
+  bool isClassDeclaration = 
+        (isa<ObjcInterfaceDecl>(static_cast<Decl *>(ClassDecl))
+         || isa<ObjcCategoryDecl>(static_cast<Decl *>(ClassDecl)));
+  
   for (unsigned i = 0; i < allNum; i++ ) {
     ObjcMethodDecl *Method =
       cast_or_null<ObjcMethodDecl>(static_cast<Decl*>(allMethods[i]));
     if (!Method) continue;  // Already issued a diagnostic.
-    if (Method->isInstance())
-      insMethods.push_back(Method);
-    else
-      clsMethods.push_back(Method);
+    if (Method->isInstance()) {
+      if (isClassDeclaration) {
+        /// Check for instance method of the same name with incompatible types
+        const ObjcMethodDecl *&PrevMethod = 
+                InsMap[Method->getSelector().getAsOpaquePtr()];
+        if (PrevMethod && !MatchTwoMethodDeclarations(Method, PrevMethod)) {
+          llvm::SmallString<128> buf;
+          Diag(Method->getLocation(), diag::error_duplicate_method_decl,
+               Method->getSelector().getName(buf));
+          Diag(PrevMethod->getLocation(), diag::err_previous_declaration);
+        }
+        else {
+          insMethods.push_back(Method);
+          InsMap[Method->getSelector().getAsOpaquePtr()] = Method;
+        }
+      }
+      else
+        insMethods.push_back(Method);
+    }
+    else {
+      if (isClassDeclaration) {
+        /// Check for class method of the same name with incompatible types
+        const ObjcMethodDecl *&PrevMethod = 
+                ClsMap[Method->getSelector().getAsOpaquePtr()];
+        if (PrevMethod && !MatchTwoMethodDeclarations(Method, PrevMethod)) {
+          llvm::SmallString<128> buf;
+          Diag(Method->getLocation(), diag::error_duplicate_method_decl,
+               Method->getSelector().getName(buf));
+          Diag(PrevMethod->getLocation(), diag::err_previous_declaration);
+        }
+        else {        
+          clsMethods.push_back(Method);
+          ClsMap[Method->getSelector().getAsOpaquePtr()] = Method;
+        }
+      }
+      else
+        clsMethods.push_back(Method);
+    }
   }
   if (isa<ObjcInterfaceDecl>(static_cast<Decl *>(ClassDecl))) {
     ObjcInterfaceDecl *Interface = cast<ObjcInterfaceDecl>(

Modified: cfe/trunk/clang.xcodeproj/project.pbxproj
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/clang.xcodeproj/project.pbxproj?rev=42641&r1=42640&r2=42641&view=diff

==============================================================================
--- cfe/trunk/clang.xcodeproj/project.pbxproj (original)
+++ cfe/trunk/clang.xcodeproj/project.pbxproj Fri Oct  5 13:00:57 2007
@@ -280,7 +280,7 @@
 		DE67E70C0C020ECA00F66BC5 /* SemaStmt.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = SemaStmt.cpp; path = Sema/SemaStmt.cpp; sourceTree = "<group>"; };
 		DE67E70E0C020ECF00F66BC5 /* SemaExprCXX.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = SemaExprCXX.cpp; path = Sema/SemaExprCXX.cpp; sourceTree = "<group>"; };
 		DE67E7100C020ED400F66BC5 /* SemaExpr.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = SemaExpr.cpp; path = Sema/SemaExpr.cpp; sourceTree = "<group>"; };
-		DE67E7120C020ED900F66BC5 /* SemaDecl.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = SemaDecl.cpp; path = Sema/SemaDecl.cpp; sourceTree = "<group>"; };
+		DE67E7120C020ED900F66BC5 /* SemaDecl.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = SemaDecl.cpp; path = Sema/SemaDecl.cpp; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
 		DE67E7140C020EDF00F66BC5 /* Sema.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = Sema.h; path = Sema/Sema.h; sourceTree = "<group>"; };
 		DE67E7160C020EE400F66BC5 /* Sema.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Sema.cpp; path = Sema/Sema.cpp; sourceTree = "<group>"; };
 		DE67E7190C020F4F00F66BC5 /* ASTStreamer.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ASTStreamer.cpp; path = Sema/ASTStreamer.cpp; sourceTree = "<group>"; };
@@ -306,7 +306,7 @@
 		DEC8D9A30A94346E00353FCA /* AST.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = AST.h; path = clang/AST/AST.h; sourceTree = "<group>"; };
 		DED626C80AE0C065001E80A4 /* TargetInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = TargetInfo.cpp; sourceTree = "<group>"; };
 		DED627020AE0C51D001E80A4 /* Targets.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Targets.cpp; path = Driver/Targets.cpp; sourceTree = "<group>"; };
-		DED62ABA0AE2EDF1001E80A4 /* Decl.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Decl.cpp; path = AST/Decl.cpp; sourceTree = "<group>"; usesTabs = 1; };
+		DED62ABA0AE2EDF1001E80A4 /* Decl.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = Decl.cpp; path = AST/Decl.cpp; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
 		DED676D00B6C786700AAD4A3 /* Builtins.def */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; name = Builtins.def; path = clang/AST/Builtins.def; sourceTree = "<group>"; };
 		DED676F90B6C797B00AAD4A3 /* Builtins.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = Builtins.h; path = clang/AST/Builtins.h; sourceTree = "<group>"; };
 		DED677C80B6C854100AAD4A3 /* Builtins.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Builtins.cpp; path = AST/Builtins.cpp; sourceTree = "<group>"; };

Modified: cfe/trunk/include/clang/AST/DeclObjC.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclObjC.h?rev=42641&r1=42640&r2=42641&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/DeclObjC.h (original)
+++ cfe/trunk/include/clang/AST/DeclObjC.h Fri Oct  5 13:00:57 2007
@@ -242,6 +242,12 @@
     assert(i < getNumMethodParams() && "Illegal param #");
     return ParamInfo[i];
   }
+  
+  int getNumParams() const { return NumMethodParams; }
+  ParmVarDecl *getParamDecl(int i) const {
+    assert(i < getNumParams() && "Illegal param #");
+    return ParamInfo[i];
+  }  
   void setMethodParams(ParmVarDecl **NewParamInfo, unsigned NumParams);
 
   AttributeList *getMethodAttrs() const {return MethodAttrs;}

Modified: cfe/trunk/include/clang/Basic/DiagnosticKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticKinds.def?rev=42641&r1=42640&r2=42641&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticKinds.def Fri Oct  5 13:00:57 2007
@@ -438,6 +438,10 @@
      "incomplete implementation of class '%0'")
 DIAG(warn_incomplete_impl_category, WARNING,
      "incomplete implementation of category '%0'")
+DIAG(error_duplicate_method_decl, ERROR,
+     "duplicate declaration of method '%0'")
+DIAG(err_previous_declaration, ERROR,
+     "previous declaration is here")
 
 
 //===----------------------------------------------------------------------===//

Added: cfe/trunk/test/Sema/check-dup-decl-methods-1.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/check-dup-decl-methods-1.m?rev=42641&view=auto

==============================================================================
--- cfe/trunk/test/Sema/check-dup-decl-methods-1.m (added)
+++ cfe/trunk/test/Sema/check-dup-decl-methods-1.m Fri Oct  5 13:00:57 2007
@@ -0,0 +1,32 @@
+// RUN: clang -fsyntax-only -verify %s
+
+ at interface SUPER
+- (int) meth;
++ (int) foobar;
+ at end
+
+ at interface T @end
+
+ at interface class1 : SUPER
+- (int) meth;	// expected-error {{previous declaration is here}}
+- (int*) meth;	// expected-error {{duplicate declaration of method 'meth'}}
+- (T*) meth1;  
+- (T*) meth1;
++ (T*) meth1;
+ at end
+
+ at interface class1(cat)
+- (int) catm : (char)ch1; // expected-error {{previous declaration is here}}
+- (int) catm1 : (char)ch : (int)i;
+- (int) catm : (char*)ch1; // expected-error {{duplicate declaration of method 'catm:'}}
++ (int) catm1 : (char)ch : (int)i;
++ (T*) meth1;
+ at end
+
+ at interface class1(cat1)
++ (int) catm1 : (char)ch : (int)i; // expected-error {{previous declaration is here}}
++ (T*) meth1; // expected-error {{previous declaration is here}}
++ (int) catm1 : (char)ch : (int*)i; // expected-error {{duplicate declaration of method 'catm1::'}}
++ (T**) meth1; // expected-error {{duplicate declaration of method 'meth1'}}
++ (int) foobar;
+ at end





More information about the cfe-commits mailing list