[cfe-commits] r42531 - in /cfe/trunk: AST/Decl.cpp Parse/ParseObjc.cpp Sema/Sema.h Sema/SemaDecl.cpp clang.xcodeproj/project.pbxproj include/clang/AST/Decl.h include/clang/AST/DeclObjC.h include/clang/Parse/Action.h test/Sema/method-undef-category-warn-1.m

Fariborz Jahanian fjahanian at apple.com
Tue Oct 2 09:38:50 PDT 2007


Author: fjahanian
Date: Tue Oct  2 11:38:50 2007
New Revision: 42531

URL: http://llvm.org/viewvc/llvm-project?rev=42531&view=rev
Log:
This patch introduces the ObjcCategoryImplDecl class and does the checking related to 
unimplemented methods in category implementation.

Added:
    cfe/trunk/test/Sema/method-undef-category-warn-1.m
Modified:
    cfe/trunk/AST/Decl.cpp
    cfe/trunk/Parse/ParseObjc.cpp
    cfe/trunk/Sema/Sema.h
    cfe/trunk/Sema/SemaDecl.cpp
    cfe/trunk/clang.xcodeproj/project.pbxproj
    cfe/trunk/include/clang/AST/Decl.h
    cfe/trunk/include/clang/AST/DeclObjC.h
    cfe/trunk/include/clang/Parse/Action.h

Modified: cfe/trunk/AST/Decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/AST/Decl.cpp?rev=42531&r1=42530&r2=42531&view=diff

==============================================================================
--- cfe/trunk/AST/Decl.cpp (original)
+++ cfe/trunk/AST/Decl.cpp Tue Oct  2 11:38:50 2007
@@ -34,6 +34,7 @@
 static unsigned nCategoryDecls = 0;
 static unsigned nIvarDecls = 0;
 static unsigned nObjcImplementationDecls = 0;
+static unsigned nObjcCategoryImpl = 0;
 
 static bool StatSwitch = false;
 
@@ -136,6 +137,10 @@
 	  nObjcImplementationDecls, (int)sizeof(ObjcImplementationDecl),
 	  int(nObjcImplementationDecls*sizeof(ObjcImplementationDecl)));
 
+  fprintf(stderr, "    %d class implementation decls, %d each (%d bytes)\n", 
+	  nObjcCategoryImpl, (int)sizeof(ObjcCategoryImplDecl),
+	  int(nObjcCategoryImpl*sizeof(ObjcCategoryImplDecl)));
+
   fprintf(stderr, "Total bytes = %d\n", 
 	  int(nFuncs*sizeof(FunctionDecl)+nBlockVars*sizeof(BlockVarDecl)+
 	      nFileVars*sizeof(FileVarDecl)+nParmVars*sizeof(ParmVarDecl)+
@@ -199,6 +204,9 @@
     case ObjcImplementation: 
       nObjcImplementationDecls++;
       break;
+    case ObjcCategoryImpl:
+      nObjcCategoryImpl++;
+      break;
   }
 }
 
@@ -344,7 +352,7 @@
 }
 
 /// ObjcAddCat - Insert instance and methods declarations into
-/// ObjcProtocolDecl's CatInsMethods and CatClsMethods fields.
+/// ObjcCategoryDecl's CatInsMethods and CatClsMethods fields.
 ///
 void ObjcCategoryDecl::ObjcAddCatMethods(ObjcMethodDecl **insMethods, 
 					 unsigned numInsMembers,
@@ -362,6 +370,25 @@
   }
 }
 
+/// ObjcAddCatImplMethods - Insert instance and methods declarations into
+/// ObjcCategoryImplDecl's CatInsMethods and CatClsMethods fields.
+///
+void ObjcCategoryImplDecl::ObjcAddCatImplMethods(ObjcMethodDecl **insMethods, 
+						 unsigned numInsMembers,
+						 ObjcMethodDecl **clsMethods,
+						 unsigned numClsMembers) {
+  NumCatInsMethods = numInsMembers;
+  if (numInsMembers) {
+    CatInsMethods = new ObjcMethodDecl*[numInsMembers];
+    memcpy(CatInsMethods, insMethods, numInsMembers*sizeof(ObjcMethodDecl*));
+  }
+  NumCatClsMethods = numClsMembers;
+  if (numClsMembers) {
+    CatClsMethods = new ObjcMethodDecl*[numClsMembers];
+    memcpy(CatClsMethods, clsMethods, numClsMembers*sizeof(ObjcMethodDecl*));
+  }
+}
+
 /// ObjcAddImplMethods - Insert instance and methods declarations into
 /// ObjcImplementationDecl's InsMethods and ClsMethods fields.
 ///

Modified: cfe/trunk/Parse/ParseObjc.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Parse/ParseObjc.cpp?rev=42531&r1=42530&r2=42531&view=diff

==============================================================================
--- cfe/trunk/Parse/ParseObjc.cpp (original)
+++ cfe/trunk/Parse/ParseObjc.cpp Tue Oct  2 11:38:50 2007
@@ -934,7 +934,10 @@
       return 0;
     }
     rparenLoc = ConsumeParen();
-    return 0;
+    DeclTy *ImplCatType = Actions.ObjcStartCategoryImplementation(CurScope,
+                                    atLoc, nameId, nameLoc, categoryId, 
+                                    categoryLoc);
+    return ImplCatType;
   }
   // We have a class implementation
   SourceLocation superClassLoc;

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

==============================================================================
--- cfe/trunk/Sema/Sema.h (original)
+++ cfe/trunk/Sema/Sema.h Tue Oct  2 11:38:50 2007
@@ -49,6 +49,8 @@
   class ObjcInterfaceDecl;
   class ObjcProtocolDecl;
   class ObjcImplementationDecl;
+  class ObjcCategoryImplDecl;
+  class ObjcCategoryDecl;
 
 /// Sema - This implements semantic analysis and AST building for C.
 class Sema : public Action {
@@ -219,6 +221,11 @@
   void ImplMethodsVsClassMethods(ObjcImplementationDecl* IMPDecl, 
                                  ObjcInterfaceDecl* IDecl);
   
+  /// ImplCategoryMethodsVsIntfMethods - Checks that methods declared in the
+  /// category interface is implemented in the category @implementation.
+  void ImplCategoryMethodsVsIntfMethods(ObjcCategoryImplDecl *CatImplDecl,
+                                         ObjcCategoryDecl *CatClassDecl);
+  
   //===--------------------------------------------------------------------===//
   // Statement Parsing Callbacks: SemaStmt.cpp.
 public:
@@ -395,6 +402,13 @@
                     IdentifierInfo *SuperClassname, 
                     SourceLocation SuperClassLoc);
   
+  virtual DeclTy *ObjcStartCategoryImplementation(Scope* S,
+                                                  SourceLocation AtCatImplLoc,
+                                                  IdentifierInfo *ClassName, 
+                                                  SourceLocation ClassLoc,
+                                                  IdentifierInfo *CatName,
+                                                  SourceLocation CatLoc);
+  
   virtual DeclTy *ObjcClassDeclaration(Scope *S, SourceLocation AtClassLoc,
                                        IdentifierInfo **IdentList,
                                        unsigned NumElts);

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

==============================================================================
--- cfe/trunk/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/Sema/SemaDecl.cpp Tue Oct  2 11:38:50 2007
@@ -1068,6 +1068,25 @@
   return CDecl;
 }
 
+/// ObjcStartCategoryImplementation - Perform semantic checks on the
+/// category implementation declaration and build an ObjcCategoryImplDecl
+/// object.
+Sema::DeclTy *Sema::ObjcStartCategoryImplementation(Scope* S,
+                      SourceLocation AtCatImplLoc,
+                      IdentifierInfo *ClassName, SourceLocation ClassLoc,
+                      IdentifierInfo *CatName, SourceLocation CatLoc) {
+  ObjcInterfaceDecl *IDecl = getObjCInterfaceDecl(S, ClassName, ClassLoc);
+  ObjcCategoryImplDecl *CDecl = new ObjcCategoryImplDecl(AtCatImplLoc, 
+                                                         ClassName, IDecl,
+                                                         CatName);
+  /// Check that class of this category is already completely declared.
+  if (!IDecl || IDecl->getIsForwardDecl())
+    Diag(ClassLoc, diag::err_undef_interface, ClassName->getName());
+  /// TODO: Check that CatName, category name, is not used in another
+  // implementation.
+  return CDecl;
+}
+
 Sema::DeclTy *Sema::ObjcStartClassImplementation(Scope *S,
                       SourceLocation AtClassImplLoc,
                       IdentifierInfo *ClassName, SourceLocation ClassLoc,
@@ -1255,7 +1274,51 @@
     ObjcProtocolDecl* PDecl = protocols[i];
     CheckProtocolMethodDefs(PDecl, InsMap, ClsMap);
   }
-  return;
+}
+
+/// ImplCategoryMethodsVsIntfMethods - Checks that methods declared in the
+/// category interface is implemented in the category @implementation.
+void Sema::ImplCategoryMethodsVsIntfMethods(ObjcCategoryImplDecl *CatImplDecl,
+                                            ObjcCategoryDecl *CatClassDecl) {
+  llvm::DenseMap<void *, char> InsMap;
+  // Check and see if instance methods in category interface have been
+  // implemented in its implementation class.
+  ObjcMethodDecl **methods = CatImplDecl->getCatInsMethods();
+  for (int i=0; i < CatImplDecl->getNumCatInsMethods(); i++) {
+    InsMap[methods[i]->getSelector().getAsOpaquePtr()] = 'a';
+  }
+  
+  methods = CatClassDecl->getCatInsMethods();
+  for (int j = 0; j < CatClassDecl->getNumCatInsMethods(); j++)
+    if (!InsMap.count(methods[j]->getSelector().getAsOpaquePtr())) {
+      llvm::SmallString<128> buf;
+      Diag(methods[j]->getLocation(), diag::warn_undef_method_impl,
+           methods[j]->getSelector().getName(buf));
+    }
+  llvm::DenseMap<void *, char> ClsMap;
+  // Check and see if class methods in category interface have been
+  // implemented in its implementation class.
+  methods = CatImplDecl->getCatClsMethods();
+  for (int i=0; i < CatImplDecl->getNumCatClsMethods(); i++) {
+    ClsMap[methods[i]->getSelector().getAsOpaquePtr()] = 'a';
+  }
+  
+  methods = CatClassDecl->getCatClsMethods();
+  for (int j = 0; j < CatClassDecl->getNumCatClsMethods(); j++)
+    if (!ClsMap.count(methods[j]->getSelector().getAsOpaquePtr())) {
+      llvm::SmallString<128> buf;
+      Diag(methods[j]->getLocation(), diag::warn_undef_method_impl,
+           methods[j]->getSelector().getName(buf));
+    }
+  
+  // Check the protocol list for unimplemented methods in the @implementation
+  // class.
+  ObjcProtocolDecl** protocols = CatClassDecl->getCatReferencedProtocols();
+  for (int i = 0; i < CatClassDecl->getNumCatReferencedProtocols(); i++) {
+    ObjcProtocolDecl* PDecl = protocols[i];
+    CheckProtocolMethodDefs(PDecl, InsMap, ClsMap);
+  }
+  
 }
 
 /// ObjcClassDeclaration - 
@@ -1647,6 +1710,24 @@
     if (IDecl)
       ImplMethodsVsClassMethods(ImplClass, IDecl);
   }
+  else if (isa<ObjcCategoryImplDecl>(static_cast<Decl *>(ClassDecl))) {
+    ObjcCategoryImplDecl* CatImplClass = cast<ObjcCategoryImplDecl>(
+                                          static_cast<Decl*>(ClassDecl));
+    CatImplClass->ObjcAddCatImplMethods(&insMethods[0], insMethods.size(),
+                                        &clsMethods[0], clsMethods.size());
+    ObjcInterfaceDecl* IDecl = CatImplClass->getClassInterface();
+    // Find category interface decl and then check that all methods declared
+    // in this interface is implemented in the category @implementation.
+    if (IDecl) {
+      for (ObjcCategoryDecl *Categories = IDecl->getListCategories();
+           Categories; Categories = Categories->getNextClassCategory()) {
+        if (Categories->getCatName() == CatImplClass->getObjcCatName()) {
+          ImplCategoryMethodsVsIntfMethods(CatImplClass, Categories);
+          break;
+        }
+      }
+    }
+  }
   else
     assert(0 && "Sema::ObjcAddMethodsToClass(): Unknown DeclTy");
   return;

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

==============================================================================
--- cfe/trunk/clang.xcodeproj/project.pbxproj (original)
+++ cfe/trunk/clang.xcodeproj/project.pbxproj Tue Oct  2 11:38:50 2007
@@ -737,6 +737,7 @@
 		08FB7793FE84155DC02AAC07 /* Project object */ = {
 			isa = PBXProject;
 			buildConfigurationList = 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "clang" */;
+			compatibilityVersion = "Xcode 2.4";
 			hasScannedForEncodings = 1;
 			mainGroup = 08FB7794FE84155DC02AAC07 /* clang */;
 			projectDirPath = "";

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

==============================================================================
--- cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/trunk/include/clang/AST/Decl.h Tue Oct  2 11:38:50 2007
@@ -35,7 +35,7 @@
     Function, BlockVariable, FileVariable, ParmVariable, EnumConstant,
     // Concrete sub-classes of TypeDecl
     Typedef, Struct, Union, Class, Enum, ObjcInterface, ObjcClass, ObjcMethod,
-    ObjcProtocol, ObjcForwardProtocol, ObjcCategory,
+    ObjcProtocol, ObjcForwardProtocol, ObjcCategory, ObjcCategoryImpl,
     ObjcImplementation,
     // Concrete sub-class of Decl
     Field, ObjcIvar

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

==============================================================================
--- cfe/trunk/include/clang/AST/DeclObjC.h (original)
+++ cfe/trunk/include/clang/AST/DeclObjC.h Tue Oct  2 11:38:50 2007
@@ -448,6 +448,17 @@
     CatReferencedProtocols[idx] = OID;
   }
   
+  ObjcProtocolDecl **getCatReferencedProtocols() const { 
+    return CatReferencedProtocols; 
+  }
+  int getNumCatReferencedProtocols() const { return NumCatReferencedProtocols; }
+  
+  ObjcMethodDecl **getCatInsMethods() const { return CatInsMethods; }
+  int getNumCatInsMethods() const { return NumCatInsMethods; }
+  
+  ObjcMethodDecl **getCatClsMethods() const { return CatClsMethods; }
+  int getNumCatClsMethods() const { return NumCatClsMethods; }
+  
   void ObjcAddCatMethods(ObjcMethodDecl **insMethods, unsigned numInsMembers,
                          ObjcMethodDecl **clsMethods, unsigned numClsMembers);
   
@@ -466,6 +477,56 @@
   static bool classof(const ObjcCategoryDecl *D) { return true; }
 };
 
+/// ObjcCategoryImplDecl - An object of this class encapsulates a category 
+/// @implementation declaration.
+class ObjcCategoryImplDecl : public Decl {
+  /// Class interface for this category implementation
+  ObjcInterfaceDecl *ClassInterface;
+
+  /// Category name
+  IdentifierInfo *ObjcCatName;
+      
+  /// category instance methods being implemented
+  ObjcMethodDecl **CatInsMethods; // Null if category is not implementing any
+  int NumCatInsMethods;           // -1 if category is not implementing any
+  
+  /// category class methods being implemented
+  ObjcMethodDecl **CatClsMethods; // Null if category is not implementing any
+  int NumCatClsMethods;  // -1 if category is not implementing any
+  
+  public:
+    ObjcCategoryImplDecl(SourceLocation L, IdentifierInfo *Id,
+                         ObjcInterfaceDecl *classInterface,
+                         IdentifierInfo *catName)
+    : Decl(ObjcCategoryImpl),
+    ClassInterface(classInterface),
+    ObjcCatName(catName),
+    CatInsMethods(0), NumCatInsMethods(-1),
+    CatClsMethods(0), NumCatClsMethods(-1) {}
+        
+    ObjcInterfaceDecl *getClassInterface() const { 
+      return ClassInterface; 
+    }
+  
+  IdentifierInfo *getObjcCatName() const { return ObjcCatName; }
+  
+  ObjcMethodDecl **getCatInsMethods() const { return CatInsMethods; }
+  int getNumCatInsMethods() const { return NumCatInsMethods; }
+  
+  ObjcMethodDecl **getCatClsMethods() const { return CatClsMethods; }
+  int getNumCatClsMethods() const { return NumCatClsMethods; }
+  
+  
+  void ObjcAddCatImplMethods(
+        ObjcMethodDecl **insMethods, unsigned numInsMembers,
+        ObjcMethodDecl **clsMethods, unsigned numClsMembers);
+  
+  static bool classof(const Decl *D) {
+    return D->getKind() == ObjcCategoryImpl;
+  }
+  static bool classof(const ObjcCategoryImplDecl *D) { return true; }
+};
+
 /// ObjcImplementationDecl - Represents a class definition - this is where
 /// method definitions are specified. For example:
 ///

Modified: cfe/trunk/include/clang/Parse/Action.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Action.h?rev=42531&r1=42530&r2=42531&view=diff

==============================================================================
--- cfe/trunk/include/clang/Parse/Action.h (original)
+++ cfe/trunk/include/clang/Parse/Action.h Tue Oct  2 11:38:50 2007
@@ -472,6 +472,14 @@
                     SourceLocation SuperClassLoc) {
     return 0;
   }
+  virtual DeclTy *ObjcStartCategoryImplementation(Scope* S,
+                                                  SourceLocation AtCatImplLoc,
+                                                  IdentifierInfo *ClassName, 
+                                                  SourceLocation ClassLoc,
+                                                  IdentifierInfo *CatName,
+                                                  SourceLocation CatLoc) {
+    return 0;
+  }  
   virtual DeclTy *ObjcBuildMethodDeclaration(SourceLocation MethodLoc, 
     tok::TokenKind MethodType, TypeTy *ReturnType, Selector Sel,
     // optional arguments. The number of types/arguments is obtained

Added: cfe/trunk/test/Sema/method-undef-category-warn-1.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/method-undef-category-warn-1.m?rev=42531&view=auto

==============================================================================
--- cfe/trunk/test/Sema/method-undef-category-warn-1.m (added)
+++ cfe/trunk/test/Sema/method-undef-category-warn-1.m Tue Oct  2 11:38:50 2007
@@ -0,0 +1,26 @@
+ at interface MyClass1 
+ at end
+
+ at protocol P
+- (void) Pmeth;	// expected-warning {{method definition for 'Pmeth' not found}}
+- (void) Pmeth1; // expected-warning {{method definition for 'Pmeth1' not found}}
+ at end
+
+ at interface MyClass1(CAT) <P>
+- (void) meth2;	// expected-warning {{method definition for 'meth2' not found}}
+ at end
+
+ at implementation MyClass1(CAT)
+- (void) Pmeth1{}
+ at end
+
+ at interface MyClass1(DOG) <P>
+- (void)ppp;  // expected-warning {{method definition for 'ppp' not found}}
+ at end
+
+ at implementation MyClass1(DOG)
+- (void) Pmeth {}
+ at end
+
+ at implementation MyClass1(CAT1)
+ at end





More information about the cfe-commits mailing list