Move Sema::PropertyIfSetterOrGetter to ObjCMethodDecl::findPropertyDecl.

Then, switch users of PropertyIfSetterOrGetter and LookupPropertyDecl
(the latter by name) over to findPropertyDecl. This actually makes
-Wreceiver-is-weak a bit stronger than it was before.

llvm-svn: 165628
This commit is contained in:
Jordan Rose 2012-10-10 16:42:54 +00:00
parent 79af985bad
commit 2bd991a1c0
8 changed files with 97 additions and 120 deletions

View File

@ -427,7 +427,14 @@ public:
/// method in the interface or its categories.
void getOverriddenMethods(
SmallVectorImpl<const ObjCMethodDecl *> &Overridden) const;
/// \brief Returns the property associated with this method's selector.
///
/// Note that even if this particular method is not marked as a property
/// accessor, it is still possible for it to match a property declared in a
/// superclass. Pass \c false if you only want to check the current class.
const ObjCPropertyDecl *findPropertyDecl(bool CheckOverrides = true) const;
// Related to protocols declared in \@protocol
void setDeclImplementation(ImplementationControl ic) {
DeclImplementation = ic;

View File

@ -2308,18 +2308,7 @@ public:
void CollectImmediateProperties(ObjCContainerDecl *CDecl,
llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>& PropMap,
llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>& SuperPropMap);
/// LookupPropertyDecl - Looks up a property in the current class and all
/// its protocols.
ObjCPropertyDecl *LookupPropertyDecl(const ObjCContainerDecl *CDecl,
IdentifierInfo *II);
/// PropertyIfSetterOrGetter - Looks up the property if named declaration
/// is a setter or getter method backing a property.
ObjCPropertyDecl *PropertyIfSetterOrGetter(const NamedDecl *D,
bool CheckOverrides = true);
/// Called by ActOnProperty to handle \@property declarations in
/// class extensions.
Decl *HandlePropertyInClassExtension(Scope *S,

View File

@ -895,6 +895,48 @@ void ObjCMethodDecl::getOverriddenMethods(
}
}
const ObjCPropertyDecl *
ObjCMethodDecl::findPropertyDecl(bool CheckOverrides) const {
Selector Sel = getSelector();
unsigned NumArgs = Sel.getNumArgs();
if (NumArgs > 1)
return 0;
if (getMethodFamily() != OMF_None)
return 0;
if (isPropertyAccessor()) {
const ObjCContainerDecl *Container = cast<ObjCContainerDecl>(getParent());
bool IsGetter = (NumArgs == 0);
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;
}
llvm_unreachable("Marked as a property accessor but no property found!");
}
if (!CheckOverrides)
return 0;
typedef SmallVector<const ObjCMethodDecl *, 8> OverridesTy;
OverridesTy Overrides;
getOverriddenMethods(Overrides);
for (OverridesTy::const_iterator I = Overrides.begin(), E = Overrides.end();
I != E; ++I) {
if (const ObjCPropertyDecl *Prop = (*I)->findPropertyDecl(false))
return Prop;
}
return 0;
}
//===----------------------------------------------------------------------===//
// ObjCInterfaceDecl
//===----------------------------------------------------------------------===//

View File

@ -87,13 +87,17 @@ static AvailabilityResult DiagnoseAvailabilityOfDecl(Sema &S,
if (const EnumDecl *TheEnumDecl = dyn_cast<EnumDecl>(DC))
Result = TheEnumDecl->getAvailability(&Message);
}
const ObjCPropertyDecl *ObjCPDecl = 0;
if (Result == AR_Deprecated || Result == AR_Unavailable)
if (ObjCPropertyDecl *ND = S.PropertyIfSetterOrGetter(D)) {
AvailabilityResult PDeclResult = ND->getAvailability(0);
if (PDeclResult == Result)
ObjCPDecl = ND;
if (Result == AR_Deprecated || Result == AR_Unavailable) {
if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
if (const ObjCPropertyDecl *PD = MD->findPropertyDecl()) {
AvailabilityResult PDeclResult = PD->getAvailability(0);
if (PDeclResult == Result)
ObjCPDecl = PD;
}
}
}
switch (Result) {
case AR_Available:

View File

@ -1305,8 +1305,8 @@ static void DiagnoseARCUseOfWeakReceiver(Sema &S, Expr *Receiver) {
Expr *RExpr = Receiver->IgnoreParenImpCasts();
SourceLocation Loc = RExpr->getLocStart();
QualType T = RExpr->getType();
ObjCPropertyDecl *PDecl = 0;
ObjCMethodDecl *GDecl = 0;
const ObjCPropertyDecl *PDecl = 0;
const ObjCMethodDecl *GDecl = 0;
if (PseudoObjectExpr *POE = dyn_cast<PseudoObjectExpr>(RExpr)) {
RExpr = POE->getSyntacticForm();
if (ObjCPropertyRefExpr *PRE = dyn_cast<ObjCPropertyRefExpr>(RExpr)) {
@ -1328,14 +1328,8 @@ static void DiagnoseARCUseOfWeakReceiver(Sema &S, Expr *Receiver) {
// See if receiver is a method which envokes a synthesized getter
// backing a 'weak' property.
ObjCMethodDecl *Method = ME->getMethodDecl();
if (Method && Method->isPropertyAccessor()) {
Selector Sel = Method->getSelector();
if (Sel.getNumArgs() == 0) {
const DeclContext *Container = Method->getDeclContext();
PDecl =
S.LookupPropertyDecl(cast<ObjCContainerDecl>(Container),
Sel.getIdentifierInfoForSlot(0));
}
if (Method && Method->getSelector().getNumArgs() == 0) {
PDecl = Method->findPropertyDecl();
if (PDecl)
T = PDecl->getType();
}

View File

@ -1525,97 +1525,6 @@ static void CollectSuperClassPropertyImplementations(ObjCInterfaceDecl *CDecl,
}
}
/// LookupPropertyDecl - Looks up a property in the current class and all
/// its protocols.
ObjCPropertyDecl *Sema::LookupPropertyDecl(const ObjCContainerDecl *CDecl,
IdentifierInfo *II) {
if (const ObjCInterfaceDecl *IDecl =
dyn_cast<ObjCInterfaceDecl>(CDecl)) {
for (ObjCContainerDecl::prop_iterator P = IDecl->prop_begin(),
E = IDecl->prop_end(); P != E; ++P) {
ObjCPropertyDecl *Prop = *P;
if (Prop->getIdentifier() == II)
return Prop;
}
// scan through class's protocols.
for (ObjCInterfaceDecl::all_protocol_iterator
PI = IDecl->all_referenced_protocol_begin(),
E = IDecl->all_referenced_protocol_end(); PI != E; ++PI) {
ObjCPropertyDecl *Prop = LookupPropertyDecl((*PI), II);
if (Prop)
return Prop;
}
}
else if (const ObjCProtocolDecl *PDecl =
dyn_cast<ObjCProtocolDecl>(CDecl)) {
for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(),
E = PDecl->prop_end(); P != E; ++P) {
ObjCPropertyDecl *Prop = *P;
if (Prop->getIdentifier() == II)
return Prop;
}
// scan through protocol's protocols.
for (ObjCProtocolDecl::protocol_iterator PI = PDecl->protocol_begin(),
E = PDecl->protocol_end(); PI != E; ++PI) {
ObjCPropertyDecl *Prop = LookupPropertyDecl((*PI), II);
if (Prop)
return Prop;
}
}
else if (const ObjCCategoryDecl *CatDecl =
dyn_cast<ObjCCategoryDecl>(CDecl)) {
for (ObjCContainerDecl::prop_iterator P = CatDecl->prop_begin(),
E = CatDecl->prop_end(); P != E; ++P) {
ObjCPropertyDecl *Prop = *P;
if (Prop->getIdentifier() == II)
return Prop;
}
}
return 0;
}
/// PropertyIfSetterOrGetter - Looks up the property if named declaration
/// is a setter or getter method backing a property.
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();
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;
}
/// \brief Default synthesizes all properties which must be synthesized
/// in class's \@implementation.
void Sema::DefaultSynthesizeProperties(Scope *S, ObjCImplDecl* IMPDecl,

View File

@ -5,7 +5,7 @@
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}}
@property(nonatomic,assign) id ptarget __attribute__((availability(ios,introduced=2.0,deprecated=3.0))); // expected-note 2 {{property 'ptarget' is declared deprecated here}}
@end
@protocol P1<P>
@ -50,3 +50,15 @@ 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}}
}
@interface ProtocolInCategory
@end
@interface ProtocolInCategory (TheCategory) <P1>
- (id)ptarget; // expected-note {{method 'ptarget' declared here}}
@end
id useDeprecatedProperty(ProtocolInCategory *obj) {
return [obj ptarget]; // expected-warning {{'ptarget' is deprecated: first deprecated in iOS 3.0}}
}

View File

@ -52,7 +52,7 @@ void test0(Test0 *x) {
@interface MyClass {
__weak MyClass *_parent;
}
@property (weak) MyClass *parent; // expected-note 2 {{property declared here}}
@property (weak) MyClass *parent; // expected-note 4 {{property declared here}}
@end
@implementation MyClass
@ -78,3 +78,23 @@ void testProtocol(id <MyProtocol> input) {
[input.object Meth]; // expected-warning {{weak property may be unpredictably set to nil}} expected-note {{assign the value to a strong variable to keep the object alive during use}}
}
@interface Subclass : MyClass
// Unnecessarily redeclare -parent.
- (id)parent;
@end
@implementation Subclass
- (id)parent {
return [super parent];
}
- (void)doSomethingElse {
[[self parent] doSomething]; // expected-warning {{weak property may be unpredictably set to nil}} expected-note {{assign the value to a strong variable to keep the object alive during use}}
(void)self.parent.doSomething; // expected-warning {{weak property may be unpredictably set to nil}} expected-note {{assign the value to a strong variable to keep the object alive during use}}
}
@end