]> granicus.if.org Git - clang/commitdiff
ObjectiveC Class Properties: warn if a class property accessor is mistakenly an
authorManman Ren <manman.ren@gmail.com>
Wed, 18 May 2016 18:12:34 +0000 (18:12 +0000)
committerManman Ren <manman.ren@gmail.com>
Wed, 18 May 2016 18:12:34 +0000 (18:12 +0000)
instance method.

When diagnosing unimplemented class property, make sure we emit
a warning when we only see an instance method with the right selector.

Also warn when we only see a class method for an instance property.

rdar://26141719

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@269968 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaObjCProperty.cpp
test/SemaObjC/objc-class-property.m

index 1bf88f4e9393fd3689e1ff55b26bb00878a56465..f9c495d64199301b363e7bdb934972c92f414d09 100644 (file)
@@ -1763,19 +1763,23 @@ void Sema::DefaultSynthesizeProperties(Scope *S, Decl *D) {
       DefaultSynthesizeProperties(S, IC, IDecl);
 }
 
-static void DiagnoseUnimplementedAccessor(Sema &S,
-                                          ObjCInterfaceDecl *PrimaryClass,
-                                          Selector Method,
-                                          ObjCImplDecl* IMPDecl,
-                                          ObjCContainerDecl *CDecl,
-                                          ObjCCategoryDecl *C,
-                                          ObjCPropertyDecl *Prop,
-                                          Sema::SelectorSet &SMap) {
+static void DiagnoseUnimplementedAccessor(
+    Sema &S, ObjCInterfaceDecl *PrimaryClass, Selector Method,
+    ObjCImplDecl *IMPDecl, ObjCContainerDecl *CDecl, ObjCCategoryDecl *C,
+    ObjCPropertyDecl *Prop,
+    llvm::SmallPtrSet<const ObjCMethodDecl *, 8> &SMap) {
+  // Check to see if we have a corresponding selector in SMap and with the
+  // right method type.
+  auto I = std::find_if(SMap.begin(), SMap.end(),
+    [&](const ObjCMethodDecl *x) {
+      return x->getSelector() == Method &&
+             x->isClassMethod() == Prop->isClassProperty();
+    });
   // When reporting on missing property setter/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 (!SMap.count(Method) &&
+  if (I == SMap.end() &&
       (PrimaryClass == nullptr ||
        !PrimaryClass->lookupPropertyAccessor(Method, C,
                                              Prop->isClassProperty()))) {
@@ -1867,10 +1871,10 @@ void Sema::DiagnoseUnimplementedProperties(Scope *S, ObjCImplDecl* IMPDecl,
   for (const auto *I : IMPDecl->property_impls())
     PropImplMap.insert(I->getPropertyDecl());
 
-  SelectorSet InsMap;
+  llvm::SmallPtrSet<const ObjCMethodDecl *, 8> InsMap;
   // Collect property accessors implemented in current implementation.
   for (const auto *I : IMPDecl->methods())
-    InsMap.insert(I->getSelector());
+    InsMap.insert(I);
   
   ObjCCategoryDecl *C = dyn_cast<ObjCCategoryDecl>(CDecl);
   ObjCInterfaceDecl *PrimaryClass = nullptr;
@@ -1882,7 +1886,7 @@ void Sema::DiagnoseUnimplementedProperties(Scope *S, ObjCImplDecl* IMPDecl,
         // setter/getter is implemented in category's primary class
         // implementation.
         for (const auto *I : IMP->methods())
-          InsMap.insert(I->getSelector());
+          InsMap.insert(I);
       }
 
   for (ObjCContainerDecl::PropertyMap::iterator
index 5e1b866cbc897672fe742c58e3cd8fc271c34f0e..f6733574c09cda46efefab6fb1ab95cf2d2fcc30 100644 (file)
@@ -43,3 +43,16 @@ void message_id(id me) {
 void message_class(Class me) {
   [me c2];
 }
+
+@interface NSObject
+@end
+
+@interface MyClass : NSObject
+@property(class, readonly) int classProp; // expected-note {{property declared here}}
+@end
+
+@implementation MyClass // expected-warning {{class property 'classProp' requires method 'classProp' to be defined}}
+- (int)classProp { // Oops, mistakenly made this an instance method.
+  return 8;
+}
+@end