diff options
author | Steve Naroff <snaroff@apple.com> | 2008-05-30 00:40:33 +0000 |
---|---|---|
committer | Steve Naroff <snaroff@apple.com> | 2008-05-30 00:40:33 +0000 |
commit | ae7840776d6cd31b4d7a4a345b61bcbb3744df6c (patch) | |
tree | 0b1fc9e7cdf0700efbe86ad799e4a87115c2fded | |
parent | 54eec4c00d25cbb30a3e589f1b3a4ebaa72c81a0 (diff) |
Add basic support for properties references (a missing feature).
While it is far from complete, it does fix the following <rdar://problem/5967199> clang on xcode: error: member reference is not to a structure or union
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@51719 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/AST/ExprObjC.h | 35 | ||||
-rw-r--r-- | include/clang/AST/StmtNodes.def | 7 | ||||
-rw-r--r-- | lib/AST/Expr.cpp | 9 | ||||
-rw-r--r-- | lib/AST/StmtPrinter.cpp | 8 | ||||
-rw-r--r-- | lib/AST/StmtSerialization.cpp | 15 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 30 |
6 files changed, 101 insertions, 3 deletions
diff --git a/include/clang/AST/ExprObjC.h b/include/clang/AST/ExprObjC.h index 3242d25ecf..d00cb9a9a6 100644 --- a/include/clang/AST/ExprObjC.h +++ b/include/clang/AST/ExprObjC.h @@ -189,6 +189,41 @@ public: static ObjCIvarRefExpr* CreateImpl(llvm::Deserializer& D, ASTContext& C); }; +/// ObjCPropertyRefExpr - A reference to an ObjC property. +class ObjCPropertyRefExpr : public Expr { + class Decl *D; // an ObjCMethodDecl or ObjCPropertyDecl + SourceLocation Loc; + Expr *Base; + +public: + ObjCPropertyRefExpr(Decl *d, QualType t, SourceLocation l, Expr *base) : + Expr(ObjCPropertyRefExprClass, t), D(d), Loc(l), Base(base) {} + + Decl *getDecl() { return D; } + const Decl *getDecl() const { return D; } + + virtual SourceRange getSourceRange() const { + return SourceRange(getBase()->getLocStart(), Loc); + } + const Expr *getBase() const { return Base; } + Expr *getBase() { return Base; } + void setBase(Expr * base) { Base = base; } + + SourceLocation getLocation() const { return Loc; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == ObjCPropertyRefExprClass; + } + static bool classof(const ObjCPropertyRefExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); + + virtual void EmitImpl(llvm::Serializer& S) const; + static ObjCPropertyRefExpr* CreateImpl(llvm::Deserializer& D, ASTContext& C); +}; + class ObjCMessageExpr : public Expr { enum { RECEIVER=0, ARGS_START=1 }; diff --git a/include/clang/AST/StmtNodes.def b/include/clang/AST/StmtNodes.def index 65ce33b456..915dc263ff 100644 --- a/include/clang/AST/StmtNodes.def +++ b/include/clang/AST/StmtNodes.def @@ -100,12 +100,13 @@ STMT(72, ObjCMessageExpr , Expr) STMT(73, ObjCSelectorExpr , Expr) STMT(74, ObjCProtocolExpr , Expr) STMT(75, ObjCIvarRefExpr , Expr) +STMT(76, ObjCPropertyRefExpr , Expr) // Clang Extensions. -STMT(76, OverloadExpr , Expr) -STMT(77, ShuffleVectorExpr , Expr) +STMT(77, OverloadExpr , Expr) +STMT(78, ShuffleVectorExpr , Expr) -LAST_EXPR(77) +LAST_EXPR(78) #undef STMT #undef FIRST_STMT diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 502dd3b8e5..eb9add9e12 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -1187,6 +1187,15 @@ Stmt::child_iterator ObjCIvarRefExpr::child_end() { return reinterpret_cast<Stmt**>(&Base)+1; } +// ObjCIvarRefExpr +Stmt::child_iterator ObjCPropertyRefExpr::child_begin() { + return reinterpret_cast<Stmt**>(&Base); +} + +Stmt::child_iterator ObjCPropertyRefExpr::child_end() { + return reinterpret_cast<Stmt**>(&Base)+1; +} + // PreDefinedExpr Stmt::child_iterator PreDefinedExpr::child_begin() { return child_iterator(); } Stmt::child_iterator PreDefinedExpr::child_end() { return child_iterator(); } diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp index b55869b082..d52f48ed21 100644 --- a/lib/AST/StmtPrinter.cpp +++ b/lib/AST/StmtPrinter.cpp @@ -484,6 +484,14 @@ void StmtPrinter::VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node) { OS << Node->getDecl()->getName(); } +void StmtPrinter::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *Node) { + if (Node->getBase()) { + PrintExpr(Node->getBase()); + OS << "."; + } + // FIXME: OS << Node->getDecl()->getName(); +} + void StmtPrinter::VisitPreDefinedExpr(PreDefinedExpr *Node) { switch (Node->getIdentType()) { default: diff --git a/lib/AST/StmtSerialization.cpp b/lib/AST/StmtSerialization.cpp index 1e5229e26a..25e9514db1 100644 --- a/lib/AST/StmtSerialization.cpp +++ b/lib/AST/StmtSerialization.cpp @@ -988,6 +988,21 @@ ObjCIvarRefExpr* ObjCIvarRefExpr::CreateImpl(Deserializer& D, ASTContext& C) { return dr; } +void ObjCPropertyRefExpr::EmitImpl(Serializer& S) const { + S.Emit(Loc); + S.Emit(getType()); + S.EmitPtr(getDecl()); +} + +ObjCPropertyRefExpr* ObjCPropertyRefExpr::CreateImpl(Deserializer& D, + ASTContext& C) { + SourceLocation Loc = SourceLocation::ReadVal(D); + QualType T = QualType::ReadVal(D); + ObjCPropertyRefExpr* dr = new ObjCPropertyRefExpr(NULL,T,Loc,0); + D.ReadPtr(dr->D,false); + return dr; +} + void ObjCMessageExpr::EmitImpl(Serializer& S) const { S.EmitBool(getReceiver() ? true : false); S.Emit(getType()); diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 04561f5f62..7f80203a00 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -605,6 +605,36 @@ ActOnMemberReferenceExpr(ExprTy *Base, SourceLocation OpLoc, if (ObjCIvarDecl *IV = IFace->lookupInstanceVariable(&Member, clsDeclared)) return new ObjCIvarRefExpr(IV, IV->getType(), MemberLoc, BaseExpr, OpKind==tok::arrow); + } else if (isObjCObjectPointerType(BaseType)) { + PointerType *pointerType = static_cast<PointerType*>(BaseType.getTypePtr()); + BaseType = pointerType->getPointeeType(); + ObjCInterfaceDecl *IFace; + if (isa<ObjCInterfaceType>(BaseType.getCanonicalType())) + IFace = dyn_cast<ObjCInterfaceType>(BaseType)->getDecl(); + else + IFace = dyn_cast<ObjCQualifiedInterfaceType>(BaseType)->getDecl(); + ObjCInterfaceDecl *clsDeclared; + if (ObjCIvarDecl *IV = IFace->lookupInstanceVariable(&Member, clsDeclared)) + return new ObjCIvarRefExpr(IV, IV->getType(), MemberLoc, BaseExpr, + OpKind==tok::arrow); + // Check for properties. + if (OpKind==tok::period) { + // Before we look for explicit property declarations, we check for + // nullary methods (which allow '.' notation). + Selector Sel = PP.getSelectorTable().getNullarySelector(&Member); + ObjCMethodDecl *MD = IFace->lookupInstanceMethod(Sel); + if (MD) + return new ObjCPropertyRefExpr(MD, MD->getResultType(), + MemberLoc, BaseExpr); + // FIXME: Need to deal with setter methods that take 1 argument. E.g.: + // @interface NSBundle : NSObject {} + // - (NSString *)bundlePath; + // - (void)setBundlePath:(NSString *)x; + // @end + // void someMethod() { frameworkBundle.bundlePath = 0; } + // + // FIXME: lookup explicit properties... + } } return Diag(OpLoc, diag::err_typecheck_member_reference_structUnion, SourceRange(MemberLoc)); |