aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AST/StmtPrinter.cpp4
-rw-r--r--Sema/SemaExpr.cpp17
-rw-r--r--include/clang/AST/Expr.h10
-rw-r--r--test/Sema/static-ivar-ref-1.m16
4 files changed, 42 insertions, 5 deletions
diff --git a/AST/StmtPrinter.cpp b/AST/StmtPrinter.cpp
index ae8bb1ae57..d96a0486cf 100644
--- a/AST/StmtPrinter.cpp
+++ b/AST/StmtPrinter.cpp
@@ -383,6 +383,10 @@ void StmtPrinter::VisitDeclRefExpr(DeclRefExpr *Node) {
}
void StmtPrinter::VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node) {
+ if (Node->getBase()) {
+ PrintExpr(Node->getBase());
+ OS << (Node->isArrow() ? "->" : ".");
+ }
OS << Node->getDecl()->getName();
}
diff --git a/Sema/SemaExpr.cpp b/Sema/SemaExpr.cpp
index d51a29631b..8f816e67ef 100644
--- a/Sema/SemaExpr.cpp
+++ b/Sema/SemaExpr.cpp
@@ -519,9 +519,20 @@ ActOnMemberReferenceExpr(ExprTy *Base, SourceLocation OpLoc,
if (ret.isNull())
return true;
return new OCUVectorElementExpr(ret, BaseExpr, Member, MemberLoc);
- } else
- return Diag(OpLoc, diag::err_typecheck_member_reference_structUnion,
- SourceRange(MemberLoc));
+ } else if (BaseType->isObjcInterfaceType()) {
+ ObjcInterfaceDecl *IFace;
+ if (isa<ObjcInterfaceType>(BaseType.getCanonicalType()))
+ IFace = dyn_cast<ObjcInterfaceType>(BaseType)->getDecl();
+ else
+ IFace = dyn_cast<ObjcQualifiedInterfaceType>(BaseType)
+ ->getInterfaceType()->getDecl();
+ ObjcInterfaceDecl *clsDeclared;
+ if (ObjcIvarDecl *IV = IFace->lookupInstanceVariable(&Member, clsDeclared))
+ return new ObjCIvarRefExpr(IV, IV->getType(), MemberLoc, BaseExpr,
+ OpKind==tok::arrow);
+ }
+ return Diag(OpLoc, diag::err_typecheck_member_reference_structUnion,
+ SourceRange(MemberLoc));
}
/// ActOnCallExpr - Handle a call to Fn with the specified array of arguments.
diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h
index 0a3caa7f88..b3279a0429 100644
--- a/include/clang/AST/Expr.h
+++ b/include/clang/AST/Expr.h
@@ -1234,13 +1234,19 @@ class ObjCProtocolExpr : public Expr {
class ObjCIvarRefExpr : public Expr {
class ObjcIvarDecl *D;
SourceLocation Loc;
+ Expr *Base;
+ bool IsArrow; // True if this is "X->F", false if this is "X.F".
+
public:
- ObjCIvarRefExpr(ObjcIvarDecl *d, QualType t, SourceLocation l) :
- Expr(ObjCIvarRefExprClass, t), D(d), Loc(l) {}
+ ObjCIvarRefExpr(ObjcIvarDecl *d, QualType t, SourceLocation l, Expr *base=0,
+ bool arrow = false) :
+ Expr(ObjCIvarRefExprClass, t), D(d), Loc(l), Base(base), IsArrow(arrow) {}
ObjcIvarDecl *getDecl() { return D; }
const ObjcIvarDecl *getDecl() const { return D; }
virtual SourceRange getSourceRange() const { return SourceRange(Loc); }
+ Expr *const getBase() const { return Base; }
+ const bool isArrow() const { return IsArrow; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == ObjCIvarRefExprClass;
diff --git a/test/Sema/static-ivar-ref-1.m b/test/Sema/static-ivar-ref-1.m
new file mode 100644
index 0000000000..d01a7fb6da
--- /dev/null
+++ b/test/Sema/static-ivar-ref-1.m
@@ -0,0 +1,16 @@
+// RUN: clang -ast-print %s
+
+@interface current
+{
+ int ivar;
+ int ivar1;
+ int ivar2;
+}
+@end
+
+current *pc;
+
+int foo()
+{
+ return pc->ivar2 + (*pc).ivar + pc->ivar1;
+}