[cfe-commits] r65744 - in /cfe/trunk: include/clang/AST/DeclObjC.h lib/Sema/Sema.h lib/Sema/SemaDeclObjC.cpp test/SemaObjC/method-undef-extension-warn-1.m

Chris Lattner sabre at nondot.org
Sat Feb 28 16:56:52 PST 2009


Author: lattner
Date: Sat Feb 28 18:56:52 2009
New Revision: 65744

URL: http://llvm.org/viewvc/llvm-project?rev=65744&view=rev
Log:
"This patch uses the new ObjCImplDecl class to merge  Sema::ImplMethodsVsClassMethods and Sema::ImplCategoryMethodsVsIntfMethods methods.
And now, when clang check a class implementation to find unimplemented methods, it also checks all methods from the class extensions (unnamed categories).

There is also a test case to check this warning.

This patch contains also a minor update for ObjCImplDecl . getNameAsCString and getNameAsString now returns an empty string instead of crashing for unnamed categories."

Patch by Jean-Daniel Dupas!


Added:
    cfe/trunk/test/SemaObjC/method-undef-extension-warn-1.m
Modified:
    cfe/trunk/include/clang/AST/DeclObjC.h
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaDeclObjC.cpp

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

==============================================================================
--- cfe/trunk/include/clang/AST/DeclObjC.h (original)
+++ cfe/trunk/include/clang/AST/DeclObjC.h Sat Feb 28 18:56:52 2009
@@ -757,13 +757,16 @@
   llvm::SmallVector<ObjCPropertyImplDecl*, 8> PropertyImplementations;
   
   SourceLocation EndLoc;  
+  
 protected:
   ObjCImplDecl(Kind DK, DeclContext *DC, SourceLocation L,
                ObjCInterfaceDecl *classInterface)
-  : Decl(DK, DC, L), DeclContext(DK),
-  ClassInterface(classInterface) {}
+      : Decl(DK, DC, L), DeclContext(DK),
+        ClassInterface(classInterface) {}
   
 public:
+  virtual ~ObjCImplDecl() {}
+  
   const ObjCInterfaceDecl *getClassInterface() const { return ClassInterface; }
   ObjCInterfaceDecl *getClassInterface() { return ClassInterface; }
   
@@ -849,12 +852,12 @@
   /// interface associated with this implementation as a C string
   /// (const char*).
   const char *getNameAsCString() const {
-    return Id->getName();
+    return Id ? Id->getName() : "";
   }
   
   /// @brief Get the name of the class associated with this interface.
   std::string getNameAsString() const {
-    return Id->getName();
+    return Id ? Id->getName() : "";
   }
   
   static bool classof(const Decl *D) { return D->getKind() == ObjCCategoryImpl;}

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

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Sat Feb 28 18:56:52 2009
@@ -68,6 +68,7 @@
   class ObjCInterfaceDecl;
   class ObjCCompatibleAliasDecl;
   class ObjCProtocolDecl;
+  class ObjCImplDecl;
   class ObjCImplementationDecl;
   class ObjCCategoryImplDecl;
   class ObjCCategoryDecl;
@@ -930,14 +931,11 @@
                                 SourceLocation Loc);
   
   /// ImplMethodsVsClassMethods - This is main routine to warn if any method
-  /// remains unimplemented in the @implementation class.
-  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);
+  /// remains unimplemented in the class or category @implementation.
+  void ImplMethodsVsClassMethods(ObjCImplDecl* IMPDecl, 
+                                 ObjCContainerDecl* IDecl, 
+                                 bool IncompleteImpl = false);
+  
   /// MatchTwoMethodDeclarations - Checks if two methods' type match and returns
   /// true, or false, accordingly.
   bool MatchTwoMethodDeclarations(const ObjCMethodDecl *Method, 

Modified: cfe/trunk/lib/Sema/SemaDeclObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclObjC.cpp?rev=65744&r1=65743&r2=65744&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclObjC.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclObjC.cpp Sat Feb 28 18:56:52 2009
@@ -814,8 +814,9 @@
     CheckProtocolMethodDefs(ImpLoc, *PI, IncompleteImpl, InsMap, ClsMap, IDecl);
 }
 
-void Sema::ImplMethodsVsClassMethods(ObjCImplementationDecl* IMPDecl, 
-                                     ObjCInterfaceDecl* IDecl) {
+void Sema::ImplMethodsVsClassMethods(ObjCImplDecl* IMPDecl, 
+                                     ObjCContainerDecl* CDecl, 
+                                     bool IncompleteImpl) {
   llvm::DenseSet<Selector> InsMap;
   // Check and see if instance methods in class interface have been
   // implemented in the implementation class.
@@ -823,9 +824,8 @@
        E = IMPDecl->instmeth_end(); I != E; ++I)
     InsMap.insert((*I)->getSelector());
   
-  bool IncompleteImpl = false;
-  for (ObjCInterfaceDecl::instmeth_iterator I = IDecl->instmeth_begin(),
-       E = IDecl->instmeth_end(); I != E; ++I) {
+  for (ObjCInterfaceDecl::instmeth_iterator I = CDecl->instmeth_begin(),
+       E = CDecl->instmeth_end(); I != E; ++I) {
     if (!(*I)->isSynthesized() && !InsMap.count((*I)->getSelector())) {
       WarnUndefinedMethod(IMPDecl->getLocation(), *I, IncompleteImpl);
       continue;
@@ -834,7 +834,7 @@
     ObjCMethodDecl *ImpMethodDecl = 
       IMPDecl->getInstanceMethod((*I)->getSelector());
     ObjCMethodDecl *IntfMethodDecl = 
-      IDecl->getInstanceMethod((*I)->getSelector());
+      CDecl->getInstanceMethod((*I)->getSelector());
     assert(IntfMethodDecl && 
            "IntfMethodDecl is null in ImplMethodsVsClassMethods");
     // ImpMethodDecl may be null as in a @dynamic property.
@@ -849,82 +849,41 @@
        E = IMPDecl->classmeth_end(); I != E; ++I)
     ClsMap.insert((*I)->getSelector());
   
-  for (ObjCInterfaceDecl::classmeth_iterator I = IDecl->classmeth_begin(),
-       E = IDecl->classmeth_end(); I != E; ++I)
+  for (ObjCInterfaceDecl::classmeth_iterator I = CDecl->classmeth_begin(),
+       E = CDecl->classmeth_end(); I != E; ++I)
     if (!ClsMap.count((*I)->getSelector()))
       WarnUndefinedMethod(IMPDecl->getLocation(), *I, IncompleteImpl);
     else {
       ObjCMethodDecl *ImpMethodDecl = 
         IMPDecl->getClassMethod((*I)->getSelector());
       ObjCMethodDecl *IntfMethodDecl = 
-        IDecl->getClassMethod((*I)->getSelector());
+        CDecl->getClassMethod((*I)->getSelector());
       WarnConflictingTypedMethods(ImpMethodDecl, IntfMethodDecl);
     }
   
   
   // Check the protocol list for unimplemented methods in the @implementation
   // class.
-  const ObjCList<ObjCProtocolDecl> &Protocols =
-    IDecl->getReferencedProtocols();
-  for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
-       E = Protocols.end(); I != E; ++I)
-    CheckProtocolMethodDefs(IMPDecl->getLocation(), *I, 
-                            IncompleteImpl, InsMap, ClsMap, IDecl);
-}
-
-/// ImplCategoryMethodsVsIntfMethods - Checks that methods declared in the
-/// category interface are implemented in the category @implementation.
-void Sema::ImplCategoryMethodsVsIntfMethods(ObjCCategoryImplDecl *CatImplDecl,
-                                            ObjCCategoryDecl *CatClassDecl) {
-  llvm::DenseSet<Selector> InsMap;
-  // Check and see if instance methods in category interface have been
-  // implemented in its implementation class.
-  for (ObjCCategoryImplDecl::instmeth_iterator I =CatImplDecl->instmeth_begin(),
-       E = CatImplDecl->instmeth_end(); I != E; ++I)
-    InsMap.insert((*I)->getSelector());
-  
-  bool IncompleteImpl = false;
-  for (ObjCCategoryDecl::instmeth_iterator I = CatClassDecl->instmeth_begin(),
-       E = CatClassDecl->instmeth_end(); I != E; ++I)
-    if (!(*I)->isSynthesized() && !InsMap.count((*I)->getSelector()))
-      WarnUndefinedMethod(CatImplDecl->getLocation(), *I, IncompleteImpl);
-    else {
-      ObjCMethodDecl *ImpMethodDecl = 
-        CatImplDecl->getInstanceMethod((*I)->getSelector());
-      ObjCMethodDecl *IntfMethodDecl = 
-        CatClassDecl->getInstanceMethod((*I)->getSelector());
-      assert(IntfMethodDecl && 
-             "IntfMethodDecl is null in ImplCategoryMethodsVsIntfMethods");
-      // ImpMethodDecl may be null as in a @dynamic property.
-      if (ImpMethodDecl)        
-        WarnConflictingTypedMethods(ImpMethodDecl, IntfMethodDecl);
-    }
-
-  llvm::DenseSet<Selector> ClsMap;
-  // Check and see if class methods in category interface have been
-  // implemented in its implementation class.
-  for (ObjCCategoryImplDecl::classmeth_iterator
-       I = CatImplDecl->classmeth_begin(), E = CatImplDecl->classmeth_end();
-       I != E; ++I)
-    ClsMap.insert((*I)->getSelector());
-  
-  for (ObjCCategoryDecl::classmeth_iterator I = CatClassDecl->classmeth_begin(),
-       E = CatClassDecl->classmeth_end(); I != E; ++I)
-    if (!ClsMap.count((*I)->getSelector()))
-      WarnUndefinedMethod(CatImplDecl->getLocation(), *I, IncompleteImpl);
-    else {
-      ObjCMethodDecl *ImpMethodDecl = 
-        CatImplDecl->getClassMethod((*I)->getSelector());
-      ObjCMethodDecl *IntfMethodDecl = 
-        CatClassDecl->getClassMethod((*I)->getSelector());
-      WarnConflictingTypedMethods(ImpMethodDecl, IntfMethodDecl);
+  if (ObjCInterfaceDecl *I = dyn_cast<ObjCInterfaceDecl> (CDecl)) {
+    for (ObjCCategoryDecl::protocol_iterator PI = I->protocol_begin(),
+         E = I->protocol_end(); PI != E; ++PI)
+      CheckProtocolMethodDefs(IMPDecl->getLocation(), *PI, IncompleteImpl, 
+                              InsMap, ClsMap, I);
+    // Check class extensions (unnamed categories)
+    for (ObjCCategoryDecl *Categories = I->getCategoryList();
+         Categories; Categories = Categories->getNextClassCategory()) {
+      if (!Categories->getIdentifier()) {
+        ImplMethodsVsClassMethods(IMPDecl, Categories, IncompleteImpl);
+        break;
+      }
     }
-  // Check the protocol list for unimplemented methods in the @implementation
-  // class.
-  for (ObjCCategoryDecl::protocol_iterator PI = CatClassDecl->protocol_begin(),
-       E = CatClassDecl->protocol_end(); PI != E; ++PI)
-    CheckProtocolMethodDefs(CatImplDecl->getLocation(), *PI, IncompleteImpl, 
-                            InsMap, ClsMap, CatClassDecl->getClassInterface());
+  } else if (ObjCCategoryDecl *C = dyn_cast<ObjCCategoryDecl>(CDecl)) {
+    for (ObjCCategoryDecl::protocol_iterator PI = C->protocol_begin(),
+         E = C->protocol_end(); PI != E; ++PI)
+      CheckProtocolMethodDefs(IMPDecl->getLocation(), *PI, IncompleteImpl, 
+                              InsMap, ClsMap, C->getClassInterface());
+  } else
+    assert(false && "invalid ObjCContainerDecl type.");
 }
 
 /// ActOnForwardClassDeclaration - 
@@ -1302,7 +1261,7 @@
       for (ObjCCategoryDecl *Categories = IDecl->getCategoryList();
            Categories; Categories = Categories->getNextClassCategory()) {
         if (Categories->getIdentifier() == CatImplClass->getIdentifier()) {
-          ImplCategoryMethodsVsIntfMethods(CatImplClass, Categories);
+          ImplMethodsVsClassMethods(CatImplClass, Categories);
           break;
         }
       }

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

==============================================================================
--- cfe/trunk/test/SemaObjC/method-undef-extension-warn-1.m (added)
+++ cfe/trunk/test/SemaObjC/method-undef-extension-warn-1.m Sat Feb 28 18:56:52 2009
@@ -0,0 +1,25 @@
+// RUN: clang -fsyntax-only -verify %s
+
+ at interface MyClass
+ at end
+
+ at protocol P
+- (void)Pmeth;
+- (void)Pmeth1;
+ at end
+
+// Class extension
+ at interface MyClass () <P>
+- (void)meth2;
+ at end
+
+// Add a category to test that clang does not emit warning for this method.
+ at interface MyClass (Category) 
+- (void)categoryMethod;
+ at end
+
+ at implementation MyClass // expected-warning {{incomplete implementation}} \
+                           expected-warning {{method definition for 'meth2' not found}} \
+                           expected-warning {{method definition for 'Pmeth1' not found}}
+- (void)Pmeth {}
+ at end





More information about the cfe-commits mailing list