From 1ca6694b5b37470ac736737a26da09b088a18d5d Mon Sep 17 00:00:00 2001 From: Steve Naroff Date: Wed, 11 Mar 2009 13:48:17 +0000 Subject: [PATCH] Fix 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 --- lib/Sema/SemaExpr.cpp | 61 ++++++++++++++++------------ test/SemaObjC/property-user-setter.m | 29 +++++++++++++ 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; +} -- 2.40.0