]> granicus.if.org Git - clang/commitdiff
Fix <rdar://problem/6578665> user declared setter method should be used when using...
authorSteve Naroff <snaroff@apple.com>
Wed, 11 Mar 2009 13:48:17 +0000 (13:48 +0000)
committerSteve Naroff <snaroff@apple.com>
Wed, 11 Mar 2009 13:48:17 +0000 (13:48 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@66658 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaExpr.cpp
test/SemaObjC/property-user-setter.m

index df8afa450bbc786f39bc8721c6853f487a271a03..9534f7354f3ee36eacbe2de75e91295dd5eee9a9 100644 (file)
@@ -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);
   }
index d4da1dfed9f4607527f022926192cff01cafb0a4..489e3a7ab65585a6b606f3ebb0d45aa95bfb65ff 100644 (file)
 
 @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;
+}