]> granicus.if.org Git - clang/commitdiff
Patch to allow over-riding of readonly property to
authorFariborz Jahanian <fjahanian@apple.com>
Tue, 25 Nov 2008 17:56:43 +0000 (17:56 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Tue, 25 Nov 2008 17:56:43 +0000 (17:56 +0000)
a writable property in one of its category.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@60035 91177308-0d34-0410-b5e6-96231b3b80d8

lib/AST/Expr.cpp
test/Analysis/ObjCProperties.m
test/SemaObjC/property-category-1.m [new file with mode: 0644]

index 835a467fc21a0116133d3ae554c49cd19737b103..56f08b28d9549e4c81bef910986470a8e8339433 100644 (file)
@@ -551,14 +551,28 @@ Expr::isModifiableLvalueResult Expr::isModifiableLvalue(ASTContext &Ctx) const {
   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)
+      if (PDecl->isReadOnly()) {
+        // Main class has the property as 'readyonly'. Must search
+        // through the category list to see if the property's 
+        // attribute has been over-ridden to 'readwrite'.
+        const Expr *BaseExpr = PropExpr->getBase();
+        QualType BaseType = BaseExpr->getType();
+        const PointerType *PTy = BaseType->getAsPointerType();
+        const ObjCInterfaceType *IFTy = 
+          PTy->getPointeeType()->getAsObjCInterfaceType();
+        ObjCInterfaceDecl *IFace = IFTy->getDecl();
+        for (ObjCCategoryDecl *Category = IFace->getCategoryList();
+             Category; Category = Category->getNextClassCategory()) {
+          PDecl= Category->FindPropertyDeclaration(PDecl->getIdentifier());
+          if (PDecl && !PDecl->isReadOnly())
+            return MLV_Valid;
+        }
         return MLV_ReadonlyProperty;
+      }
     }
   }
   // Assigning to an 'implicit' property?
-  if (getStmtClass() == ObjCKVCRefExprClass) {
+  else if (getStmtClass() == ObjCKVCRefExprClass) {
     const ObjCKVCRefExpr* KVCExpr = cast<ObjCKVCRefExpr>(this);
     if (KVCExpr->getSetterMethod() == 0)
       return MLV_NoSetterProperty;
index 03eefc23fe299633e1eed5204e87361aeec53694..f207475bd637f4ef4d5e6ccf788da2895aaf5883 100644 (file)
@@ -8,7 +8,7 @@
     id _X;
 }
 - (id)initWithY:(id)Y;
-@property(copy, readonly) id X;
+@property(copy, readwrite) id X;
 @end
 
 @implementation MyClass
diff --git a/test/SemaObjC/property-category-1.m b/test/SemaObjC/property-category-1.m
new file mode 100644 (file)
index 0000000..32e14f0
--- /dev/null
@@ -0,0 +1,35 @@
+// RUN: clang -fsyntax-only -verify %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;
+}
+