[cfe-commits] r60700 - in /cfe/trunk: Driver/RewriteObjC.cpp test/Rewriter/properties.m
Steve Naroff
snaroff at apple.com
Mon Dec 8 08:43:48 PST 2008
Author: snaroff
Date: Mon Dec 8 10:43:47 2008
New Revision: 60700
URL: http://llvm.org/viewvc/llvm-project?rev=60700&view=rev
Log:
Handle chained/nested property 'getters' (obj.p1.p2.p3).
This is a follow-up to fixing <rdar://problem/6213955> clang ObjC rewriter: rewriter doesn't appear to support @property and @synthesize.
Added:
cfe/trunk/test/Rewriter/properties.m
Modified:
cfe/trunk/Driver/RewriteObjC.cpp
Modified: cfe/trunk/Driver/RewriteObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Driver/RewriteObjC.cpp?rev=60700&r1=60699&r2=60700&view=diff
==============================================================================
--- cfe/trunk/Driver/RewriteObjC.cpp (original)
+++ cfe/trunk/Driver/RewriteObjC.cpp Mon Dec 8 10:43:47 2008
@@ -16,6 +16,7 @@
#include "clang/AST/AST.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/TranslationUnit.h"
+#include "clang/AST/ParentMap.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/Diagnostic.h"
@@ -107,6 +108,10 @@
// This maps a property to it's assignment statement.
llvm::DenseMap<ObjCPropertyRefExpr *, BinaryOperator *> PropSetters;
+ // This maps a property to it's synthesied message expression.
+ // This allows us to rewrite chained getters (e.g. o.a.b.c).
+ llvm::DenseMap<ObjCPropertyRefExpr *, Stmt *> PropGetters;
+
// This maps an original source AST to it's rewritten form. This allows
// us to avoid rewriting the same node twice (which is very uncommon).
// This is needed to support some of the exotic property rewriting.
@@ -209,6 +214,9 @@
Stmt *RewriteFunctionBodyOrGlobalInitializer(Stmt *S);
void CollectPropertySetters(Stmt *S);
+ Stmt *CurrentBody;
+ ParentMap *PropParentMap; // created lazily.
+
Stmt *RewriteAtEncode(ObjCEncodeExpr *Exp);
Stmt *RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV, SourceLocation OrigStart);
Stmt *RewritePropertyGetter(ObjCPropertyRefExpr *PropRefExpr);
@@ -1016,7 +1024,13 @@
llvm::SmallVector<Expr *, 1> ExprVec;
ExprVec.push_back(newStmt);
- MsgExpr = new ObjCMessageExpr(PropRefExpr->getBase(),
+ Stmt *Receiver = PropRefExpr->getBase();
+ ObjCPropertyRefExpr *PRE = dyn_cast<ObjCPropertyRefExpr>(Receiver);
+ if (PRE && PropGetters[PRE]) {
+ // This allows us to handle chain/nested property getters.
+ Receiver = PropGetters[PRE];
+ }
+ MsgExpr = new ObjCMessageExpr(dyn_cast<Expr>(Receiver),
PDecl->getSetterName(), PDecl->getType(),
PDecl->getSetterMethodDecl(),
SourceLocation(), SourceLocation(),
@@ -1036,19 +1050,37 @@
ObjCMessageExpr *MsgExpr;
ObjCPropertyDecl *PDecl = PropRefExpr->getProperty();
- MsgExpr = new ObjCMessageExpr(PropRefExpr->getBase(),
+ Stmt *Receiver = PropRefExpr->getBase();
+
+ ObjCPropertyRefExpr *PRE = dyn_cast<ObjCPropertyRefExpr>(Receiver);
+ if (PRE && PropGetters[PRE]) {
+ // This allows us to handle chain/nested property getters.
+ Receiver = PropGetters[PRE];
+ }
+ MsgExpr = new ObjCMessageExpr(dyn_cast<Expr>(Receiver),
PDecl->getGetterName(), PDecl->getType(),
PDecl->getGetterMethodDecl(),
SourceLocation(), SourceLocation(),
0, 0);
Stmt *ReplacingStmt = SynthMessageExpr(MsgExpr);
-
- ReplaceStmt(PropRefExpr, ReplacingStmt);
-
- // delete PropRefExpr; elsewhere...
- delete MsgExpr;
- return ReplacingStmt;
+
+ if (!PropParentMap)
+ PropParentMap = new ParentMap(CurrentBody);
+
+ Stmt *Parent = PropParentMap->getParent(PropRefExpr);
+ if (Parent && isa<ObjCPropertyRefExpr>(Parent)) {
+ // We stash away the ReplacingStmt since actually doing the
+ // replacement/rewrite won't work for nested getters (e.g. obj.p.i)
+ PropGetters[PropRefExpr] = ReplacingStmt;
+ delete MsgExpr;
+ return PropRefExpr; // return the original...
+ } else {
+ ReplaceStmt(PropRefExpr, ReplacingStmt);
+ // delete PropRefExpr; elsewhere...
+ delete MsgExpr;
+ return ReplacingStmt;
+ }
}
Stmt *RewriteObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV,
@@ -4272,8 +4304,13 @@
if (Stmt *Body = FD->getBody()) {
CurFunctionDef = FD;
CollectPropertySetters(Body);
+ CurrentBody = Body;
FD->setBody(RewriteFunctionBodyOrGlobalInitializer(Body));
-
+ CurrentBody = 0;
+ if (PropParentMap) {
+ delete PropParentMap;
+ PropParentMap = 0;
+ }
// This synthesizes and inserts the block "impl" struct, invoke function,
// and any copy/dispose helper functions.
InsertBlockLiteralsWithinFunction(FD);
@@ -4283,10 +4320,15 @@
}
if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
if (Stmt *Body = MD->getBody()) {
- //Body->dump();
CurMethodDef = MD;
CollectPropertySetters(Body);
+ CurrentBody = Body;
MD->setBody(RewriteFunctionBodyOrGlobalInitializer(Body));
+ CurrentBody = 0;
+ if (PropParentMap) {
+ delete PropParentMap;
+ PropParentMap = 0;
+ }
InsertBlockLiteralsWithinMethod(MD);
CurMethodDef = 0;
}
@@ -4312,7 +4354,13 @@
if (VD->getInit()) {
GlobalVarDecl = VD;
CollectPropertySetters(VD->getInit());
+ CurrentBody = VD->getInit();
RewriteFunctionBodyOrGlobalInitializer(VD->getInit());
+ CurrentBody = 0;
+ if (PropParentMap) {
+ delete PropParentMap;
+ PropParentMap = 0;
+ }
SynthesizeBlockLiterals(VD->getTypeSpecStartLoc(),
VD->getNameAsCString());
GlobalVarDecl = 0;
Added: cfe/trunk/test/Rewriter/properties.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Rewriter/properties.m?rev=60700&view=auto
==============================================================================
--- cfe/trunk/test/Rewriter/properties.m (added)
+++ cfe/trunk/test/Rewriter/properties.m Mon Dec 8 10:43:47 2008
@@ -0,0 +1,53 @@
+// RUN: clang -rewrite-objc %s -o -
+
+ at interface Foo {
+ int i;
+ int rrrr;
+ Foo *o;
+}
+ at property int i;
+ at property(readonly) int rrrr;
+ at property int d;
+ at property(retain) Foo *o;
+
+- (void)foo;
+ at end
+
+ at implementation Foo
+ at synthesize i;
+ at synthesize rrrr;
+ at synthesize o;
+
+ at dynamic d;
+
+- (void)foo {
+ i = 99;
+}
+
+- (int)bar {
+ return i;
+}
+ at end
+
+ at interface Bar {
+}
+ at end
+
+ at implementation Bar
+
+static int func(int i);
+
+- (void)baz {
+ Foo *obj1, *obj2;
+ int i;
+ if (obj1.i == obj2.rrrr)
+ obj1.i = 33;
+ obj1.i = func(obj2.rrrr);
+ obj1.i = obj2.rrrr;
+ obj1.i = (obj2.rrrr);
+ [obj1 setI:[obj2 rrrr]];
+ obj1.i = [obj2 rrrr];
+ i = obj1.o.i;
+ obj1.o.i = 77;
+}
+ at end
More information about the cfe-commits
mailing list