forked from OSchip/llvm-project
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:
parent
79af985bad
commit
2bd991a1c0
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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}}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in New Issue