r180198 - Objective-C: When reporting on missing property accessor implementation in

Fariborz Jahanian fjahanian at apple.com
Wed Apr 24 10:06:38 PDT 2013


Author: fjahanian
Date: Wed Apr 24 12:06:38 2013
New Revision: 180198

URL: http://llvm.org/viewvc/llvm-project?rev=180198&view=rev
Log:
Objective-C: When reporting on missing property accessor implementation in
categories, do not report when they are declared in primary class,
class's protocol, or one of it super classes. This is because,
its class is going to implement them. // rdar://13713098

Modified:
    cfe/trunk/include/clang/AST/DeclObjC.h
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/AST/DeclObjC.cpp
    cfe/trunk/lib/Sema/SemaDeclObjC.cpp
    cfe/trunk/lib/Sema/SemaObjCProperty.cpp
    cfe/trunk/test/SemaObjC/property-category-4.m
    cfe/trunk/test/SemaObjC/property.m

Modified: cfe/trunk/include/clang/AST/DeclObjC.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclObjC.h?rev=180198&r1=180197&r2=180198&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclObjC.h (original)
+++ cfe/trunk/include/clang/AST/DeclObjC.h Wed Apr 24 12:06:38 2013
@@ -1136,7 +1136,8 @@ public:
   // Lookup a method. First, we search locally. If a method isn't
   // found, we search referenced protocols and class categories.
   ObjCMethodDecl *lookupMethod(Selector Sel, bool isInstance,
-                               bool shallowCategoryLookup= false) const;
+                               bool shallowCategoryLookup= false,
+                               bool CategoryLookup= true) const;
   ObjCMethodDecl *lookupInstanceMethod(Selector Sel,
                             bool shallowCategoryLookup = false) const {
     return lookupMethod(Sel, true/*isInstance*/, shallowCategoryLookup);
@@ -1155,6 +1156,15 @@ public:
     return lookupPrivateMethod(Sel, false);
   }
 
+  /// \brief Lookup a setter or getter in the class hierarchy.
+  /// In this lookup, only class hierarchy and not its categories
+  /// are looked up
+  ObjCMethodDecl *lookupPropertyAccessor(const Selector Sel) const {
+     return lookupMethod(Sel, true/*isInstance*/,
+                         false /*shallowCategoryLookup*/,
+                         false /*CategoryLookup*/);
+  }
+
   SourceLocation getEndOfDefinitionLoc() const { 
     if (!hasDefinition())
       return getLocation();

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=180198&r1=180197&r2=180198&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Wed Apr 24 12:06:38 2013
@@ -2475,8 +2475,7 @@ public:
   /// DiagnoseUnimplementedProperties - This routine warns on those properties
   /// which must be implemented by this implementation.
   void DiagnoseUnimplementedProperties(Scope *S, ObjCImplDecl* IMPDecl,
-                                       ObjCContainerDecl *CDecl,
-                                       const SelectorSet &InsMap);
+                                       ObjCContainerDecl *CDecl);
 
   /// DefaultSynthesizeProperties - This routine default synthesizes all
   /// properties which must be synthesized in the class's \@implementation.

Modified: cfe/trunk/lib/AST/DeclObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclObjC.cpp?rev=180198&r1=180197&r2=180198&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclObjC.cpp (original)
+++ cfe/trunk/lib/AST/DeclObjC.cpp Wed Apr 24 12:06:38 2013
@@ -445,7 +445,8 @@ ObjCInterfaceDecl *ObjCInterfaceDecl::lo
 /// the class, its categories, and its super classes (using a linear search).
 ObjCMethodDecl *ObjCInterfaceDecl::lookupMethod(Selector Sel, 
                                      bool isInstance,
-                                     bool shallowCategoryLookup) const {
+                                     bool shallowCategoryLookup,
+                                     bool CategoryLookup) const {
   // FIXME: Should make sure no callers ever do this.
   if (!hasDefinition())
     return 0;
@@ -468,23 +469,24 @@ ObjCMethodDecl *ObjCInterfaceDecl::looku
         return MethodDecl;
     
     // Didn't find one yet - now look through categories.
-    for (ObjCInterfaceDecl::visible_categories_iterator
+    if (CategoryLookup)
+      for (ObjCInterfaceDecl::visible_categories_iterator
            Cat = ClassDecl->visible_categories_begin(),
            CatEnd = ClassDecl->visible_categories_end();
-         Cat != CatEnd; ++Cat) {
-      if ((MethodDecl = Cat->getMethod(Sel, isInstance)))
-        return MethodDecl;
+           Cat != CatEnd; ++Cat) {
+        if ((MethodDecl = Cat->getMethod(Sel, isInstance)))
+          return MethodDecl;
 
-      if (!shallowCategoryLookup) {
-        // Didn't find one yet - look through protocols.
-        const ObjCList<ObjCProtocolDecl> &Protocols =
-          Cat->getReferencedProtocols();
-        for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
-             E = Protocols.end(); I != E; ++I)
-          if ((MethodDecl = (*I)->lookupMethod(Sel, isInstance)))
-            return MethodDecl;
+        if (!shallowCategoryLookup) {
+          // Didn't find one yet - look through protocols.
+          const ObjCList<ObjCProtocolDecl> &Protocols =
+            Cat->getReferencedProtocols();
+          for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
+               E = Protocols.end(); I != E; ++I)
+            if ((MethodDecl = (*I)->lookupMethod(Sel, isInstance)))
+              return MethodDecl;
+        }
       }
-    }
   
     ClassDecl = ClassDecl->getSuperClass();
   }

Modified: cfe/trunk/lib/Sema/SemaDeclObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclObjC.cpp?rev=180198&r1=180197&r2=180198&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclObjC.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclObjC.cpp Wed Apr 24 12:06:38 2013
@@ -1836,7 +1836,7 @@ void Sema::ImplMethodsVsClassMethods(Sco
     if  (!(LangOpts.ObjCDefaultSynthProperties &&
            LangOpts.ObjCRuntime.isNonFragile()) ||
          IDecl->isObjCRequiresPropertyDefs())
-      DiagnoseUnimplementedProperties(S, IMPDecl, CDecl, InsMap);
+      DiagnoseUnimplementedProperties(S, IMPDecl, CDecl);
       
   SelectorSet ClsMap;
   for (ObjCImplementationDecl::classmeth_iterator
@@ -1883,17 +1883,7 @@ void Sema::ImplMethodsVsClassMethods(Sco
            E = C->protocol_end(); PI != E; ++PI)
         CheckProtocolMethodDefs(IMPDecl->getLocation(), *PI, IncompleteImpl,
                                 InsMap, ClsMap, CDecl);
-      // Report unimplemented properties in the category as well.
-      // When reporting on missing setter/getters, do not report when
-      // setter/getter is implemented in category's primary class 
-      // implementation.
-      if (ObjCInterfaceDecl *ID = C->getClassInterface())
-        if (ObjCImplDecl *IMP = ID->getImplementation()) {
-          for (ObjCImplementationDecl::instmeth_iterator
-               I = IMP->instmeth_begin(), E = IMP->instmeth_end(); I!=E; ++I)
-            InsMap.insert((*I)->getSelector());
-        }
-      DiagnoseUnimplementedProperties(S, IMPDecl, CDecl, InsMap);      
+      DiagnoseUnimplementedProperties(S, IMPDecl, CDecl);
     } 
   } else
     llvm_unreachable("invalid ObjCContainerDecl type.");

Modified: cfe/trunk/lib/Sema/SemaObjCProperty.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaObjCProperty.cpp?rev=180198&r1=180197&r2=180198&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaObjCProperty.cpp (original)
+++ cfe/trunk/lib/Sema/SemaObjCProperty.cpp Wed Apr 24 12:06:38 2013
@@ -1660,8 +1660,7 @@ void Sema::DefaultSynthesizeProperties(S
 }
 
 void Sema::DiagnoseUnimplementedProperties(Scope *S, ObjCImplDecl* IMPDecl,
-                                      ObjCContainerDecl *CDecl,
-                                      const SelectorSet &InsMap) {
+                                      ObjCContainerDecl *CDecl) {
   ObjCContainerDecl::PropertyMap NoNeedToImplPropMap;
   ObjCInterfaceDecl *IDecl;
   // Gather properties which need not be implemented in this class
@@ -1690,6 +1689,26 @@ void Sema::DiagnoseUnimplementedProperti
        EI = IMPDecl->propimpl_end(); I != EI; ++I)
     PropImplMap.insert(I->getPropertyDecl());
 
+  SelectorSet InsMap;
+  // Collect property accessors implemented in current implementation.
+  for (ObjCImplementationDecl::instmeth_iterator
+       I = IMPDecl->instmeth_begin(), E = IMPDecl->instmeth_end(); I!=E; ++I)
+    InsMap.insert((*I)->getSelector());
+  
+  ObjCCategoryDecl *C = dyn_cast<ObjCCategoryDecl>(CDecl);
+  ObjCInterfaceDecl *PrimaryClass = 0;
+  if (C && !C->IsClassExtension())
+    if ((PrimaryClass = C->getClassInterface()))
+      // Report unimplemented properties in the category as well.
+      if (ObjCImplDecl *IMP = PrimaryClass->getImplementation()) {
+        // When reporting on missing setter/getters, do not report when
+        // setter/getter is implemented in category's primary class
+        // implementation.
+        for (ObjCImplementationDecl::instmeth_iterator
+             I = IMP->instmeth_begin(), E = IMP->instmeth_end(); I!=E; ++I)
+          InsMap.insert((*I)->getSelector());
+      }
+
   for (ObjCContainerDecl::PropertyMap::iterator
        P = PropMap.begin(), E = PropMap.end(); P != E; ++P) {
     ObjCPropertyDecl *Prop = P->second;
@@ -1699,7 +1718,13 @@ void Sema::DiagnoseUnimplementedProperti
         PropImplMap.count(Prop) ||
         Prop->getAvailability() == AR_Unavailable)
       continue;
-    if (!InsMap.count(Prop->getGetterName())) {
+    // When reporting on missing property getter implementation in
+    // categories, do not report when they are declared in primary class,
+    // class's protocol, or one of it super classes. This is because,
+    // the class is going to implement them.
+    if (!InsMap.count(Prop->getGetterName()) &&
+        (PrimaryClass == 0 ||
+         !PrimaryClass->lookupPropertyAccessor(Prop->getGetterName()))) {
       Diag(IMPDecl->getLocation(),
            isa<ObjCCategoryDecl>(CDecl) ?
             diag::warn_setter_getter_impl_required_in_category :
@@ -1713,8 +1738,13 @@ void Sema::DiagnoseUnimplementedProperti
             Diag(RID->getLocation(), diag::note_suppressed_class_declare);
             
     }
-
-    if (!Prop->isReadOnly() && !InsMap.count(Prop->getSetterName())) {
+    // When reporting on missing property setter implementation in
+    // categories, do not report when they are declared in primary class,
+    // class's protocol, or one of it super classes. This is because,
+    // the class is going to implement them.
+    if (!Prop->isReadOnly() && !InsMap.count(Prop->getSetterName()) &&
+        (PrimaryClass == 0 ||
+         !PrimaryClass->lookupPropertyAccessor(Prop->getSetterName()))) {
       Diag(IMPDecl->getLocation(),
            isa<ObjCCategoryDecl>(CDecl) ?
            diag::warn_setter_getter_impl_required_in_category :

Modified: cfe/trunk/test/SemaObjC/property-category-4.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/property-category-4.m?rev=180198&r1=180197&r2=180198&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/property-category-4.m (original)
+++ cfe/trunk/test/SemaObjC/property-category-4.m Wed Apr 24 12:06:38 2013
@@ -16,3 +16,72 @@
 @dynamic d_selectedObjects; // expected-error {{property declared in category 'CAT' cannot be implemented in class implementation}}
 @end
 
+
+// rdar://13713098
+// Test1
+ at interface NSArray 
+- (int)count;
+ at end
+
+ at protocol MyCountable
+ at property  (readonly) int count;
+ at end
+
+
+ at interface NSArray(Additions) <MyCountable>
+ at end
+
+ at implementation NSArray(Additions)
+ at end
+
+// Test2
+ at protocol NSProtocol
+- (int)count;
+ at end
+
+ at interface NSArray1 <NSProtocol>
+ at end
+
+ at interface NSArray1(Additions) <MyCountable>
+ at end
+
+ at implementation NSArray1(Additions)
+ at end
+
+// Test3
+ at interface Super <NSProtocol>
+ at end
+
+ at interface NSArray2 : Super @end
+
+ at interface NSArray2(Additions) <MyCountable>
+ at end
+
+ at implementation NSArray2(Additions)
+ at end
+
+// Test3
+ at interface Super1 <NSProtocol>
+ at property  (readonly) int count;
+ at end
+
+ at protocol MyCountable1
+ at end
+
+ at interface NSArray3 : Super1 <MyCountable1>
+ at end
+
+ at implementation NSArray3
+ at end
+
+// Test4
+ at interface I
+ at property int d1;
+ at end
+
+ at interface I(CAT)
+ at property int d1;
+ at end
+
+ at implementation I(CAT)
+ at end

Modified: cfe/trunk/test/SemaObjC/property.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/property.m?rev=180198&r1=180197&r2=180198&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/property.m (original)
+++ cfe/trunk/test/SemaObjC/property.m Wed Apr 24 12:06:38 2013
@@ -11,7 +11,7 @@
 @end
 
 @interface I(CAT)
- at property int d1;	// expected-note 2 {{property declared here}}
+ at property int d1;
 @end
 
 @implementation I
@@ -22,8 +22,7 @@
 @synthesize name;	// OK! property with same name as an accessible ivar of same name
 @end
 
- at implementation I(CAT)  // expected-warning {{property 'd1' requires method 'd1' to be defined }} \
-                        // expected-warning {{property 'd1' requires method 'setD1:' to be defined }}
+ at implementation I(CAT) 
 @synthesize d1;		// expected-error {{@synthesize not allowed in a category's implementation}}
 @dynamic bad;		// expected-error {{property implementation must have its declaration in the category 'CAT'}}
 @end





More information about the cfe-commits mailing list