aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteve Naroff <snaroff@apple.com>2009-03-11 13:48:17 +0000
committerSteve Naroff <snaroff@apple.com>2009-03-11 13:48:17 +0000
commit1ca6694b5b37470ac736737a26da09b088a18d5d (patch)
treec9172aeee5b7ff4f9ba7fc33c9e0d69e1f7c7458
parent3c4b37980ad5582409fa9a99ac29da8ab59f1ed0 (diff)
Fix <rdar://problem/6578665> user declared setter method should be used when using property syntx.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@66658 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Sema/SemaExpr.cpp61
-rw-r--r--test/SemaObjC/property-user-setter.m29
2 files changed, 64 insertions, 26 deletions
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index df8afa450b..9534f7354f 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -1883,38 +1883,47 @@ Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc,
// Check if we can reference this property.
if (DiagnoseUseOfDecl(Getter, MemberLoc))
return ExprError();
-
- // If we found a getter then this may be a valid dot-reference, we
- // will look for the matching setter, in case it is needed.
- Selector SetterSel =
- SelectorTable::constructSetterName(PP.getIdentifierTable(),
- PP.getSelectorTable(), &Member);
- ObjCMethodDecl *Setter = IFace->lookupInstanceMethod(SetterSel);
- if (!Setter) {
- // If this reference is in an @implementation, also check for 'private'
- // methods.
- if (ObjCMethodDecl *CurMeth = getCurMethodDecl())
- if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface())
- if (ObjCImplementationDecl *ImpDecl =
- ObjCImplementations[ClassDecl->getIdentifier()])
- Setter = ImpDecl->getInstanceMethod(SetterSel);
- }
- // Look through local category implementations associated with the class.
- if (!Setter) {
- for (unsigned i = 0; i < ObjCCategoryImpls.size() && !Setter; i++) {
- if (ObjCCategoryImpls[i]->getClassInterface() == IFace)
- Setter = ObjCCategoryImpls[i]->getInstanceMethod(SetterSel);
- }
+ }
+ // If we found a getter then this may be a valid dot-reference, we
+ // will look for the matching setter, in case it is needed.
+ Selector SetterSel =
+ SelectorTable::constructSetterName(PP.getIdentifierTable(),
+ PP.getSelectorTable(), &Member);
+ ObjCMethodDecl *Setter = IFace->lookupInstanceMethod(SetterSel);
+ if (!Setter) {
+ // If this reference is in an @implementation, also check for 'private'
+ // methods.
+ if (ObjCMethodDecl *CurMeth = getCurMethodDecl())
+ if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface())
+ if (ObjCImplementationDecl *ImpDecl =
+ ObjCImplementations[ClassDecl->getIdentifier()])
+ Setter = ImpDecl->getInstanceMethod(SetterSel);
+ }
+ // Look through local category implementations associated with the class.
+ if (!Setter) {
+ for (unsigned i = 0; i < ObjCCategoryImpls.size() && !Setter; i++) {
+ if (ObjCCategoryImpls[i]->getClassInterface() == IFace)
+ Setter = ObjCCategoryImpls[i]->getInstanceMethod(SetterSel);
}
+ }
- if (Setter && DiagnoseUseOfDecl(Setter, MemberLoc))
- return ExprError();
+ if (Setter && DiagnoseUseOfDecl(Setter, MemberLoc))
+ return ExprError();
+ if (Getter || Setter) {
+ QualType PType;
+
+ if (Getter)
+ PType = Getter->getResultType();
+ else {
+ for (ObjCMethodDecl::param_iterator PI = Setter->param_begin(),
+ E = Setter->param_end(); PI != E; ++PI)
+ PType = (*PI)->getType();
+ }
// FIXME: we must check that the setter has property type.
- return Owned(new (Context) ObjCKVCRefExpr(Getter, Getter->getResultType(),
+ return Owned(new (Context) ObjCKVCRefExpr(Getter, PType,
Setter, MemberLoc, BaseExpr));
}
-
return ExprError(Diag(MemberLoc, diag::err_property_not_found)
<< &Member << BaseType);
}
diff --git a/test/SemaObjC/property-user-setter.m b/test/SemaObjC/property-user-setter.m
index d4da1dfed9..489e3a7ab6 100644
--- a/test/SemaObjC/property-user-setter.m
+++ b/test/SemaObjC/property-user-setter.m
@@ -59,3 +59,32 @@
@end
+static int g_val;
+
+@interface Root
++ alloc;
+- init;
+@end
+
+@interface Subclass : Root
+{
+ int setterOnly;
+}
+- (void) setSetterOnly:(int)value;
+@end
+
+@implementation Subclass
+- (void) setSetterOnly:(int)value {
+ setterOnly = value;
+ g_val = setterOnly;
+}
+@end
+
+int main (void) {
+ Subclass *x = [[Subclass alloc] init];
+
+ x.setterOnly = 4;
+ if (g_val != 4)
+ abort ();
+ return 0;
+}