diff options
| author | Fariborz Jahanian <fjahanian@apple.com> | 2009-01-12 19:55:42 +0000 |
|---|---|---|
| committer | Fariborz Jahanian <fjahanian@apple.com> | 2009-01-12 19:55:42 +0000 |
| commit | 8e1555c7c3bf668fbda3fa9c13f0499332e1bf70 (patch) | |
| tree | 7008bf246b43c096f5001a6ec77617d1d4a92045 /clang/lib/Sema | |
| parent | df5598444af12781b8d1eb0d6059463934d5c620 (diff) | |
| download | bcm5719-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.h | 3 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaDeclObjC.cpp | 45 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 25 |
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; |

