/// 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;
}
// 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}}
+}