New declarations/defs for Objc2's foreach-statement. This is work in progress.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@45511 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/AST/Stmt.cpp b/AST/Stmt.cpp
index 0d1ec03..95d077c 100644
--- a/AST/Stmt.cpp
+++ b/AST/Stmt.cpp
@@ -183,6 +183,14 @@
 Stmt::child_iterator ForStmt::child_begin() { return &SubExprs[0]; }
 Stmt::child_iterator ForStmt::child_end() { return &SubExprs[0]+END_EXPR; }
 
+// ObjcForCollectionStmt
+Stmt::child_iterator ObjcForCollectionStmt::child_begin() { 
+  return &SubExprs[0]; 
+}
+Stmt::child_iterator ObjcForCollectionStmt::child_end() { 
+  return &SubExprs[0]+END_EXPR; 
+}
+
 // GotoStmt
 Stmt::child_iterator GotoStmt::child_begin() { return child_iterator(); }
 Stmt::child_iterator GotoStmt::child_end() { return child_iterator(); }
diff --git a/AST/StmtPrinter.cpp b/AST/StmtPrinter.cpp
index fc28d06..099dd28 100644
--- a/AST/StmtPrinter.cpp
+++ b/AST/StmtPrinter.cpp
@@ -296,6 +296,25 @@
   }
 }
 
+void StmtPrinter::VisitObjcForCollectionStmt(ObjcForCollectionStmt *Node) {
+  Indent() << "for (";
+  if (DeclStmt *DS = dyn_cast<DeclStmt>(Node->getElement()))
+    PrintRawDecl(DS->getDecl());
+  else
+    PrintExpr(cast<Expr>(Node->getElement()));
+  OS << " in ";
+  PrintExpr(Node->getCollection());
+  OS << ") ";
+  
+  if (CompoundStmt *CS = dyn_cast<CompoundStmt>(Node->getBody())) {
+    PrintRawCompoundStmt(CS);
+    OS << "\n";
+  } else {
+    OS << "\n";
+    PrintStmt(Node->getBody());
+  }
+}
+
 void StmtPrinter::VisitGotoStmt(GotoStmt *Node) {
   Indent() << "goto " << Node->getLabel()->getName() << ";\n";
 }
diff --git a/AST/StmtSerialization.cpp b/AST/StmtSerialization.cpp
index d6f9dca..53dabbd 100644
--- a/AST/StmtSerialization.cpp
+++ b/AST/StmtSerialization.cpp
@@ -94,6 +94,9 @@
 
     case ForStmtClass:
       return ForStmt::CreateImpl(D);
+      
+    case ObjcForCollectionStmtClass:
+      return ObjcForCollectionStmt::CreateImpl(D);
     
     case GotoStmtClass:
       return GotoStmt::CreateImpl(D);
@@ -560,6 +563,21 @@
   return new ForStmt(Init,Cond,Inc,Body,ForLoc);
 }
 
+void ObjcForCollectionStmt::EmitImpl(Serializer& S) const {
+  S.Emit(ForCollectionLoc);
+  S.EmitOwnedPtr(getElement());
+  S.EmitOwnedPtr(getCollection());
+  S.EmitOwnedPtr(getBody());
+}
+
+ObjcForCollectionStmt* ObjcForCollectionStmt::CreateImpl(Deserializer& D) {
+  SourceLocation ForCollectionLoc = SourceLocation::ReadVal(D);
+  Stmt* Element = D.ReadOwnedPtr<Stmt>();
+  Expr* Collection = D.ReadOwnedPtr<Expr>();
+  Stmt* Body = D.ReadOwnedPtr<Stmt>();
+  return new ObjcForCollectionStmt(Element,Collection,Body,ForCollectionLoc);
+}
+
 void GotoStmt::EmitImpl(Serializer& S) const {
   S.Emit(GotoLoc);
   S.Emit(LabelLoc);
diff --git a/Parse/ParseObjc.cpp b/Parse/ParseObjc.cpp
index 19bbfea..e661e87 100644
--- a/Parse/ParseObjc.cpp
+++ b/Parse/ParseObjc.cpp
@@ -491,6 +491,16 @@
   return false;
 } 
 
+///  objc-for-collection-in: 'in'
+///
+bool Parser::isObjCForCollectionInKW() {
+  if (Tok.is(tok::identifier)) {
+    const IdentifierInfo *II = Tok.getIdentifierInfo();
+    return II == ObjCForCollectionInKW;
+  }
+  return false;
+}
+
 /// ParseObjcTypeQualifierList - This routine parses the objective-c's type
 /// qualifier list and builds their bitmask representation in the input
 /// argument.
diff --git a/Parse/Parser.cpp b/Parse/Parser.cpp
index 04cfea6..4bcbfc7 100644
--- a/Parse/Parser.cpp
+++ b/Parse/Parser.cpp
@@ -254,6 +254,7 @@
     ObjcPropertyAttrs[objc_copy] = &PP.getIdentifierTable().get("copy");
     ObjcPropertyAttrs[objc_nonatomic] = 
                                   &PP.getIdentifierTable().get("nonatomic");
+    ObjCForCollectionInKW = &PP.getIdentifierTable().get("in");
   }
 }
 
diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h
index 0eff0a7..58d61f6 100644
--- a/include/clang/AST/Stmt.h
+++ b/include/clang/AST/Stmt.h
@@ -573,6 +573,51 @@
   static ForStmt* CreateImpl(llvm::Deserializer& D);
 };
 
+/// ObjcForCollectionStmt - This represents Objective-c's collection statement;
+/// represented as 'for (element 'in' collection-expression)' stmt.
+///
+class ObjcForCollectionStmt : public Stmt {
+  enum { ELEM, COLLECTION, BODY, END_EXPR };
+  Stmt* SubExprs[END_EXPR]; // SubExprs[ELEM] is an expression or declstmt.
+  SourceLocation ForCollectionLoc;
+public:
+  ObjcForCollectionStmt(Stmt *Elem, Expr *Collect, Stmt *Body, 
+                        SourceLocation FCL) 
+  : Stmt(ObjcForCollectionStmtClass) {
+    SubExprs[ELEM] = Elem;
+    SubExprs[COLLECTION] = reinterpret_cast<Stmt*>(Collect);
+    SubExprs[BODY] = Body;
+    ForCollectionLoc = FCL;
+  }
+    
+  Stmt *getElement() { return SubExprs[ELEM]; }
+  Expr *getCollection() { 
+    return reinterpret_cast<Expr*>(SubExprs[COLLECTION]); 
+  }
+  Stmt *getBody() { return SubExprs[BODY]; }
+    
+  const Stmt *getElement() const { return SubExprs[ELEM]; }
+  const Expr *getCollection() const { 
+    return reinterpret_cast<Expr*>(SubExprs[COLLECTION]);
+  }
+  const Stmt *getBody() const { return SubExprs[BODY]; }
+    
+  virtual SourceRange getSourceRange() const { 
+    return SourceRange(ForCollectionLoc, SubExprs[BODY]->getLocEnd()); 
+  }
+  static bool classof(const Stmt *T) { 
+    return T->getStmtClass() == ObjcForCollectionStmtClass; 
+  }
+  static bool classof(const ObjcForCollectionStmt *) { return true; }
+    
+  // Iterators
+  virtual child_iterator child_begin();
+  virtual child_iterator child_end();
+    
+  virtual void EmitImpl(llvm::Serializer& S) const;
+  static ObjcForCollectionStmt* CreateImpl(llvm::Deserializer& D);
+};
+  
 /// GotoStmt - This represents a direct goto.
 ///
 class GotoStmt : public Stmt {
diff --git a/include/clang/AST/StmtNodes.def b/include/clang/AST/StmtNodes.def
index 27a5d1e..387ff65 100644
--- a/include/clang/AST/StmtNodes.def
+++ b/include/clang/AST/StmtNodes.def
@@ -49,8 +49,10 @@
 STMT(20, ObjcAtCatchStmt      , Stmt)
 STMT(21, ObjcAtFinallyStmt    , Stmt)
 STMT(22, ObjcAtThrowStmt      , Stmt)
+// Obj-C2 statements
+STMT(23, ObjcForCollectionStmt, Stmt)
 
-LAST_STMT(22)
+LAST_STMT(23)
 
 FIRST_EXPR(31)
 // Expressions.
diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h
index 20a836c..40531b6 100644
--- a/include/clang/Parse/Parser.h
+++ b/include/clang/Parse/Parser.h
@@ -292,6 +292,9 @@
   };
   IdentifierInfo *ObjcPropertyAttrs[objc_NumAttrs];
   bool isObjCPropertyAttribute();
+  
+  IdentifierInfo *ObjCForCollectionInKW;
+  bool isObjCForCollectionInKW();
 
   TypeTy *ParseObjCTypeName(ObjcDeclSpec &DS);
   void ParseObjCMethodRequirement();