]> granicus.if.org Git - clang/commitdiff
Change Sema::PropertyIfSetterOrGetter to make use of isPropertyAccessor.
authorJordan Rose <jordan_rose@apple.com>
Wed, 10 Oct 2012 16:42:38 +0000 (16:42 +0000)
committerJordan Rose <jordan_rose@apple.com>
Wed, 10 Oct 2012 16:42:38 +0000 (16:42 +0000)
Old algorithm:
1. See if the name looks like a getter or setter.
2. Use the name to look up a property in the current ObjCContainer
   and all its protocols.
3. If the current container is an interface, also look in all categories
   and superclasses (and superclass categories, and so on).

New algorithm:
1. See if the method is marked as a property accessor. If so, look through
   all properties in the current container and find one that has a matching
   selector.
2. Find all overrides of the method using ObjCMethodDecl's
   getOverriddenMethods. This collects methods in superclasses and protocols
   (as well as superclass categories, which isn't really necessary), and
   checks if THEY are accessors. This part is not done recursively, since
   getOverriddenMethods is already recursive.

This lets us handle getters and setters that do not match the property
names.

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

include/clang/Sema/Sema.h
lib/Sema/SemaObjCProperty.cpp
test/SemaObjC/property-deprecated-warning.m

index 2a6d4bbe880b4ef1caa0b9eb54f03c740a586ad2..6823e45ecbf4680f0951bca3a407f65e56e443ec 100644 (file)
@@ -2317,7 +2317,8 @@ public:
   
   /// PropertyIfSetterOrGetter - Looks up the property if named declaration
   /// is a setter or getter method backing a property.
-  ObjCPropertyDecl *PropertyIfSetterOrGetter(NamedDecl *D);
+  ObjCPropertyDecl *PropertyIfSetterOrGetter(const NamedDecl *D,
+                                             bool CheckOverrides = true);
 
   /// Called by ActOnProperty to handle \@property declarations in
   /// class extensions.
index 8364c07b99c28c89ab2f0f0e449a500bb851d6a4..64dfa5677abe201b64bc4e2c69b5dcb74ea3c13f 100644 (file)
@@ -1576,44 +1576,43 @@ ObjCPropertyDecl *Sema::LookupPropertyDecl(const ObjCContainerDecl *CDecl,
 
 /// PropertyIfSetterOrGetter - Looks up the property if named declaration
 /// is a setter or getter method backing a property.
-ObjCPropertyDecl *Sema::PropertyIfSetterOrGetter(NamedDecl *D) {
-  if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(D)) {
+ObjCPropertyDecl *Sema::PropertyIfSetterOrGetter(const NamedDecl *D,
+                                                 bool CheckOverrides) {
+  const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(D);
+  if (!Method)
+    return 0;
+
+  if (Method->isPropertyAccessor()) {
+    const ObjCContainerDecl *Container =
+      cast<ObjCContainerDecl>(Method->getParent());
+
     Selector Sel = Method->getSelector();
-    IdentifierInfo *Id = 0;
-    if (Sel.getNumArgs() == 0)
-      Id = Sel.getIdentifierInfoForSlot(0);
-    else if (Sel.getNumArgs() == 1) {
-      StringRef str = Sel.getNameForSlot(0);
-      if (str.startswith("set")) {
-        str = str.substr(3);
-        char front = str.front();
-        front = islower(front) ? toupper(front) : tolower(front);
-        SmallString<100> PropertyName = str;
-        PropertyName[0] = front;
-        Id = &PP.getIdentifierTable().get(PropertyName);
-      }
-    }
-    if (Id) {
-      if (isa<ObjCInterfaceDecl>(Method->getDeclContext())) {
-        const ObjCInterfaceDecl *IDecl = Method->getClassInterface();
-        while (IDecl) {
-          ObjCPropertyDecl  *PDecl =
-            LookupPropertyDecl(cast<ObjCContainerDecl>(IDecl), Id);
-          if (PDecl)
-            return PDecl;
-          for (ObjCCategoryDecl *Category = IDecl->getCategoryList();
-             Category; Category = Category->getNextClassCategory())
-            if ((PDecl =
-                 LookupPropertyDecl(cast<ObjCContainerDecl>(Category), Id)))
-              return PDecl;
-          IDecl = IDecl->getSuperClass();
-        }
-      } else if (ObjCPropertyDecl  *PDecl =
-                  LookupPropertyDecl(
-                    cast<ObjCContainerDecl>(Method->getDeclContext()), Id))
-               return PDecl;
+    bool IsGetter = (Sel.isUnarySelector());
+
+    for (ObjCContainerDecl::prop_iterator I = Container->prop_begin(),
+                                          E = Container->prop_end();
+         I != E; ++I) {
+      Selector NextSel = IsGetter ? (*I)->getGetterName()
+                                  : (*I)->getSetterName();
+      if (NextSel == Sel)
+        return *I;
     }
+
+    return 0;
   }
+
+  if (!CheckOverrides)
+    return 0;
+
+  typedef SmallVector<const ObjCMethodDecl *, 8> OverridesTy;
+  OverridesTy Overrides;
+  Method->getOverriddenMethods(Overrides);
+  for (OverridesTy::const_iterator I = Overrides.begin(), E = Overrides.end();
+       I != E; ++I) {
+    if (ObjCPropertyDecl *Prop = PropertyIfSetterOrGetter(*I, false))
+      return Prop;
+  }
+
   return 0;
 }
 
index b3c662074fe3e06fbbb86a0d0534f2f43a82058a..3e6ffe06722039de458baa520094233f33d91a12 100644 (file)
@@ -2,6 +2,8 @@
 // RUN: %clang_cc1 -x objective-c++ -fsyntax-only -triple thumbv6-apple-ios3.0 -verify -Wno-objc-root-class %s
 // rdar://12324295
 
+typedef signed char BOOL;
+
 @protocol P
 @property(nonatomic,assign) id ptarget __attribute__((availability(ios,introduced=2.0,deprecated=3.0))); // expected-note {{property 'ptarget' is declared deprecated here}}
 @end
   [self setPtarget: (id)0]; // expected-warning {{setPtarget:' is deprecated: first deprecated in iOS 3.0}}
 }
 @end
+
+
+@interface CustomAccessorNames
+@property(getter=isEnabled,assign) BOOL enabled __attribute__((availability(ios,introduced=2.0,deprecated=3.0))); // expected-note {{method 'isEnabled' declared here}} expected-note {{property 'enabled' is declared deprecated here}}
+
+@property(setter=setNewDelegate:,assign) id delegate __attribute__((availability(ios,introduced=2.0,deprecated=3.0))); // expected-note {{method 'setNewDelegate:' declared here}} expected-note {{property 'delegate' is declared deprecated here}}
+@end
+
+void testCustomAccessorNames(CustomAccessorNames *obj) {
+  if ([obj isEnabled]) // expected-warning {{'isEnabled' is deprecated: first deprecated in iOS 3.0}}
+    [obj setNewDelegate:0]; // expected-warning {{'setNewDelegate:' is deprecated: first deprecated in iOS 3.0}}
+}