aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/AST/DeclObjC.h9
-rw-r--r--include/clang/Sema/Sema.h11
-rw-r--r--lib/AST/DeclObjC.cpp42
-rw-r--r--lib/Sema/SemaExpr.cpp14
-rw-r--r--lib/Sema/SemaExprObjC.cpp14
-rw-r--r--lib/Sema/SemaObjCProperty.cpp91
-rw-r--r--test/SemaObjC/property-deprecated-warning.m14
-rw-r--r--test/SemaObjC/weak-receiver-warn.m22
8 files changed, 97 insertions, 120 deletions
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<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;
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<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,
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<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
//===----------------------------------------------------------------------===//
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<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:
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<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();
}
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<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,
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<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}}
+}
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 <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
+