summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
authorFariborz Jahanian <fjahanian@apple.com>2008-11-22 20:25:50 +0000
committerFariborz Jahanian <fjahanian@apple.com>2008-11-22 20:25:50 +0000
commit5118c418e65cb0f19b31c713e7052d153f907d7b (patch)
treeb97d7a311277dd26a50405dc2897faa7cc7d90c2 /clang/lib
parent8cd9b96ee185e4db5828310dcc959e985e0adec5 (diff)
downloadbcm5719-llvm-5118c418e65cb0f19b31c713e7052d153f907d7b.tar.gz
bcm5719-llvm-5118c418e65cb0f19b31c713e7052d153f907d7b.zip
Support for implicit property assignment. Error assigning to
'implicit' property with no 'setter'. llvm-svn: 59878
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/AST/Expr.cpp6
-rw-r--r--clang/lib/AST/StmtSerialization.cpp2
-rw-r--r--clang/lib/Sema/SemaExpr.cpp44
3 files changed, 48 insertions, 4 deletions
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index 6a15ea68a52..0ff345a1a8d 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -557,6 +557,12 @@ Expr::isModifiableLvalueResult Expr::isModifiableLvalue(ASTContext &Ctx) const {
return MLV_ReadonlyProperty;
}
}
+ // Assigning to an 'implicit' property?
+ if (getStmtClass() == ObjCKVCRefExprClass) {
+ const ObjCKVCRefExpr* KVCExpr = cast<ObjCKVCRefExpr>(this);
+ if (KVCExpr->getSetterMethod() == 0)
+ return MLV_NoSetterProperty;
+ }
return MLV_Valid;
}
diff --git a/clang/lib/AST/StmtSerialization.cpp b/clang/lib/AST/StmtSerialization.cpp
index 2d6f3c7e8a3..8bf70396856 100644
--- a/clang/lib/AST/StmtSerialization.cpp
+++ b/clang/lib/AST/StmtSerialization.cpp
@@ -1173,7 +1173,7 @@ ObjCKVCRefExpr* ObjCKVCRefExpr::CreateImpl(Deserializer& D,
ASTContext& C) {
SourceLocation Loc = SourceLocation::ReadVal(D);
QualType T = QualType::ReadVal(D);
- ObjCKVCRefExpr* dr = new ObjCKVCRefExpr(NULL,T,Loc,0);
+ ObjCKVCRefExpr* dr = new ObjCKVCRefExpr(NULL,T,NULL,Loc,0);
D.ReadPtr(dr->Setter,false);
D.ReadPtr(dr->Getter,false);
return dr;
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 8474548740b..ef3ead4fa2c 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -1090,6 +1090,20 @@ CheckExtVectorComponent(QualType baseType, SourceLocation OpLoc,
return VT; // should never get here (a typedef type should always be found).
}
+/// constructSetterName - Return the setter name for the given
+/// identifier, i.e. "set" + Name where the initial character of Name
+/// has been capitalized.
+// FIXME: Merge with same routine in Parser. But where should this
+// live?
+static IdentifierInfo *constructSetterName(IdentifierTable &Idents,
+ const IdentifierInfo *Name) {
+ llvm::SmallString<100> SelectorName;
+ SelectorName = "set";
+ SelectorName.append(Name->getName(), Name->getName()+Name->getLength());
+ SelectorName[3] = toupper(SelectorName[3]);
+ return &Idents.get(&SelectorName[0], &SelectorName[SelectorName.size()]);
+}
+
Action::ExprResult Sema::
ActOnMemberReferenceExpr(ExprTy *Base, SourceLocation OpLoc,
tok::TokenKind OpKind, SourceLocation MemberLoc,
@@ -1198,9 +1212,30 @@ ActOnMemberReferenceExpr(ExprTy *Base, SourceLocation OpLoc,
}
if (Getter) {
// If we found a getter then this may be a valid dot-reference, we
- // will look for the matching setter, if it is needed. But we don't
- // know this yet.
- return new ObjCKVCRefExpr(Getter, Getter->getResultType(),
+ // will look for the matching setter, in case it is needed.
+ IdentifierInfo *SetterName = constructSetterName(PP.getIdentifierTable(),
+ &Member);
+ Selector SetterSel = PP.getSelectorTable().getUnarySelector(SetterName);
+ ObjCMethodDecl *Setter = IFace->lookupInstanceMethod(SetterSel);
+ if (!Setter) {
+ // If this reference is in an @implementation, also check for 'private'
+ // methods.
+ if (ObjCMethodDecl *CurMeth = getCurMethodDecl())
+ if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface())
+ if (ObjCImplementationDecl *ImpDecl =
+ ObjCImplementations[ClassDecl->getIdentifier()])
+ Setter = ImpDecl->getInstanceMethod(SetterSel);
+ }
+ // Look through local category implementations associated with the class.
+ if (!Setter) {
+ for (unsigned i = 0; i < ObjCCategoryImpls.size() && !Setter; i++) {
+ if (ObjCCategoryImpls[i]->getClassInterface() == IFace)
+ Setter = ObjCCategoryImpls[i]->getInstanceMethod(SetterSel);
+ }
+ }
+
+ // FIXME: we must check that the setter has property type.
+ return new ObjCKVCRefExpr(Getter, Getter->getResultType(), Setter,
MemberLoc, BaseExpr);
}
}
@@ -2522,6 +2557,9 @@ static bool CheckForModifiableLvalue(Expr *E, SourceLocation Loc, Sema &S) {
case Expr::MLV_ReadonlyProperty:
Diag = diag::error_readonly_property_assignment;
break;
+ case Expr::MLV_NoSetterProperty:
+ Diag = diag::error_nosetter_property_assignment;
+ break;
}
if (NeedType)
OpenPOWER on IntegriCloud