[cfe-commits] r60540 - in /cfe/trunk: Driver/RewriteObjC.cpp include/clang/AST/ExprObjC.h lib/AST/StmtPrinter.cpp lib/AST/StmtSerialization.cpp

Steve Naroff snaroff at apple.com
Thu Dec 4 08:24:48 PST 2008


Author: snaroff
Date: Thu Dec  4 10:24:46 2008
New Revision: 60540

URL: http://llvm.org/viewvc/llvm-project?rev=60540&view=rev
Log:
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 ".").
 

Modified:
    cfe/trunk/Driver/RewriteObjC.cpp
    cfe/trunk/include/clang/AST/ExprObjC.h
    cfe/trunk/lib/AST/StmtPrinter.cpp
    cfe/trunk/lib/AST/StmtSerialization.cpp

Modified: cfe/trunk/Driver/RewriteObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Driver/RewriteObjC.cpp?rev=60540&r1=60539&r2=60540&view=diff

==============================================================================
--- cfe/trunk/Driver/RewriteObjC.cpp (original)
+++ cfe/trunk/Driver/RewriteObjC.cpp Thu Dec  4 10:24:46 2008
@@ -104,8 +104,10 @@
 
     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 @@
     
     // 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 @@
   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 @@
                                 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::RewriteMessageExpr(ObjCMessageExpr *Exp) {
   Stmt *ReplacingStmt = SynthMessageExpr(Exp);
   
+  //ReplacingStmt->dump();
   // Now do the actual rewrite.
   ReplaceStmt(Exp, ReplacingStmt);
   
@@ -3980,6 +4007,27 @@
 // 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 @@
   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 @@
     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 @@
     // 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 @@
 
     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 @@
     if (Stmt *Body = MD->getBody()) {
       //Body->dump();
       CurMethodDef = MD;
+      CollectPropertySetters(Body);
       MD->setBody(RewriteFunctionBodyOrGlobalInitializer(Body));
       InsertBlockLiteralsWithinMethod(MD);
       CurMethodDef = 0;
@@ -4199,6 +4254,7 @@
     }
     if (VD->getInit()) {
       GlobalVarDecl = VD;
+      CollectPropertySetters(VD->getInit());
       RewriteFunctionBodyOrGlobalInitializer(VD->getInit());
       SynthesizeBlockLiterals(VD->getTypeSpecStartLoc(), 
                               VD->getNameAsCString());

Modified: cfe/trunk/include/clang/AST/ExprObjC.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ExprObjC.h?rev=60540&r1=60539&r2=60540&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/ExprObjC.h (original)
+++ cfe/trunk/include/clang/AST/ExprObjC.h Thu Dec  4 10:24:46 2008
@@ -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 @@
 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; 

Modified: cfe/trunk/lib/AST/StmtPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtPrinter.cpp?rev=60540&r1=60539&r2=60540&view=diff

==============================================================================
--- cfe/trunk/lib/AST/StmtPrinter.cpp (original)
+++ cfe/trunk/lib/AST/StmtPrinter.cpp Thu Dec  4 10:24:46 2008
@@ -499,7 +499,7 @@
     PrintExpr(Node->getBase());
     OS << ".";
   }
-  // FIXME: OS << Node->getDecl()->getName();
+  OS << Node->getProperty()->getNameAsCString();
 }
 
 void StmtPrinter::VisitObjCKVCRefExpr(ObjCKVCRefExpr *Node) {

Modified: cfe/trunk/lib/AST/StmtSerialization.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtSerialization.cpp?rev=60540&r1=60539&r2=60540&view=diff

==============================================================================
--- cfe/trunk/lib/AST/StmtSerialization.cpp (original)
+++ cfe/trunk/lib/AST/StmtSerialization.cpp Thu Dec  4 10:24:46 2008
@@ -1165,7 +1165,7 @@
 }
 
 void ObjCPropertyRefExpr::EmitImpl(Serializer& S) const {
-  S.Emit(Loc);
+  S.Emit(IdLoc);
   S.Emit(getType());
   S.EmitPtr(getProperty());
 }





More information about the cfe-commits mailing list