New AST node to access "implicit" setter/getter using property dor syntax.
Issuing diagnostics when assigning to read-only properties.
This is work in progress.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@59874 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index e6a7b41..6a15ea6 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -463,6 +463,8 @@
     return LV_Valid;
   case ObjCPropertyRefExprClass: // FIXME: check if read-only property.
     return LV_Valid;
+  case ObjCKVCRefExprClass: // FIXME: check if read-only property.
+      return LV_Valid;
   case PredefinedExprClass:
     return LV_Valid;
   case VAArgExprClass:
@@ -545,6 +547,16 @@
     if (!BDR->isByRef() && isa<VarDecl>(BDR->getDecl()))
       return MLV_NotBlockQualified;
   }
+  // Assigning to a readonly property?
+  if (getStmtClass() == ObjCPropertyRefExprClass) {
+    const ObjCPropertyRefExpr* PropExpr = cast<ObjCPropertyRefExpr>(this);
+    if (ObjCPropertyDecl *PDecl = PropExpr->getProperty()) {
+      ObjCPropertyDecl::PropertyAttributeKind Pkind = 
+        PDecl->getPropertyAttributes();
+      if (Pkind == ObjCPropertyDecl::OBJC_PR_readonly)
+        return MLV_ReadonlyProperty;
+    }
+  }
   return MLV_Valid;    
 }
 
@@ -1353,6 +1365,10 @@
 Stmt::child_iterator ObjCPropertyRefExpr::child_begin() { return &Base; }
 Stmt::child_iterator ObjCPropertyRefExpr::child_end() { return &Base+1; }
 
+// ObjCKVCRefExpr
+Stmt::child_iterator ObjCKVCRefExpr::child_begin() { return &Base; }
+Stmt::child_iterator ObjCKVCRefExpr::child_end() { return &Base+1; }
+
 // ObjCSuperExpr
 Stmt::child_iterator ObjCSuperExpr::child_begin() { return child_iterator(); }
 Stmt::child_iterator ObjCSuperExpr::child_end() { return child_iterator(); }
diff --git a/lib/AST/StmtDumper.cpp b/lib/AST/StmtDumper.cpp
index a992efb..04ae2cd 100644
--- a/lib/AST/StmtDumper.cpp
+++ b/lib/AST/StmtDumper.cpp
@@ -139,6 +139,7 @@
     void VisitObjCSelectorExpr(ObjCSelectorExpr *Node);
     void VisitObjCProtocolExpr(ObjCProtocolExpr *Node);
     void VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *Node);
+    void VisitObjCKVCRefExpr(ObjCKVCRefExpr *Node);
     void VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node);
     void VisitObjCSuperExpr(ObjCSuperExpr *Node);
   };
@@ -470,16 +471,18 @@
 void StmtDumper::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *Node) {
   DumpExpr(Node);
 
-  if (Node->getKind() == ObjCPropertyRefExpr::MethodRef) {
-    ObjCMethodDecl *Getter = Node->getGetterMethod();
-    ObjCMethodDecl *Setter = Node->getSetterMethod();
-    fprintf(F, " Kind=MethodRef Getter=\"%s\" Setter=\"%s\"", 
-            Getter->getSelector().getName().c_str(),
-            Setter ? Setter->getSelector().getName().c_str() : "(null)");
-  } else {
-    fprintf(F, " Kind=PropertyRef Property=\"%s\"", 
-            Node->getProperty()->getIdentifierName());
-  }
+  fprintf(F, " Kind=PropertyRef Property=\"%s\"", 
+          Node->getProperty()->getIdentifierName());
+}
+
+void StmtDumper::VisitObjCKVCRefExpr(ObjCKVCRefExpr *Node) {
+  DumpExpr(Node);
+  
+  ObjCMethodDecl *Getter = Node->getGetterMethod();
+  ObjCMethodDecl *Setter = Node->getSetterMethod();
+  fprintf(F, " Kind=MethodRef Getter=\"%s\" Setter=\"%s\"", 
+          Getter->getSelector().getName().c_str(),
+          Setter ? Setter->getSelector().getName().c_str() : "(null)");
 }
 
 void StmtDumper::VisitObjCSuperExpr(ObjCSuperExpr *Node) {
diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp
index cb5c44f..94cfae9 100644
--- a/lib/AST/StmtPrinter.cpp
+++ b/lib/AST/StmtPrinter.cpp
@@ -502,6 +502,14 @@
   // FIXME: OS << Node->getDecl()->getName();
 }
 
+void StmtPrinter::VisitObjCKVCRefExpr(ObjCKVCRefExpr *Node) {
+  if (Node->getBase()) {
+    PrintExpr(Node->getBase());
+    OS << ".";
+  }
+  // FIXME: Setter/Getter names
+}
+
 void StmtPrinter::VisitPredefinedExpr(PredefinedExpr *Node) {
   switch (Node->getIdentType()) {
     default:
diff --git a/lib/AST/StmtSerialization.cpp b/lib/AST/StmtSerialization.cpp
index 8faef8b..2d6f3c7 100644
--- a/lib/AST/StmtSerialization.cpp
+++ b/lib/AST/StmtSerialization.cpp
@@ -1150,14 +1150,14 @@
 void ObjCPropertyRefExpr::EmitImpl(Serializer& S) const {
   S.Emit(Loc);
   S.Emit(getType());
-  unsigned Kind = getKind();
-  S.Emit(Kind);
-  if (Kind == PropertyRef) {
-    S.EmitPtr(getProperty());
-  } else {
-    S.EmitPtr(getGetterMethod());
-    S.EmitPtr(getSetterMethod());
-  }
+  S.EmitPtr(getProperty());
+}
+
+void ObjCKVCRefExpr::EmitImpl(Serializer& S) const {
+  S.Emit(Loc);
+  S.Emit(getType());
+  S.EmitPtr(getGetterMethod());
+  S.EmitPtr(getSetterMethod());
 }
   
 ObjCPropertyRefExpr* ObjCPropertyRefExpr::CreateImpl(Deserializer& D, 
@@ -1165,13 +1165,17 @@
   SourceLocation Loc = SourceLocation::ReadVal(D);
   QualType T = QualType::ReadVal(D);
   ObjCPropertyRefExpr* dr = new ObjCPropertyRefExpr(NULL,T,Loc,0);
-  unsigned Kind = D.ReadInt();
-  if (Kind == PropertyRef) {
-    D.ReadPtr(dr->Referent.AsProperty,false);
-  } else {
-    D.ReadPtr(dr->Referent.AsMethod.Setter,false);
-    D.ReadPtr(dr->Referent.AsMethod.Getter,false);
-  }
+  D.ReadPtr(dr->AsProperty,false);
+  return dr;
+}
+
+ObjCKVCRefExpr* ObjCKVCRefExpr::CreateImpl(Deserializer& D, 
+                                           ASTContext& C) {
+  SourceLocation Loc = SourceLocation::ReadVal(D);
+  QualType T = QualType::ReadVal(D);
+  ObjCKVCRefExpr* dr = new ObjCKVCRefExpr(NULL,T,Loc,0);
+  D.ReadPtr(dr->Setter,false);
+  D.ReadPtr(dr->Getter,false);
   return dr;
 }