Support for implicit property assignment. Error assigning to
'implicit' property with no 'setter'.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@59878 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 8474548..ef3ead4 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -1090,6 +1090,20 @@
   return VT; // should never get here (a typedef type should always be found).
 }
 
+/// constructSetterName - Return the setter name for the given
+/// identifier, i.e. "set" + Name where the initial character of Name
+/// has been capitalized.
+// FIXME: Merge with same routine in Parser. But where should this
+// live?
+static IdentifierInfo *constructSetterName(IdentifierTable &Idents,
+                                           const IdentifierInfo *Name) {
+  llvm::SmallString<100> SelectorName;
+  SelectorName = "set";
+  SelectorName.append(Name->getName(), Name->getName()+Name->getLength());
+  SelectorName[3] = toupper(SelectorName[3]);
+  return &Idents.get(&SelectorName[0], &SelectorName[SelectorName.size()]);
+}
+
 Action::ExprResult Sema::
 ActOnMemberReferenceExpr(ExprTy *Base, SourceLocation OpLoc,
                          tok::TokenKind OpKind, SourceLocation MemberLoc,
@@ -1198,9 +1212,30 @@
     }
     if (Getter) {
       // If we found a getter then this may be a valid dot-reference, we
-      // will look for the matching setter, if it is needed. But we don't
-      // know this yet.
-      return new ObjCKVCRefExpr(Getter, Getter->getResultType(), 
+      // will look for the matching setter, in case it is needed.
+      IdentifierInfo *SetterName = constructSetterName(PP.getIdentifierTable(),
+                                                       &Member);
+      Selector SetterSel = PP.getSelectorTable().getUnarySelector(SetterName);
+      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);
+        }
+      }
+      
+      // FIXME: we must check that the setter has property type.      
+      return new ObjCKVCRefExpr(Getter, Getter->getResultType(), Setter,
                                 MemberLoc, BaseExpr);
     }
   }
@@ -2522,6 +2557,9 @@
   case Expr::MLV_ReadonlyProperty:
     Diag = diag::error_readonly_property_assignment;
     break;
+  case Expr::MLV_NoSetterProperty:
+    Diag = diag::error_nosetter_property_assignment;
+    break;
   }
 
   if (NeedType)