[cfe-commits] r60760 - in /cfe/trunk: Driver/RewriteObjC.cpp test/Rewriter/properties.m

Steve Naroff snaroff at apple.com
Tue Dec 9 04:56:40 PST 2008


Author: snaroff
Date: Tue Dec  9 06:56:34 2008
New Revision: 60760

URL: http://llvm.org/viewvc/llvm-project?rev=60760&view=rev
Log:
Fix <rdar://problem/6429113> clang ObjC rewriter: crash rewriting file with Blocks and properties

More fancy footwork to cope with rewriting property 'setters'.

Modified:
    cfe/trunk/Driver/RewriteObjC.cpp
    cfe/trunk/test/Rewriter/properties.m

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

==============================================================================
--- cfe/trunk/Driver/RewriteObjC.cpp (original)
+++ cfe/trunk/Driver/RewriteObjC.cpp Tue Dec  9 06:56:34 2008
@@ -120,6 +120,8 @@
     FunctionDecl *CurFunctionDef;
     VarDecl *GlobalVarDecl;
     
+    bool DisableReplaceStmt;
+    
     static const int OBJC_ABI_VERSION =7 ;
   public:
     virtual void Initialize(ASTContext &context);
@@ -146,6 +148,9 @@
       if (ReplacingStmt)
         return; // We can't rewrite the same node twice.
 
+      if (DisableReplaceStmt)
+        return; // Used when rewriting the assignment of a property setter.
+
       // If replacement succeeded or warning disabled return with no warning.
       if (!Rewrite.ReplaceStmt(Old, New)) {
         ReplacedNodes[Old] = New;
@@ -156,7 +161,32 @@
       Diags.Report(Context->getFullLoc(Old->getLocStart()), RewriteFailedDiag)
                    << Old->getSourceRange();
     }
-    
+
+    void ReplaceStmtWithRange(Stmt *Old, Stmt *New, SourceRange SrcRange) {
+      // Measaure the old text.
+      int Size = Rewrite.getRangeSize(SrcRange);
+      if (Size == -1) {
+        Diags.Report(Context->getFullLoc(Old->getLocStart()), RewriteFailedDiag)
+                     << Old->getSourceRange();
+        return;
+      }
+      // Get the new text.
+      std::string SStr;
+      llvm::raw_string_ostream S(SStr);
+      New->printPretty(S);
+      const std::string &Str = S.str();
+
+      // If replacement succeeded or warning disabled return with no warning.
+      if (!Rewrite.ReplaceText(SrcRange.getBegin(), Size, &Str[0], Str.size())) {
+        ReplacedNodes[Old] = New;
+        return;
+      }
+      if (SilenceRewriteMacroWarning)
+        return;
+      Diags.Report(Context->getFullLoc(Old->getLocStart()), RewriteFailedDiag)
+                   << Old->getSourceRange();
+    }
+
     void InsertText(SourceLocation Loc, const char *StrData, unsigned StrLen,
                     bool InsertAfter = true) {
       // If insertion succeeded or warning disabled return with no warning.
@@ -220,7 +250,8 @@
     Stmt *RewriteAtEncode(ObjCEncodeExpr *Exp);
     Stmt *RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV, SourceLocation OrigStart);
     Stmt *RewritePropertyGetter(ObjCPropertyRefExpr *PropRefExpr);
-    Stmt *RewritePropertySetter(BinaryOperator *BinOp, Expr *newStmt);
+    Stmt *RewritePropertySetter(BinaryOperator *BinOp, Expr *newStmt, 
+                                SourceRange SrcRange);
     Stmt *RewriteAtSelector(ObjCSelectorExpr *Exp);
     Stmt *RewriteMessageExpr(ObjCMessageExpr *Exp);
     Stmt *RewriteObjCStringLiteral(ObjCStringLiteral *Exp);
@@ -407,6 +438,7 @@
   NSStringRecord = 0;
   CurMethodDef = 0;
   CurFunctionDef = 0;
+  GlobalVarDecl = 0;
   SuperStructDecl = 0;
   ConstantStringDecl = 0;
   BcLabelCount = 0;
@@ -414,7 +446,8 @@
   NumObjCStringLiterals = 0;
   PropParentMap = 0;
   CurrentBody = 0;
-
+  DisableReplaceStmt = false;
+  
   // Get the ID and start/end of the main file.
   MainFileID = SM->getMainFileID();
   const llvm::MemoryBuffer *MainBuf = SM->getBuffer(MainFileID);
@@ -1019,7 +1052,8 @@
   ReplaceText(ClassDecl->getAtEndLoc(), 0, "// ", 3);
 }
 
-Stmt *RewriteObjC::RewritePropertySetter(BinaryOperator *BinOp, Expr *newStmt) {
+Stmt *RewriteObjC::RewritePropertySetter(BinaryOperator *BinOp, Expr *newStmt,
+                                         SourceRange SrcRange) {
   // 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());
@@ -1042,7 +1076,7 @@
   Stmt *ReplacingStmt = SynthMessageExpr(MsgExpr);
   
   // Now do the actual rewrite.
-  ReplaceStmt(BinOp, ReplacingStmt);
+  ReplaceStmtWithRange(BinOp, ReplacingStmt, SrcRange);
   delete BinOp;
   delete MsgExpr;
   return ReplacingStmt;
@@ -4134,7 +4168,15 @@
     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.
+      DisableReplaceStmt = true;
+      // Save the source range. Even if we disable the replacement, the
+      // rewritten node will have been inserted into the tree. If the synthesized
+      // node is at the 'end', the rewriter will fail. Consider this:
+      //    self.errorHandler = handler ? handler : 
+      //              ^(NSURL *errorURL, NSError *error) { return (BOOL)1; };
+      SourceRange SrcRange = BinOp->getSourceRange();
       Stmt *newStmt = RewriteFunctionBodyOrGlobalInitializer(BinOp->getRHS());
+      DisableReplaceStmt = false;
       //
       // Unlike the main iterator, we explicily avoid changing 'BinOp'. If
       // we changed the RHS of BinOp, the rewriter would fail (since it needs
@@ -4167,7 +4209,7 @@
       // This implies the Rewrite* routines can no longer delete the original 
       // node. As a result, we now leak the original AST nodes.
       //
-      return RewritePropertySetter(BinOp, dyn_cast<Expr>(newStmt));
+      return RewritePropertySetter(BinOp, dyn_cast<Expr>(newStmt), SrcRange);
     } else {
       return RewritePropertyGetter(PropRefExpr);
     }

Modified: cfe/trunk/test/Rewriter/properties.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Rewriter/properties.m?rev=60760&r1=60759&r2=60760&view=diff

==============================================================================
--- cfe/trunk/test/Rewriter/properties.m (original)
+++ cfe/trunk/test/Rewriter/properties.m Tue Dec  9 06:56:34 2008
@@ -47,6 +47,7 @@
     obj1.i = (obj2.rrrr);
     [obj1 setI:[obj2 rrrr]];
     obj1.i = [obj2 rrrr];
+    obj1.i = 3 + [obj2 rrrr];
     i = obj1.o.i;
     obj1.o.i = 77;
 }





More information about the cfe-commits mailing list