Set default property attributes on each property.
Implemented anonymous category (also know as continuation class)
used to override main class's property attribute. This is work in 
propgress.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@60114 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp
index 95737af..9f37e90 100644
--- a/lib/Sema/SemaDeclObjC.cpp
+++ b/lib/Sema/SemaDeclObjC.cpp
@@ -1186,12 +1186,81 @@
                                   ObjCDeclSpec &ODS,
                                   Selector GetterSel,
                                   Selector SetterSel,
+                                  DeclTy *ClassCategory,
+                                  bool *isOverridingProperty,
                                   tok::ObjCKeywordKind MethodImplKind) {
-  QualType T = GetTypeForDeclarator(FD.D, S);
   unsigned Attributes = ODS.getPropertyAttributes();
+  bool isReadWrite = ((Attributes & ObjCDeclSpec::DQ_PR_readwrite) ||
+                      // default is readwrite!
+                      !(Attributes & ObjCDeclSpec::DQ_PR_readonly));
+  // property is defaulted to 'assign' if it is readwrite and is 
+  // not retain or copy
+  bool isAssign = ((Attributes & ObjCDeclSpec::DQ_PR_assign) ||
+                   (isReadWrite && 
+                    !(Attributes & ObjCDeclSpec::DQ_PR_retain) && 
+                    !(Attributes & ObjCDeclSpec::DQ_PR_copy)));
+  QualType T = GetTypeForDeclarator(FD.D, S);
+  Decl *ClassDecl = static_cast<Decl *>(ClassCategory);
 
   // May modify Attributes.
   CheckObjCPropertyAttributes(T, AtLoc, Attributes);
+  
+  if (ObjCCategoryDecl *CDecl = dyn_cast<ObjCCategoryDecl>(ClassDecl))
+    if (!CDecl->getIdentifier()) {
+      // This is an anonymous category. property requires special 
+      // handling.
+      if (ObjCInterfaceDecl *ICDecl = CDecl->getClassInterface()) {
+        if (ObjCPropertyDecl *PIDecl =
+            ICDecl->FindPropertyDeclaration(FD.D.getIdentifier())) {
+          // property 'PIDecl's readonly attribute will be over-ridden
+          // with anonymous category's readwrite property attribute!
+          unsigned PIkind = PIDecl->getPropertyAttributes();
+          if (isReadWrite && (PIkind & ObjCPropertyDecl::OBJC_PR_readonly)) {
+            if ((Attributes & ObjCPropertyDecl::OBJC_PR_retain) !=
+                (PIkind & ObjCPropertyDecl::OBJC_PR_retain) ||
+                (Attributes & ObjCPropertyDecl::OBJC_PR_copy) !=
+                (PIkind & ObjCPropertyDecl::OBJC_PR_copy) ||
+                (Attributes & ObjCPropertyDecl::OBJC_PR_nonatomic) !=
+                (PIkind & ObjCPropertyDecl::OBJC_PR_nonatomic))
+              Diag(AtLoc, diag::warn_property_attr_mismatch);
+            PIDecl->makeitReadWriteAttribute();
+            if (Attributes & ObjCDeclSpec::DQ_PR_retain)
+              PIDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_retain);
+            if (Attributes & ObjCDeclSpec::DQ_PR_copy)
+              PIDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_copy);
+            PIDecl->setSetterName(SetterSel);
+            // FIXME: use a common routine with addPropertyMethods.
+            ObjCMethodDecl *SetterDecl =
+              ObjCMethodDecl::Create(Context, AtLoc, AtLoc, SetterSel,
+                                     Context.VoidTy,
+                                     ICDecl,
+                                     true, false, true, 
+                                     ObjCMethodDecl::Required);
+            ParmVarDecl *Argument = ParmVarDecl::Create(Context,
+                                                        SetterDecl,
+                                                        SourceLocation(),
+                                                        FD.D.getIdentifier(),
+                                                        T,
+                                                        VarDecl::None,
+                                                        0, 0);
+            SetterDecl->setMethodParams(&Argument, 1);
+            PIDecl->setSetterMethodDecl(SetterDecl);
+          }
+          else
+            Diag(AtLoc, diag::err_use_continuation_class);
+          *isOverridingProperty = true;
+          return 0;
+        }
+        // else
+        // FIXME:
+        // no matching property found in the main class. Must simply
+        // add this property to the main class's property list.
+      } else {
+          Diag(CDecl->getLocation(), diag::err_continuation_class);
+          *isOverridingProperty = true;
+          return 0;
+      }
+    }
 
   ObjCPropertyDecl *PDecl = ObjCPropertyDecl::Create(Context, AtLoc, 
                                                      FD.D.getIdentifier(), T);
@@ -1209,10 +1278,7 @@
   if (Attributes & ObjCDeclSpec::DQ_PR_setter)
     PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_setter);
   
-  if (Attributes & ObjCDeclSpec::DQ_PR_assign)
-    PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_assign);
-  
-  if (Attributes & ObjCDeclSpec::DQ_PR_readwrite)
+  if (isReadWrite)
     PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readwrite);
   
   if (Attributes & ObjCDeclSpec::DQ_PR_retain)
@@ -1221,6 +1287,9 @@
   if (Attributes & ObjCDeclSpec::DQ_PR_copy)
     PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_copy);
   
+  if (isAssign)
+    PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_assign);
+  
   if (Attributes & ObjCDeclSpec::DQ_PR_nonatomic)
     PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_nonatomic);