From: Jordan Rose Date: Wed, 10 Oct 2012 16:42:54 +0000 (+0000) Subject: Move Sema::PropertyIfSetterOrGetter to ObjCMethodDecl::findPropertyDecl. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=04bec39d61f2b392d798882c9141fecf3ca653c5;p=clang 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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@165628 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h index 330f6931f3..530546ecc3 100644 --- a/include/clang/AST/DeclObjC.h +++ b/include/clang/AST/DeclObjC.h @@ -427,7 +427,14 @@ public: /// method in the interface or its categories. void getOverriddenMethods( SmallVectorImpl &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; diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 6823e45ecb..bdc245ee5a 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -2308,18 +2308,7 @@ public: void CollectImmediateProperties(ObjCContainerDecl *CDecl, llvm::DenseMap& PropMap, llvm::DenseMap& 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, diff --git a/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp index 750bcaf2e8..90b8807be9 100644 --- a/lib/AST/DeclObjC.cpp +++ b/lib/AST/DeclObjC.cpp @@ -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(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 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 //===----------------------------------------------------------------------===// diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 7c73c17df8..669d8356f5 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -87,13 +87,17 @@ static AvailabilityResult DiagnoseAvailabilityOfDecl(Sema &S, if (const EnumDecl *TheEnumDecl = dyn_cast(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(D)) { + if (const ObjCPropertyDecl *PD = MD->findPropertyDecl()) { + AvailabilityResult PDeclResult = PD->getAvailability(0); + if (PDeclResult == Result) + ObjCPDecl = PD; + } } + } switch (Result) { case AR_Available: diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp index ec16bab4b5..1bb4df0483 100644 --- a/lib/Sema/SemaExprObjC.cpp +++ b/lib/Sema/SemaExprObjC.cpp @@ -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(RExpr)) { RExpr = POE->getSyntacticForm(); if (ObjCPropertyRefExpr *PRE = dyn_cast(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(Container), - Sel.getIdentifierInfoForSlot(0)); - } + if (Method && Method->getSelector().getNumArgs() == 0) { + PDecl = Method->findPropertyDecl(); if (PDecl) T = PDecl->getType(); } diff --git a/lib/Sema/SemaObjCProperty.cpp b/lib/Sema/SemaObjCProperty.cpp index 64dfa5677a..e7fbb8ffac 100644 --- a/lib/Sema/SemaObjCProperty.cpp +++ b/lib/Sema/SemaObjCProperty.cpp @@ -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(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(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(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(D); - if (!Method) - return 0; - - if (Method->isPropertyAccessor()) { - const ObjCContainerDecl *Container = - cast(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 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, diff --git a/test/SemaObjC/property-deprecated-warning.m b/test/SemaObjC/property-deprecated-warning.m index 3e6ffe0672..aa7b764fab 100644 --- a/test/SemaObjC/property-deprecated-warning.m +++ b/test/SemaObjC/property-deprecated-warning.m @@ -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

@@ -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) +- (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}} +} diff --git a/test/SemaObjC/weak-receiver-warn.m b/test/SemaObjC/weak-receiver-warn.m index 2a109dde5e..88b867ed0d 100644 --- a/test/SemaObjC/weak-receiver-warn.m +++ b/test/SemaObjC/weak-receiver-warn.m @@ -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 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 +