зеркало из https://github.com/microsoft/clang-1.git
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
This commit is contained in:
Родитель
54eec4c00d
Коммит
ae7840776d
|
@ -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 };
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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(); }
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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));
|
||||
|
|
Загрузка…
Ссылка в новой задаче