summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema
diff options
context:
space:
mode:
authorFariborz Jahanian <fjahanian@apple.com>2009-01-12 19:55:42 +0000
committerFariborz Jahanian <fjahanian@apple.com>2009-01-12 19:55:42 +0000
commit8e1555c7c3bf668fbda3fa9c13f0499332e1bf70 (patch)
tree7008bf246b43c096f5001a6ec77617d1d4a92045 /clang/lib/Sema
parentdf5598444af12781b8d1eb0d6059463934d5c620 (diff)
downloadbcm5719-llvm-8e1555c7c3bf668fbda3fa9c13f0499332e1bf70.tar.gz
bcm5719-llvm-8e1555c7c3bf668fbda3fa9c13f0499332e1bf70.zip
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). llvm-svn: 62098
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r--clang/lib/Sema/Sema.h3
-rw-r--r--clang/lib/Sema/SemaDeclObjC.cpp45
-rw-r--r--clang/lib/Sema/SemaExpr.cpp25
3 files changed, 72 insertions, 1 deletions
diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h
index 4db6f646b6a..f098372d97f 100644
--- a/clang/lib/Sema/Sema.h
+++ b/clang/lib/Sema/Sema.h
@@ -538,6 +538,9 @@ public:
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.
diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp
index c4b085dc1eb..afcf45622b9 100644
--- a/clang/lib/Sema/SemaDeclObjC.cpp
+++ b/clang/lib/Sema/SemaDeclObjC.cpp
@@ -699,6 +699,51 @@ void Sema::WarnConflictingTypedMethods(ObjCMethodDecl *ImpMethodDecl,
}
}
+/// 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
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index bf04042ef8a..d3d3d3556c4 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -2920,10 +2920,33 @@ inline QualType Sema::CheckLogicalOperands( // C99 6.5.[13,14]
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;
OpenPOWER on IntegriCloud