[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