Several things...

- Implement RewritePropertySetter(). While the routine is simple, there were some tricky changes to RewriteFunctionBodyOrGlobalInitializer(), the main rewriter loop. It also required some additional instance data to distinguish setters from getters, as well as some changes to RewritePropertyGetter().

- Implement FIXME: for pretty printing ObjCPropertyRefExpr's.

- Changed ObjCPropertyRefExpr::getSourceRange() to point to the end of the property name (not the beginning). Also made a minor name change from "Loc"->"IdLoc" (to make it clear the Loc does not point to the ".").
 

llvm-svn: 60540
This commit is contained in:
Steve Naroff 2008-12-04 16:24:46 +00:00
parent 2c4efe68ea
commit 4588d0f060
4 changed files with 86 additions and 27 deletions

View File

@ -104,8 +104,10 @@ namespace {
llvm::DenseMap<BlockExpr *, std::string> RewrittenBlockExprs;
// This maps a synthesized message expr back to the original property.
llvm::DenseMap<Stmt *, ObjCPropertyRefExpr *> PropMsgExprs;
// This maps a property to it's assignment statement.
llvm::DenseMap<ObjCPropertyRefExpr *, BinaryOperator *> PropSetters;
// This maps a property to the stmt it was rewritten to.
llvm::DenseMap<ObjCPropertyRefExpr *, Stmt *> PropGetters;
FunctionDecl *CurFunctionDef;
VarDecl *GlobalVarDecl;
@ -194,10 +196,12 @@ namespace {
// Expression Rewriting.
Stmt *RewriteFunctionBodyOrGlobalInitializer(Stmt *S);
void CollectPropertySetters(Stmt *S);
Stmt *RewriteAtEncode(ObjCEncodeExpr *Exp);
Stmt *RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV, SourceLocation OrigStart);
Stmt *RewritePropertyRefExpr(ObjCPropertyRefExpr *PropRefExpr);
Stmt *RewritePropertySetter(BinaryOperator *BinOp, ObjCPropertyRefExpr *PRE);
Stmt *RewritePropertyGetter(ObjCPropertyRefExpr *PropRefExpr);
Stmt *RewritePropertySetter(BinaryOperator *BinOp, Expr *newStmt);
Stmt *RewriteAtSelector(ObjCSelectorExpr *Exp);
Stmt *RewriteMessageExpr(ObjCMessageExpr *Exp);
Stmt *RewriteObjCStringLiteral(ObjCStringLiteral *Exp);
@ -989,13 +993,35 @@ void RewriteObjC::RewriteInterfaceDecl(ObjCInterfaceDecl *ClassDecl) {
ReplaceText(ClassDecl->getAtEndLoc(), 0, "// ", 3);
}
Stmt *RewriteObjC::RewritePropertySetter(BinaryOperator *BinOp,
ObjCPropertyRefExpr *PRE) {
// FIXME: Fill in the transform.
return BinOp;
Stmt *RewriteObjC::RewritePropertySetter(BinaryOperator *BinOp, Expr *newStmt) {
// Synthesize a ObjCMessageExpr from a ObjCPropertyRefExpr.
// This allows us to reuse all the fun and games in SynthMessageExpr().
ObjCPropertyRefExpr *PropRefExpr = dyn_cast<ObjCPropertyRefExpr>(BinOp->getLHS());
ObjCMessageExpr *MsgExpr;
ObjCPropertyDecl *PDecl = PropRefExpr->getProperty();
llvm::SmallVector<Expr *, 1> ExprVec;
ExprVec.push_back(newStmt);
MsgExpr = new ObjCMessageExpr(PropRefExpr->getBase(),
PDecl->getSetterName(), PDecl->getType(),
PDecl->getSetterMethodDecl(),
SourceLocation(), SourceLocation(),
&ExprVec[0], 1);
Stmt *ReplacingStmt = SynthMessageExpr(MsgExpr);
// Now do the actual rewrite.
ReplaceStmt(BinOp, ReplacingStmt);
delete BinOp;
delete MsgExpr;
return ReplacingStmt;
}
Stmt *RewriteObjC::RewritePropertyRefExpr(ObjCPropertyRefExpr *PropRefExpr) {
Stmt *RewriteObjC::RewritePropertyGetter(ObjCPropertyRefExpr *PropRefExpr) {
Stmt *ReplacingStmt = PropGetters[PropRefExpr];
if (ReplacingStmt)
return ReplacingStmt; // We can't rewrite the same property twice.
// Synthesize a ObjCMessageExpr from a ObjCPropertyRefExpr.
// This allows us to reuse all the fun and games in SynthMessageExpr().
ObjCMessageExpr *MsgExpr;
@ -1007,11 +1033,11 @@ Stmt *RewriteObjC::RewritePropertyRefExpr(ObjCPropertyRefExpr *PropRefExpr) {
SourceLocation(), SourceLocation(),
0, 0);
Stmt *ReplacingStmt = SynthMessageExpr(MsgExpr);
// Now do the actual rewrite.
ReplacingStmt = SynthMessageExpr(MsgExpr);
ReplaceStmt(PropRefExpr, ReplacingStmt);
PropMsgExprs[ReplacingStmt] = PropRefExpr;
PropGetters[PropRefExpr] = ReplacingStmt;
// delete PropRefExpr; elsewhere...
delete MsgExpr;
@ -2410,6 +2436,7 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp) {
Stmt *RewriteObjC::RewriteMessageExpr(ObjCMessageExpr *Exp) {
Stmt *ReplacingStmt = SynthMessageExpr(Exp);
//ReplacingStmt->dump();
// Now do the actual rewrite.
ReplaceStmt(Exp, ReplacingStmt);
@ -3980,6 +4007,27 @@ Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp) {
// Function Body / Expression rewriting
//===----------------------------------------------------------------------===//
// This is run as a first "pass" prior to RewriteFunctionBodyOrGlobalInitializer().
// The allows the main rewrite loop to associate all ObjCPropertyRefExprs with
// their respective BinaryOperator. Without this knowledge, we'd need to rewrite
// the ObjCPropertyRefExpr twice (once as a getter, and later as a setter).
// Since the rewriter isn't capable of rewriting rewritten code, it's important
// we get this right.
void RewriteObjC::CollectPropertySetters(Stmt *S) {
// Perform a bottom up traversal of all children.
for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
CI != E; ++CI)
if (*CI)
CollectPropertySetters(*CI);
if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(S)) {
if (BinOp->isAssignmentOp()) {
if (ObjCPropertyRefExpr *PRE = dyn_cast<ObjCPropertyRefExpr>(BinOp->getLHS()))
PropSetters[PRE] = BinOp;
}
}
}
Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) {
if (isa<SwitchStmt>(S) || isa<WhileStmt>(S) ||
isa<DoStmt>(S) || isa<ForStmt>(S))
@ -4020,13 +4068,15 @@ Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) {
if (ObjCIvarRefExpr *IvarRefExpr = dyn_cast<ObjCIvarRefExpr>(S))
return RewriteObjCIvarRefExpr(IvarRefExpr, OrigStmtRange.getBegin());
if (ObjCPropertyRefExpr *PropRefExpr = dyn_cast<ObjCPropertyRefExpr>(S))
return RewritePropertyRefExpr(PropRefExpr);
if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(S)) {
if (BinOp->isAssignmentOp()) {
if (ObjCPropertyRefExpr *PRE = PropMsgExprs[BinOp->getLHS()])
return RewritePropertySetter(BinOp, PRE);
if (ObjCPropertyRefExpr *PropRefExpr = dyn_cast<ObjCPropertyRefExpr>(S)) {
BinaryOperator *BinOp = PropSetters[PropRefExpr];
if (BinOp) {
// Because the rewriter doesn't allow us to rewrite rewritten code,
// we need to rewrite the right hand side prior to rewriting the setter.
Stmt *newStmt = RewriteFunctionBodyOrGlobalInitializer(BinOp->getRHS());
return RewritePropertySetter(BinOp, dyn_cast<Expr>(newStmt));
} else {
return RewritePropertyGetter(PropRefExpr);
}
}
if (ObjCSelectorExpr *AtSelector = dyn_cast<ObjCSelectorExpr>(S))
@ -4036,6 +4086,7 @@ Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) {
return RewriteObjCStringLiteral(AtString);
if (ObjCMessageExpr *MessExpr = dyn_cast<ObjCMessageExpr>(S)) {
#if 0
// Before we rewrite it, put the original message expression in a comment.
SourceLocation startLoc = MessExpr->getLocStart();
SourceLocation endLoc = MessExpr->getLocEnd();
@ -4053,6 +4104,7 @@ Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) {
// InsertText(startLoc, messString.c_str(), messString.size());
// Tried this, but it didn't work either...
// ReplaceText(startLoc, 0, messString.c_str(), messString.size());
#endif
return RewriteMessageExpr(MessExpr);
}
@ -4162,7 +4214,9 @@ void RewriteObjC::HandleDeclInMainFile(Decl *D) {
if (Stmt *Body = FD->getBody()) {
CurFunctionDef = FD;
CollectPropertySetters(Body);
FD->setBody(RewriteFunctionBodyOrGlobalInitializer(Body));
// This synthesizes and inserts the block "impl" struct, invoke function,
// and any copy/dispose helper functions.
InsertBlockLiteralsWithinFunction(FD);
@ -4174,6 +4228,7 @@ void RewriteObjC::HandleDeclInMainFile(Decl *D) {
if (Stmt *Body = MD->getBody()) {
//Body->dump();
CurMethodDef = MD;
CollectPropertySetters(Body);
MD->setBody(RewriteFunctionBodyOrGlobalInitializer(Body));
InsertBlockLiteralsWithinMethod(MD);
CurMethodDef = 0;
@ -4199,6 +4254,7 @@ void RewriteObjC::HandleDeclInMainFile(Decl *D) {
}
if (VD->getInit()) {
GlobalVarDecl = VD;
CollectPropertySetters(VD->getInit());
RewriteFunctionBodyOrGlobalInitializer(VD->getInit());
SynthesizeBlockLiterals(VD->getTypeSpecStartLoc(),
VD->getNameAsCString());

View File

@ -15,6 +15,7 @@
#define LLVM_CLANG_AST_EXPROBJC_H
#include "clang/AST/Expr.h"
#include "clang/AST/DeclObjC.h"
#include "clang/Basic/IdentifierTable.h"
namespace clang {
@ -200,26 +201,28 @@ public:
class ObjCPropertyRefExpr : public Expr {
private:
ObjCPropertyDecl *AsProperty;
SourceLocation Loc;
SourceLocation IdLoc;
Stmt *Base;
public:
ObjCPropertyRefExpr(ObjCPropertyDecl *PD, QualType t,
SourceLocation l, Expr *base)
: Expr(ObjCPropertyRefExprClass, t), AsProperty(PD), Loc(l), Base(base) {
: Expr(ObjCPropertyRefExprClass, t), AsProperty(PD), IdLoc(l), Base(base) {
}
ObjCPropertyDecl *getProperty() const {
return AsProperty;
}
virtual SourceRange getSourceRange() const {
return SourceRange(getBase()->getLocStart(), Loc);
virtual SourceRange getSourceRange() const {
unsigned IDLen = AsProperty->getIdentifier()->getLength();
return SourceRange(getBase()->getLocStart(),
IdLoc.getFileLocWithOffset(IDLen-1));
}
const Expr *getBase() const { return cast<Expr>(Base); }
Expr *getBase() { return cast<Expr>(Base); }
void setBase(Expr * base) { Base = base; }
SourceLocation getLocation() const { return Loc; }
SourceLocation getLocation() const { return IdLoc; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == ObjCPropertyRefExprClass;

View File

@ -499,7 +499,7 @@ void StmtPrinter::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *Node) {
PrintExpr(Node->getBase());
OS << ".";
}
// FIXME: OS << Node->getDecl()->getName();
OS << Node->getProperty()->getNameAsCString();
}
void StmtPrinter::VisitObjCKVCRefExpr(ObjCKVCRefExpr *Node) {

View File

@ -1165,7 +1165,7 @@ ObjCIvarRefExpr* ObjCIvarRefExpr::CreateImpl(Deserializer& D, ASTContext& C) {
}
void ObjCPropertyRefExpr::EmitImpl(Serializer& S) const {
S.Emit(Loc);
S.Emit(IdLoc);
S.Emit(getType());
S.EmitPtr(getProperty());
}