]> granicus.if.org Git - clang/commitdiff
Set default property attributes on each property.
authorFariborz Jahanian <fjahanian@apple.com>
Wed, 26 Nov 2008 20:01:34 +0000 (20:01 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Wed, 26 Nov 2008 20:01:34 +0000 (20:01 +0000)
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

include/clang/AST/DeclObjC.h
include/clang/Basic/DiagnosticKinds.def
include/clang/Parse/Action.h
lib/Parse/ParseObjc.cpp
lib/Sema/Sema.h
lib/Sema/SemaDeclObjC.cpp
test/CodeGenObjC/continuation-class.m [new file with mode: 0644]
test/SemaObjC/property-9-impl-method.m

index b52400ab9f6843452792ba26cace98590ed5f607..eda3e6db7df6311c03f221454d3ba9b4f361c906 100644 (file)
@@ -1228,6 +1228,11 @@ public:
     PropertyAttributes |= PRVal;
   }
 
+ void makeitReadWriteAttribute(void) {
+    PropertyAttributes &= ~OBJC_PR_readonly;
+    PropertyAttributes |= OBJC_PR_readwrite;
+ } 
+
   // Helper methods for accessing attributes.
 
   /// isReadOnly - Return true iff the property has a setter.
index 6e7e58e61d28d5c60fc185ec7d1b77a0c5f308cc..a9694fa608a9556154124e7e3deaaa0d16607d03 100644 (file)
@@ -563,6 +563,12 @@ DIAG(warn_property_attribute, WARNING,
      "property %0 '%1' attribute does not match the property inherited from %2")
 DIAG(warn_property_type, WARNING,
      "property type %0 does not match property type inherited from %1")
+DIAG(err_continuation_class, ERROR,
+     "continuation class has no primary class")
+DIAG(err_use_continuation_class, ERROR,
+     "use contination class to override 'readonly' property with 'readwrite'")
+DIAG(warn_property_attr_mismatch, WARNING,
+     "property attribute in continuation class does not match the primary class")
 
 /// C++ parser diagnostics
 DIAG(err_expected_unqualified_id, ERROR,
index 3058ce3aba4750e4c82ad5f4dd913538fda81a11..e32dc388fc74329bb4a82b88e4097c52f98f0c6a 100644 (file)
@@ -963,6 +963,8 @@ public:
   virtual DeclTy *ActOnProperty (Scope *S, SourceLocation AtLoc,
                                  FieldDeclarator &FD, ObjCDeclSpec &ODS,
                                  Selector GetterSel, Selector SetterSel,
+                                DeclTy *ClassCategory,
+                                bool *OverridingProperty,
                                  tok::ObjCKeywordKind MethodImplKind) {
     return 0;
   }
index 9fe4c1ec12e24d477c8e71e3fef99bf2329b8f46..f937ef1d9c051dced06a9477aca77c4d0a5c3558 100644 (file)
@@ -332,10 +332,14 @@ void Parser::ParseObjCInterfaceDeclList(DeclTy *interfaceDecl,
                                            FD.D.getIdentifier());
         Selector SetterSel = 
           PP.getSelectorTable().getUnarySelector(SetterName);
+        bool isOverridingProperty = false;
         DeclTy *Property = Actions.ActOnProperty(CurScope, AtLoc, FD, OCDS,
                                                  GetterSel, SetterSel,
+                                                 interfaceDecl, 
+                                                 &isOverridingProperty,
                                                  MethodImplKind);
-        allProperties.push_back(Property);
+        if (!isOverridingProperty)
+          allProperties.push_back(Property);
       }
       break;
     }
index c8352172f9ae123105f64d6e82651e399fbc0078..614e4873bacc092eeeacaf1e0865031557dbf0e3 100644 (file)
@@ -1051,6 +1051,7 @@ public:
   virtual DeclTy *ActOnProperty(Scope *S, SourceLocation AtLoc,
                                 FieldDeclarator &FD, ObjCDeclSpec &ODS,
                                 Selector GetterSel, Selector SetterSel,
+                                DeclTy *ClassCategory, bool *OverridingProperty,
                                 tok::ObjCKeywordKind MethodImplKind);
   
   virtual DeclTy *ActOnPropertyImplDecl(SourceLocation AtLoc, 
index 95737af18ac9e32e729140371a5b9c85e862a057..9f37e900cdfc755ffa0579816fe40e1d1ac47bb7 100644 (file)
@@ -1186,12 +1186,81 @@ Sema::DeclTy *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc,
                                   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 @@ Sema::DeclTy *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc,
   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 @@ Sema::DeclTy *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc,
   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);
   
diff --git a/test/CodeGenObjC/continuation-class.m b/test/CodeGenObjC/continuation-class.m
new file mode 100644 (file)
index 0000000..9ac51c7
--- /dev/null
@@ -0,0 +1,35 @@
+// RUN: clang -fnext-runtime --emit-llvm -o %t %s
+
+@interface Object
+- (id)new;
+@end
+
+@interface ReadOnly : Object
+{
+  int _object;
+  int _Anotherobject;
+}
+@property(readonly) int object;
+@property(readonly) int Anotherobject;
+@end
+
+@interface ReadOnly ()
+@property(readwrite) int object;
+@property(readwrite, setter = myAnotherobjectSetter:) int Anotherobject;
+@end
+
+@implementation ReadOnly
+@synthesize object = _object;
+@synthesize  Anotherobject = _Anotherobject;
+- (void) myAnotherobjectSetter : (int)val {
+    _Anotherobject = val;
+}
+@end
+
+int main(int argc, char **argv) {
+    ReadOnly *test = [ReadOnly new];
+    test.object = 12345;
+    test.Anotherobject = 200;
+    return test.object - 12345 + test.Anotherobject - 200;
+}
+
index bb13d01b74acd055f6994bc1f2e6a046ed3f51e0..e9e81bd55f5eb1417452e486ca8477d38bd2bd27 100644 (file)
@@ -60,4 +60,5 @@ NSSize minimumSize;
   NSRect dummy, result = {};
   NSDivideRect(self.bounds, &result, &dummy, self.tabAreaThickness, self.rectEdgeForTabs);
 }
+@end