Patch to supprt case of readonly property being 
assigned to when it has user declared setter method
defined in the class implementation (but no declaration in
the class itself).


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@62098 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index bf04042..d3d3d35 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -2920,10 +2920,33 @@
   return InvalidOperands(Loc, lex, rex);
 }
 
+/// IsReadonlyProperty - Verify that otherwise a valid l-value expression
+/// is a read-only property; return true if so. A readonly property expression
+/// depends on various declarations and thus must be treated specially.
+///
+static bool IsReadonlyProperty(Expr *E, Sema &S) 
+{
+  if (E->getStmtClass() == Expr::ObjCPropertyRefExprClass) {
+    const ObjCPropertyRefExpr* PropExpr = cast<ObjCPropertyRefExpr>(E);
+    if (ObjCPropertyDecl *PDecl = PropExpr->getProperty()) {
+      QualType BaseType = PropExpr->getBase()->getType();
+      if (const PointerType *PTy = BaseType->getAsPointerType())
+        if (const ObjCInterfaceType *IFTy = 
+            PTy->getPointeeType()->getAsObjCInterfaceType())
+          if (ObjCInterfaceDecl *IFace = IFTy->getDecl())
+            if (S.isPropertyReadonly(PDecl, IFace))
+              return true;
+    }
+  }
+  return false;
+}
+
 /// CheckForModifiableLvalue - Verify that E is a modifiable lvalue.  If not,
 /// emit an error and return true.  If so, return false.
 static bool CheckForModifiableLvalue(Expr *E, SourceLocation Loc, Sema &S) {
-  Expr::isModifiableLvalueResult IsLV = E->isModifiableLvalue(S.Context); 
+  Expr::isModifiableLvalueResult IsLV = E->isModifiableLvalue(S.Context);
+  if (IsLV == Expr::MLV_Valid && IsReadonlyProperty(E, S))
+    IsLV = Expr::MLV_ReadonlyProperty;
   if (IsLV == Expr::MLV_Valid)
     return false;