]> granicus.if.org Git - clang/commitdiff
Several things...
authorSteve Naroff <snaroff@apple.com>
Thu, 4 Dec 2008 16:24:46 +0000 (16:24 +0000)
committerSteve Naroff <snaroff@apple.com>
Thu, 4 Dec 2008 16:24:46 +0000 (16:24 +0000)
- 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 ".").

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@60540 91177308-0d34-0410-b5e6-96231b3b80d8

Driver/RewriteObjC.cpp
include/clang/AST/ExprObjC.h
lib/AST/StmtPrinter.cpp
lib/AST/StmtSerialization.cpp

index f558d7d93097f1f8e10b090109c1964a1f726f04..54882c392717387362157eb8f70b6618bbe3fe44 100644 (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());
index 25a3b5fcec85efa16bf76be76ed56ed259ed5b70..04b5d754d9db3ee598db35b304e40dd2780a58e1 100644 (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; 
index 8cd79a8347d60949c4a7ccc3bed7c6fa0ea20d7d..2e54777b94f1ea1df08737f10f9684df9a06babb 100644 (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) {
index 78a2cbcaa7683c1f1e4b5a8cdb50b3b94ac9eaf6..6ebaca1c8e5535ebb3fb61749c389ecd40d0b41f 100644 (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());
 }