[cfe-commits] r62098 - in /cfe/trunk: include/clang/AST/DeclObjC.h lib/AST/DeclObjC.cpp lib/AST/Expr.cpp lib/Sema/Sema.h lib/Sema/SemaDeclObjC.cpp lib/Sema/SemaExpr.cpp test/SemaObjC/property-user-setter.m

Fariborz Jahanian fjahanian at apple.com
Mon Jan 12 11:55:42 PST 2009


Author: fjahanian
Date: Mon Jan 12 13:55:42 2009
New Revision: 62098

URL: http://llvm.org/viewvc/llvm-project?rev=62098&view=rev
Log:
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).

Modified:
    cfe/trunk/include/clang/AST/DeclObjC.h
    cfe/trunk/lib/AST/DeclObjC.cpp
    cfe/trunk/lib/AST/Expr.cpp
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaDeclObjC.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/test/SemaObjC/property-user-setter.m

Modified: cfe/trunk/include/clang/AST/DeclObjC.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclObjC.h?rev=62098&r1=62097&r2=62098&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/DeclObjC.h (original)
+++ cfe/trunk/include/clang/AST/DeclObjC.h Mon Jan 12 13:55:42 2009
@@ -405,7 +405,6 @@
   
   ObjCCategoryDecl *FindCategoryDeclaration(IdentifierInfo *CategoryId) const;
   ObjCIvarDecl *FindIvarDeclaration(IdentifierInfo *IvarId) const;
-  bool isPropertyReadonly(ObjCPropertyDecl *PropertyDecl) const;
 
   typedef ObjCList<ObjCProtocolDecl>::iterator protocol_iterator;
   protocol_iterator protocol_begin() const {return ReferencedProtocols.begin();}

Modified: cfe/trunk/lib/AST/DeclObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclObjC.cpp?rev=62098&r1=62097&r2=62098&view=diff

==============================================================================
--- cfe/trunk/lib/AST/DeclObjC.cpp (original)
+++ cfe/trunk/lib/AST/DeclObjC.cpp Mon Jan 12 13:55:42 2009
@@ -251,34 +251,6 @@
   }
 }
 
-/// isPropertyReadonly - Return true if property is readonly, by searching
-/// for the property in the class and in its categories.
-///
-bool ObjCInterfaceDecl::isPropertyReadonly(ObjCPropertyDecl *PDecl) const
-{
-  // Even if property is ready only, if interface has a user defined setter, 
-  // it is not considered read only. 
-  if (!PDecl->isReadOnly() || getInstanceMethod(PDecl->getSetterName()))
-    return false;
-
-  // Main class has the property as 'readonly'. Must search
-  // through the category list to see if the property's 
-  // attribute has been over-ridden to 'readwrite'.
-  for (ObjCCategoryDecl *Category = getCategoryList();
-       Category; Category = Category->getNextClassCategory()) {
-    // Even if property is ready only, if a category has a user defined setter, 
-    // it is not considered read only. 
-    if (Category->getInstanceMethod(PDecl->getSetterName()))
-      return false;
-    ObjCPropertyDecl *P = 
-      Category->FindPropertyDeclaration(PDecl->getIdentifier());
-    if (P && !P->isReadOnly())
-      return false;
-  }
-
-  return true;
-}
-
 /// FindCategoryDeclaration - Finds category declaration in the list of
 /// categories for this class and returns it. Name of the category is passed
 /// in 'CategoryId'. If category not found, return 0;

Modified: cfe/trunk/lib/AST/Expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Expr.cpp?rev=62098&r1=62097&r2=62098&view=diff

==============================================================================
--- cfe/trunk/lib/AST/Expr.cpp (original)
+++ cfe/trunk/lib/AST/Expr.cpp Mon Jan 12 13:55:42 2009
@@ -604,19 +604,7 @@
     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()) {
-      QualType BaseType = PropExpr->getBase()->getType();
-      if (const PointerType *PTy = BaseType->getAsPointerType())
-        if (const ObjCInterfaceType *IFTy = 
-            PTy->getPointeeType()->getAsObjCInterfaceType())
-          if (ObjCInterfaceDecl *IFace = IFTy->getDecl())
-            if (IFace->isPropertyReadonly(PDecl))
-              return MLV_ReadonlyProperty;
-    }
-  }
+  
   // Assigning to an 'implicit' property?
   else if (getStmtClass() == ObjCKVCRefExprClass) {
     const ObjCKVCRefExpr* KVCExpr = cast<ObjCKVCRefExpr>(this);

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=62098&r1=62097&r2=62098&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Mon Jan 12 13:55:42 2009
@@ -538,6 +538,9 @@
                                    ObjCMethodDecl *IntfMethod);
 
   NamespaceDecl *GetStdNamespace();
+  
+  bool isPropertyReadonly(ObjCPropertyDecl *PropertyDecl,
+                          ObjCInterfaceDecl *IDecl) const;
                            
   /// CheckProtocolMethodDefs - This routine checks unimplemented
   /// methods declared in protocol, and those referenced by it.

Modified: cfe/trunk/lib/Sema/SemaDeclObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclObjC.cpp?rev=62098&r1=62097&r2=62098&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclObjC.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclObjC.cpp Mon Jan 12 13:55:42 2009
@@ -699,6 +699,51 @@
   }
 }
 
+/// isPropertyReadonly - Return true if property is readonly, by searching
+/// for the property in the class and in its categories and implementations
+///
+bool Sema::isPropertyReadonly(ObjCPropertyDecl *PDecl,
+                              ObjCInterfaceDecl *IDecl) const {
+  // by far the most common case.
+  if (!PDecl->isReadOnly())
+    return false;
+  // Even if property is ready only, if interface has a user defined setter, 
+  // it is not considered read only.
+  if (IDecl->getInstanceMethod(PDecl->getSetterName()))
+    return false;
+  
+  // Main class has the property as 'readonly'. Must search
+  // through the category list to see if the property's 
+  // attribute has been over-ridden to 'readwrite'.
+  for (ObjCCategoryDecl *Category = IDecl->getCategoryList();
+       Category; Category = Category->getNextClassCategory()) {
+    // Even if property is ready only, if a category has a user defined setter, 
+    // it is not considered read only. 
+    if (Category->getInstanceMethod(PDecl->getSetterName()))
+      return false;
+    ObjCPropertyDecl *P = 
+    Category->FindPropertyDeclaration(PDecl->getIdentifier());
+    if (P && !P->isReadOnly())
+      return false;
+  }
+  
+  // Also, check for definition of a setter method in the implementation if
+  // all else failed.
+  if (ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(CurContext)) {
+    if (ObjCImplementationDecl *IMD = 
+        dyn_cast<ObjCImplementationDecl>(OMD->getDeclContext())) {
+      if (IMD->getInstanceMethod(PDecl->getSetterName()))
+        return false;
+    }
+    else if (ObjCCategoryImplDecl *CIMD = 
+             dyn_cast<ObjCCategoryImplDecl>(OMD->getDeclContext())) {
+      if (CIMD->getInstanceMethod(PDecl->getSetterName()))
+        return false;
+    }
+  }
+  return true;
+}
+
 /// FIXME: Type hierarchies in Objective-C can be deep. We could most
 /// likely improve the efficiency of selector lookups and type
 /// checking by associating with each protocol / interface / category

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=62098&r1=62097&r2=62098&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Mon Jan 12 13:55:42 2009
@@ -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;
   

Modified: cfe/trunk/test/SemaObjC/property-user-setter.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/property-user-setter.m?rev=62098&r1=62097&r2=62098&view=diff

==============================================================================
--- cfe/trunk/test/SemaObjC/property-user-setter.m (original)
+++ cfe/trunk/test/SemaObjC/property-user-setter.m Mon Jan 12 13:55:42 2009
@@ -23,3 +23,39 @@
   self.z = 2; // expected-error {{assigning to property with 'readonly' attribute not allowed}}
 }
 @end
+
+// Test when property is 'readonly' but it has a setter in
+// its implementation only.
+ at interface I1  {
+}
+ at property(readonly) int identifier;
+ at end
+
+
+ at implementation I1
+ at dynamic identifier;
+- (void)setIdentifier:(int)ident {}
+
+- (id)initWithIdentifier:(int)Arg {
+    self.identifier = 0;
+}
+
+ at end
+
+
+// Also in a category implementation
+ at interface I1(CAT)  
+ at property(readonly) int rprop;
+ at end
+
+
+ at implementation I1(CAT)
+ at dynamic rprop;
+- (void)setRprop:(int)ident {}
+
+- (id)initWithIdentifier:(int)Arg {
+    self.rprop = 0;
+}
+
+ at end
+





More information about the cfe-commits mailing list