[cfe-commits] r46037 - in /cfe/trunk: Driver/RewriteTest.cpp test/Sema/rewrite-foreach-5.m

Fariborz Jahanian fjahanian at apple.com
Tue Jan 15 15:58:24 PST 2008


Author: fjahanian
Date: Tue Jan 15 17:58:23 2008
New Revision: 46037

URL: http://llvm.org/viewvc/llvm-project?rev=46037&view=rev
Log:
Added support for rewriting of continue/break statements inside ObjC2's foreach-stmt.


Added:
    cfe/trunk/test/Sema/rewrite-foreach-5.m
Modified:
    cfe/trunk/Driver/RewriteTest.cpp

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

==============================================================================
--- cfe/trunk/Driver/RewriteTest.cpp (original)
+++ cfe/trunk/Driver/RewriteTest.cpp Tue Jan 15 17:58:23 2008
@@ -40,6 +40,8 @@
     llvm::SmallPtrSet<ObjCInterfaceDecl*, 8> ObjCSynthesizedStructs;
     llvm::SmallPtrSet<ObjCInterfaceDecl*, 8> ObjCForwardDecls;
     llvm::DenseMap<ObjCMethodDecl*, std::string> MethodInternalNames;
+    llvm::SmallVector<Stmt *, 32> Stmts;
+    llvm::SmallVector<int, 8> ObjCBcLabelNo;
     
     FunctionDecl *MsgSendFunctionDecl;
     FunctionDecl *MsgSendSuperFunctionDecl;
@@ -56,6 +58,9 @@
     FileVarDecl *ConstantStringClassReference;
     RecordDecl *NSStringRecord;
     
+    // ObjC foreach break/continue generation supper.
+    int BcLabelCount;
+    
     // Needed for super.
     ObjCMethodDecl *CurMethodDecl;
     RecordDecl *SuperStructDecl;
@@ -79,6 +84,7 @@
       NSStringRecord = 0;
       CurMethodDecl = 0;
       SuperStructDecl = 0;
+      BcLabelCount = 0;
       
       // Get the ID and start/end of the main file.
       MainFileID = SM->getMainFileID();
@@ -176,6 +182,8 @@
     CallExpr *SynthesizeCallToFunctionDecl(FunctionDecl *FD, 
                                            Expr **args, unsigned nargs);
     Stmt *SynthMessageExpr(ObjCMessageExpr *Exp);
+    Stmt *RewriteBreakStmt(BreakStmt *S);
+    Stmt *RewriteContinueStmt(ContinueStmt *S);
     void SynthCountByEnumWithState(std::string &buf);
     
     void SynthMsgSendFunctionDecl();
@@ -699,6 +707,14 @@
 //===----------------------------------------------------------------------===//
 
 Stmt *RewriteTest::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) {
+  if (isa<SwitchStmt>(S) || isa<WhileStmt>(S) || 
+      isa<DoStmt>(S) || isa<ForStmt>(S))
+    Stmts.push_back(S);
+  else if (isa<ObjCForCollectionStmt>(S)) {
+    Stmts.push_back(S);
+    ObjCBcLabelNo.push_back(++BcLabelCount);
+  }
+  
   // Otherwise, just rewrite all children.
   for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
        CI != E; ++CI)
@@ -753,7 +769,21 @@
   if (ObjCForCollectionStmt *StmtForCollection = 
         dyn_cast<ObjCForCollectionStmt>(S))
     return RewriteObjCForCollectionStmt(StmtForCollection);
-  
+  if (BreakStmt *StmtBreakStmt =
+      dyn_cast<BreakStmt>(S))
+    return RewriteBreakStmt(StmtBreakStmt);
+  if (ContinueStmt *StmtContinueStmt =
+      dyn_cast<ContinueStmt>(S))
+    return RewriteContinueStmt(StmtContinueStmt);
+  
+  if (isa<SwitchStmt>(S) || isa<WhileStmt>(S) || 
+      isa<DoStmt>(S) || isa<ForStmt>(S)) {
+    assert(!Stmts.empty() && "Statement stack is empty");
+    assert ((isa<SwitchStmt>(Stmts.back()) || isa<WhileStmt>(Stmts.back()) || 
+             isa<DoStmt>(Stmts.back()) || isa<ForStmt>(Stmts.back())) 
+            && "Statement stack mismatch");
+    Stmts.pop_back();
+  }
 #if 0
   if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(S)) {
     CastExpr *Replacement = new CastExpr(ICE->getType(), ICE->getSubExpr(), SourceLocation());
@@ -792,6 +822,40 @@
          "(id *)items, (unsigned int)16)";
 }
 
+/// RewriteBreakStmt - Rewrite for a break-stmt inside an ObjC2's foreach
+/// statement to exit to its outer synthesized loop.
+///
+Stmt *RewriteTest::RewriteBreakStmt(BreakStmt *S) {
+  if (Stmts.empty() || !isa<ObjCForCollectionStmt>(Stmts.back()))
+    return S;
+  // replace break with goto __break_label
+  std::string buf;
+  
+  SourceLocation startLoc = S->getLocStart();
+  buf = "goto __break_label_";
+  buf += utostr(ObjCBcLabelNo.back());
+  Rewrite.ReplaceText(startLoc, strlen("break"), buf.c_str(), buf.size());
+
+  return 0;
+}
+
+/// RewriteContinueStmt - Rewrite for a continue-stmt inside an ObjC2's foreach
+/// statement to continue with its inner synthesized loop.
+///
+Stmt *RewriteTest::RewriteContinueStmt(ContinueStmt *S) {
+  if (Stmts.empty() || !isa<ObjCForCollectionStmt>(Stmts.back()))
+    return S;
+  // replace continue with goto __continue_label
+  std::string buf;
+  
+  SourceLocation startLoc = S->getLocStart();
+  buf = "goto __continue_label_";
+  buf += utostr(ObjCBcLabelNo.back());
+  Rewrite.ReplaceText(startLoc, strlen("continue"), buf.c_str(), buf.size());
+  
+  return 0;
+}
+
 /// RewriteObjCTryStmt - Rewriter for ObjC2's foreach statement.
 ///  It rewrites:
 /// for ( type elem in collection) { stmts; }
@@ -813,17 +877,24 @@
 ///               objc_enumerationMutation(l_collection);
 ///             elem = (type)enumState.itemsPtr[counter++];
 ///             stmts;
+///             __continue_label: ;
 ///        } while (counter < limit);
 ///   } while (limit = [l_collection countByEnumeratingWithState:&enumState 
 ///                                  objects:items count:16]);
 ///   elem = nil;
-///   loopend: ;
+///   __break_label: ;
 ///  }
 ///  else
 ///       elem = nil;
 ///  }
 ///
 Stmt *RewriteTest::RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S) {
+  assert(!Stmts.empty() && "ObjCForCollectionStmt - Statement stack empty");
+  assert(isa<ObjCForCollectionStmt>(Stmts.back()) && 
+         "ObjCForCollectionStmt Statement stack mismatch");
+  assert(!ObjCBcLabelNo.empty() && 
+         "ObjCForCollectionStmt - Label No stack empty");
+  
   SourceLocation startLoc = S->getLocStart();
   const char *startBuf = SM->getCharacterData(startLoc);
   const char *elementName;
@@ -911,24 +982,31 @@
   // Replace ')' in for '(' type elem in collection ')' with all of these.
   Rewrite.ReplaceText(lparenLoc, 1, buf.c_str(), buf.size());
   
+  ///            __continue_label: ;
   ///        } while (counter < limit);
   ///   } while (limit = [l_collection countByEnumeratingWithState:&enumState 
   ///                                  objects:items count:16]);
   ///   elem = nil;
-  ///   loopend: ;
+  ///   __break_label: ;
   ///  }
   ///  else
   ///       elem = nil;
   ///  }
-  buf = ";\n\t\t";
+  /// 
+  buf = ";\n\t";
+  buf += "__continue_label_";
+  buf += utostr(ObjCBcLabelNo.back());
+  buf += ": ;";
+  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 += "__break_label_";
+  buf += utostr(ObjCBcLabelNo.back());
+  buf += ": ;\n\t";
   buf += "}\n\t";
   buf += "else\n\t\t";
   buf += elementName;
@@ -939,6 +1017,8 @@
   const char *endBodyBuf = SM->getCharacterData(endBodyLoc)+1;
   endBodyLoc = startLoc.getFileLocWithOffset(endBodyBuf-startBuf);
   Rewrite.InsertText(endBodyLoc, buf.c_str(), buf.size());
+  Stmts.pop_back();
+  ObjCBcLabelNo.pop_back();
  
   return 0;
 }

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

==============================================================================
--- cfe/trunk/test/Sema/rewrite-foreach-5.m (added)
+++ cfe/trunk/test/Sema/rewrite-foreach-5.m Tue Jan 15 17:58:23 2008
@@ -0,0 +1,47 @@
+// RUN: clang -rewrite-test %s | clang
+
+ at interface MyList
+- (id) allKeys;
+ at end
+    
+ at implementation MyList
+- (unsigned int)countByEnumeratingWithState:  (struct __objcFastEnumerationState *)state objects:  (id *)items count:(unsigned int)stackcount
+{
+        return 0;
+}
+- (id) allKeys {}
+ at end
+
+ at interface MyList (BasicTest)
+- (void)compilerTestAgainst;
+ at end
+
+int LOOP();
+ at implementation MyList (BasicTest)
+- (void)compilerTestAgainst {
+  MyList * el;
+  int i;
+        for (el in [el allKeys]) { 
+		for (i = 0; i < 10; i++)
+		  if (i == 5)
+		   break;
+
+		if (el == 0)
+		 break;
+		if (el != self)
+		  continue;
+		LOOP(); 
+	  }
+
+        for (id el1 in[el allKeys]) { 
+	    LOOP(); 
+	    for (el in self) {
+	      if (el)
+		continue;
+	    }
+	    if (el1)
+	      break;
+	  }
+}
+ at end
+





More information about the cfe-commits mailing list