[cfe-commits] r45760 - in /cfe/trunk: Driver/RewriteTest.cpp clang.xcodeproj/project.pbxproj test/Sema/rewrite-foreach-1.m

Fariborz Jahanian fjahanian at apple.com
Tue Jan 8 14:06:30 PST 2008


Author: fjahanian
Date: Tue Jan  8 16:06:28 2008
New Revision: 45760

URL: http://llvm.org/viewvc/llvm-project?rev=45760&view=rev
Log:
Patch to rewrite ObjC2's foreach-stmt.

Added:
    cfe/trunk/test/Sema/rewrite-foreach-1.m
Modified:
    cfe/trunk/Driver/RewriteTest.cpp
    cfe/trunk/clang.xcodeproj/project.pbxproj

Modified: cfe/trunk/Driver/RewriteTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Driver/RewriteTest.cpp?rev=45760&r1=45759&r2=45760&view=diff

==============================================================================
--- cfe/trunk/Driver/RewriteTest.cpp (original)
+++ cfe/trunk/Driver/RewriteTest.cpp Tue Jan  8 16:06:28 2008
@@ -121,8 +121,13 @@
                       "extern int objc_exception_match"
                       "(struct objc_class *, struct objc_object *, ...);\n"
                       "extern Protocol *objc_getProtocol(const char *);\n"
-                      "#include <objc/objc.h>\n";
-
+                      "#include <objc/objc.h>\n"
+                      "struct __objcFastEnumerationState {\n\t"
+                      "unsigned long state;\n\t"
+                      "id *itemsPtr;\n\t"
+                      "unsigned long *mutationsPtr;\n\t"
+                      "unsigned long extra[5];\n};\n";
+                      
       Rewrite.InsertText(SourceLocation::getFileLoc(MainFileID, 0), 
                          s, strlen(s));
     }
@@ -167,6 +172,9 @@
     Stmt *RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S);
     CallExpr *SynthesizeCallToFunctionDecl(FunctionDecl *FD, 
                                            Expr **args, unsigned nargs);
+    Stmt *SynthMessageExpr(ObjCMessageExpr *Exp);
+    void SynthCountByEnumWithState(std::string &buf);
+    
     void SynthMsgSendFunctionDecl();
     void SynthMsgSendSuperFunctionDecl();
     void SynthMsgSendStretFunctionDecl();
@@ -761,6 +769,25 @@
   return S;
 }
 
+/// SynthCountByEnumWithState - To print:
+/// ((unsigned int (*)
+///  (id, SEL, struct __objcFastEnumerationState *, id *, unsigned int))
+///  (void *)objc_msgSend)((id)l_collection, 
+///                        sel_registerName(
+///                          "countByEnumeratingWithState:objects:count:"), 
+///                        &enumState, 
+///                        (id *)items, (unsigned int)16)
+///
+void RewriteTest::SynthCountByEnumWithState(std::string &buf) {
+  buf += "((unsigned int (*) (id, SEL, struct __objcFastEnumerationState *, "
+  "id *, unsigned int))(void *)objc_msgSend)";
+  buf += "\n\t\t";
+  buf += "((id)l_collection,\n\t\t";
+  buf += "sel_registerName(\"countByEnumeratingWithState:objects:count:\"),";
+  buf += "\n\t\t";
+  buf += "&enumState, "
+         "(id *)items, (unsigned int)16)";
+}
 
 /// RewriteObjCTryStmt - Rewriter for ObjC2's feareach statement.
 ///  It rewrites:
@@ -768,30 +795,133 @@
  
 /// Into:
 /// {
-///   type elem;
-///   __objcFastEnumerationState enumState = { 0 };
+///   type elem; 
+///   struct __objcFastEnumerationState enumState = { 0 };
 ///   id items[16];
-///   unsigned long limit = [collection countByEnumeratingWithState:&enumState 
-///                                     objects:items count:16];
+///   id l_collection = (id)collection;
+///   unsigned long limit = [l_collection countByEnumeratingWithState:&enumState 
+///                                       objects:items count:16];
 /// if (limit) {
 ///   unsigned long startMutations = *enumState.mutationsPtr;
 ///   do {
 ///        unsigned long counter = 0;
 ///        do {
 ///             if (startMutations != *enumState.mutationsPtr) 
-///               objc_enumerationMutation(collection);
+///               objc_enumerationMutation(l_collection);
 ///             elem = enumState.itemsPtr[counter++];
 ///             stmts;
 ///        } while (counter < limit);
-///   } while (limit = [collection countByEnumeratingWithState:&enumState 
-///                                objects:items count:16]);
+///   } while (limit = [l_collection countByEnumeratingWithState:&enumState 
+///                                  objects:items count:16]);
+///   elem = nil;
+///   loopend: ;
 ///  }
 ///  else
 ///       elem = nil;
 ///  }
 ///
 Stmt *RewriteTest::RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S) {
-  return S;
+  SourceLocation startLoc = S->getLocStart();
+  SourceLocation collectionLoc = S->getCollection()->getLocStart();
+  const char *startBuf = SM->getCharacterData(startLoc);
+  const char *startCollectionBuf = SM->getCharacterData(collectionLoc);
+  const char *elementName;
+  std::string buf;
+  buf = "\n{\n\t";
+  if (DeclStmt *DS = dyn_cast<DeclStmt>(S->getElement())) {
+    // type elem;
+    QualType ElementType = cast<ValueDecl>(DS->getDecl())->getType();
+    buf += ElementType.getAsString();
+    buf += " ";
+    elementName = DS->getDecl()->getName();
+    buf += elementName;
+    buf += ";\n\t";
+  }
+  else if (DeclRefExpr *DR = dyn_cast<DeclRefExpr>(S->getElement()))
+    elementName = DR->getDecl()->getName();
+  else
+    assert(false && "RewriteObjCForCollectionStmt - bad element kind");
+  
+  // struct __objcFastEnumerationState enumState = { 0 };
+  buf += "struct __objcFastEnumerationState enumState = { 0 };\n\t";
+  // id items[16];
+  buf += "id items[16];\n\t";
+  // id l_collection = (id)
+  buf += "id l_collection = (id)";
+  // Replace: "for (type element in" with string constructed thus far. 
+  Rewrite.ReplaceText(startLoc, startCollectionBuf - startBuf,
+                      buf.c_str(), buf.size());
+  // Replace ')' in for '(' type elem in collection ')' with ';'
+  SourceLocation endCollectionLoc = S->getCollection()->getLocEnd();
+  const char *endCollectionBuf = SM->getCharacterData(endCollectionLoc);
+  const char *lparenBuf = strchr(endCollectionBuf, ')');
+  SourceLocation lparenLoc = startLoc.getFileLocWithOffset(lparenBuf-startBuf);
+  buf = ";\n\t";
+  
+  // unsigned long limit = [l_collection countByEnumeratingWithState:&enumState
+  //                                   objects:items count:16];
+  // which is synthesized into:
+  // unsigned int limit = 
+  // ((unsigned int (*)
+  //  (id, SEL, struct __objcFastEnumerationState *, id *, unsigned int))
+  //  (void *)objc_msgSend)((id)l_collection, 
+  //                        sel_registerName(
+  //                          "countByEnumeratingWithState:objects:count:"), 
+  //                        (struct __objcFastEnumerationState *)&state, 
+  //                        (id *)items, (unsigned int)16);
+  buf += "unsigned long limit =\n\t\t";
+  SynthCountByEnumWithState(buf);
+  buf += ";\n\t";
+  /// if (limit) {
+  ///   unsigned long startMutations = *enumState.mutationsPtr;
+  ///   do {
+  ///        unsigned long counter = 0;
+  ///        do {
+  ///             if (startMutations != *enumState.mutationsPtr) 
+  ///               objc_enumerationMutation(l_collection);
+  ///             elem = enumState.itemsPtr[counter++];
+  buf += "if (limit) {\n\t";
+  buf += "unsigned long startMutations = *enumState.mutationsPtr;\n\t";
+  buf += "do {\n\t\t";
+  buf += "unsigned long counter = 0;\n\t\t";
+  buf += "do {\n\t\t\t";
+  buf += "if (startMutations != *enumState.mutationsPtr)\n\t\t\t\t";
+  buf += "objc_enumerationMutation(l_collection);\n\t\t\t";
+  buf += elementName;
+  buf += " = enumState.itemsPtr[counter++];";
+  // Replace ')' in for '(' type elem in collection ')' with all of these.
+  Rewrite.ReplaceText(lparenLoc, 1, buf.c_str(), buf.size());
+  
+  ///        } while (counter < limit);
+  ///   } while (limit = [l_collection countByEnumeratingWithState:&enumState 
+  ///                                  objects:items count:16]);
+  ///   elem = nil;
+  ///   loopend: ;
+  ///  }
+  ///  else
+  ///       elem = nil;
+  ///  }
+  buf = ";\n\t\t";
+  buf += "} while (counter < limit);\n\t";
+  buf += "} while (limit = ";
+  SynthCountByEnumWithState(buf);
+  buf += ");\n\t";
+  buf += elementName;
+  buf += " = nil;\n\t";
+  // TODO: Generate a unique label to exit the for loop on break statement.
+  // buf += "loopend: ;\n\t";
+  buf += "}\n\t";
+  buf += "else\n\t\t";
+  buf += elementName;
+  buf += " = nil;\n";
+  buf += "}\n";
+  // Insert all these *after* the statement body.
+  SourceLocation endBodyLoc = S->getBody()->getLocEnd();
+  const char *endBodyBuf = SM->getCharacterData(endBodyLoc)+1;
+  endBodyLoc = startLoc.getFileLocWithOffset(endBodyBuf-startBuf);
+  Rewrite.InsertText(endBodyLoc, buf.c_str(), buf.size());
+ 
+  return 0;
 }
 
 Stmt *RewriteTest::RewriteObjCTryStmt(ObjCAtTryStmt *S) {
@@ -1422,7 +1552,7 @@
   return Context->getTagDeclType(SuperStructDecl);
 }
 
-Stmt *RewriteTest::RewriteMessageExpr(ObjCMessageExpr *Exp) {
+Stmt *RewriteTest::SynthMessageExpr(ObjCMessageExpr *Exp) {
   if (!SelGetUidFunctionDecl)
     SynthSelGetUidFunctionDecl();
   if (!MsgSendFunctionDecl)
@@ -1648,6 +1778,7 @@
   const FunctionType *FT = msgSendType->getAsFunctionType();
   CallExpr *CE = new CallExpr(PE, &MsgExprs[0], MsgExprs.size(), 
                               FT->getResultType(), SourceLocation());
+  Stmt *ReplacingStmt = CE;
   if (MsgSendStretFlavor) {
     // We have the method which returns a struct/union. Must also generate
     // call to objc_msgSend_stret and hang both varieties on a conditional
@@ -1695,20 +1826,15 @@
     // (sizeof(returnType) <= 8 ? objc_msgSend(...) : objc_msgSend_stret(...))
     ConditionalOperator *CondExpr = 
       new ConditionalOperator(lessThanExpr, CE, STCE, returnType);
-    ParenExpr *PE = new ParenExpr(SourceLocation(), SourceLocation(), CondExpr);
-    // Now do the actual rewrite.
-    if (Rewrite.ReplaceStmt(Exp, PE)) {
-      // replacement failed.
-      unsigned DiagID = Diags.getCustomDiagID(Diagnostic::Warning, 
-                       "rewriting sub-expression within a macro (may not be correct)");
-      SourceRange Range = Exp->getSourceRange();
-      Diags.Report(Context->getFullLoc(Exp->getLocStart()), DiagID, 0, 0, &Range, 1);
-    }
-    delete Exp;
-    return PE;
+    ReplacingStmt = new ParenExpr(SourceLocation(), SourceLocation(), CondExpr);
   }
+  return ReplacingStmt;
+}
+
+Stmt *RewriteTest::RewriteMessageExpr(ObjCMessageExpr *Exp) {
+  Stmt *ReplacingStmt = SynthMessageExpr(Exp);
   // Now do the actual rewrite.
-  if (Rewrite.ReplaceStmt(Exp, CE)) {
+  if (Rewrite.ReplaceStmt(Exp, ReplacingStmt)) {
     // replacement failed.
     unsigned DiagID = Diags.getCustomDiagID(Diagnostic::Warning, 
                      "rewriting sub-expression within a macro (may not be correct)");
@@ -1717,7 +1843,7 @@
   }
   
   delete Exp;
-  return CE;
+  return ReplacingStmt;
 }
 
 /// RewriteObjCProtocolExpr - Rewrite a protocol expression into

Modified: cfe/trunk/clang.xcodeproj/project.pbxproj
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/clang.xcodeproj/project.pbxproj?rev=45760&r1=45759&r2=45760&view=diff

==============================================================================
--- cfe/trunk/clang.xcodeproj/project.pbxproj (original)
+++ cfe/trunk/clang.xcodeproj/project.pbxproj Tue Jan  8 16:06:28 2008
@@ -572,9 +572,9 @@
 				DE928B7C0C0A615100231DA4 /* CodeGenModule.h */,
 				DE928B7E0C0A615600231DA4 /* CodeGenModule.cpp */,
 				DEEBC3BB0C2363BC00A9FE82 /* CodeGenTypes.cpp */,
-				DEEBC3B90C2363B800A9FE82 /* CodeGenTypes.h */,
 				1ABC36930C7A4BDC006DB0AB /* CGBuiltin.cpp */,
 				DE4264FB0C113592005A861D /* CGDecl.cpp */,
+				DEEBC3B90C2363B800A9FE82 /* CodeGenTypes.h */,
 				DE4772FB0C10EAEC002239E8 /* CGExpr.cpp */,
 				DEF2EFF20C6CDD74000C4259 /* CGExprAgg.cpp */,
 				DE224FF70C7AA98800D370A5 /* CGExprComplex.cpp */,

Added: cfe/trunk/test/Sema/rewrite-foreach-1.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/rewrite-foreach-1.m?rev=45760&view=auto

==============================================================================
--- cfe/trunk/test/Sema/rewrite-foreach-1.m (added)
+++ cfe/trunk/test/Sema/rewrite-foreach-1.m Tue Jan  8 16:06:28 2008
@@ -0,0 +1,29 @@
+// RUN: clang -rewrite-test %s
+            
+ at protocol P @end
+
+ at interface MyList
+ at end
+    
+ at implementation MyList
+- (unsigned int)countByEnumeratingWithState:  (struct __objcFastEnumerationState *)state objects:  (id *)items count:(unsigned int)stackcount
+{
+        return 0;
+}
+ at end
+
+ at interface MyList (BasicTest)
+- (void)compilerTestAgainst;
+ at end
+
+int LOOP();
+ at implementation MyList (BasicTest)
+- (void)compilerTestAgainst {
+  id el;
+        for (el in self) 
+	  { LOOP(); }
+        for (id el1 in self) 
+	  LOOP();
+}
+ at end
+





More information about the cfe-commits mailing list