[cfe-commits] r45539 - in /cfe/trunk: Parse/ParseDecl.cpp Parse/ParseObjc.cpp Parse/ParseStmt.cpp Sema/Sema.h Sema/SemaStmt.cpp include/clang/Parse/Action.h

Fariborz Jahanian fjahanian at apple.com
Thu Jan 3 09:55:25 PST 2008


Author: fjahanian
Date: Thu Jan  3 11:55:25 2008
New Revision: 45539

URL: http://llvm.org/viewvc/llvm-project?rev=45539&view=rev
Log:
Patch to parse/build AST ObjC2's foreach statement.

Modified:
    cfe/trunk/Parse/ParseDecl.cpp
    cfe/trunk/Parse/ParseObjc.cpp
    cfe/trunk/Parse/ParseStmt.cpp
    cfe/trunk/Sema/Sema.h
    cfe/trunk/Sema/SemaStmt.cpp
    cfe/trunk/include/clang/Parse/Action.h

Modified: cfe/trunk/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Parse/ParseDecl.cpp?rev=45539&r1=45538&r2=45539&view=diff

==============================================================================
--- cfe/trunk/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/Parse/ParseDecl.cpp Thu Jan  3 11:55:25 2008
@@ -296,7 +296,9 @@
     ConsumeToken();
     return Actions.FinalizeDeclaratorGroup(CurScope, LastDeclInGroup);
   }
-  
+  if (D.getContext()  == Declarator::ForContext && isObjCForCollectionInKW()) {
+    return Actions.FinalizeDeclaratorGroup(CurScope, LastDeclInGroup);
+  }
   Diag(Tok, diag::err_parse_error);
   // Skip to end of block or statement
   SkipUntil(tok::r_brace, true, true);

Modified: cfe/trunk/Parse/ParseObjc.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Parse/ParseObjc.cpp?rev=45539&r1=45538&r2=45539&view=diff

==============================================================================
--- cfe/trunk/Parse/ParseObjc.cpp (original)
+++ cfe/trunk/Parse/ParseObjc.cpp Thu Jan  3 11:55:25 2008
@@ -494,7 +494,10 @@
 ///  objc-for-collection-in: 'in'
 ///
 bool Parser::isObjCForCollectionInKW() {
-  if (Tok.is(tok::identifier)) {
+  // FIXME: May have to do additional look-ahead to only allow for
+  // valid tokens following an 'in'; such as an identifier, unary operators,
+  // '[' etc.
+  if (getLang().ObjC2 && Tok.is(tok::identifier)) {
     const IdentifierInfo *II = Tok.getIdentifierInfo();
     return II == ObjCForCollectionInKW;
   }

Modified: cfe/trunk/Parse/ParseStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Parse/ParseStmt.cpp?rev=45539&r1=45538&r2=45539&view=diff

==============================================================================
--- cfe/trunk/Parse/ParseStmt.cpp (original)
+++ cfe/trunk/Parse/ParseStmt.cpp Thu Jan  3 11:55:25 2008
@@ -721,6 +721,8 @@
 ///       for-statement: [C99 6.8.5.3]
 ///         'for' '(' expr[opt] ';' expr[opt] ';' expr[opt] ')' statement
 ///         'for' '(' declaration expr[opt] ';' expr[opt] ')' statement
+/// [OBJC2] 'for' '(' declaration 'in' expr ')' statement
+/// [OBJC2] 'for' '(' expr 'in' expr ')' statement
 Parser::StmtResult Parser::ParseForStatement() {
   assert(Tok.is(tok::kw_for) && "Not a for stmt!");
   SourceLocation ForLoc = ConsumeToken();  // eat the 'for'.
@@ -744,6 +746,7 @@
   StmtTy *FirstPart = 0;
   ExprTy *SecondPart = 0;
   StmtTy *ThirdPart = 0;
+  bool foreach = false;
   
   // Parse the first part of the for specifier.
   if (Tok.is(tok::semi)) {  // for (;
@@ -756,6 +759,12 @@
     DeclTy *aBlockVarDecl = ParseDeclaration(Declarator::ForContext);
     StmtResult stmtResult = Actions.ActOnDeclStmt(aBlockVarDecl);
     FirstPart = stmtResult.isInvalid ? 0 : stmtResult.Val;
+    if ((foreach = isObjCForCollectionInKW())) {
+      ConsumeToken(); // consume 'in'
+      Value = ParseExpression();
+      if (!Value.isInvalid)
+        SecondPart = Value.Val;
+    }
   } else {
     Value = ParseExpression();
 
@@ -768,43 +777,50 @@
       
     if (Tok.is(tok::semi)) {
       ConsumeToken();
-    } else {
+    }
+    else if ((foreach = isObjCForCollectionInKW())) {
+      ConsumeToken(); // consume 'in'
+      Value = ParseExpression();
+      if (!Value.isInvalid)
+        SecondPart = Value.Val;
+    }
+    else {
       if (!Value.isInvalid) Diag(Tok, diag::err_expected_semi_for);
       SkipUntil(tok::semi);
     }
   }
+  if (!foreach) {
+    // Parse the second part of the for specifier.
+    if (Tok.is(tok::semi)) {  // for (...;;
+      // no second part.
+      Value = ExprResult();
+    } else {
+      Value = ParseExpression();
+      if (!Value.isInvalid)
+        SecondPart = Value.Val;
+    }
   
-  // Parse the second part of the for specifier.
-  if (Tok.is(tok::semi)) {  // for (...;;
-    // no second part.
-    Value = ExprResult();
-  } else {
-    Value = ParseExpression();
-    if (!Value.isInvalid)
-      SecondPart = Value.Val;
-  }
-  
-  if (Tok.is(tok::semi)) {
-    ConsumeToken();
-  } else {
-    if (!Value.isInvalid) Diag(Tok, diag::err_expected_semi_for);
-    SkipUntil(tok::semi);
-  }
+    if (Tok.is(tok::semi)) {
+      ConsumeToken();
+    } else {
+      if (!Value.isInvalid) Diag(Tok, diag::err_expected_semi_for);
+      SkipUntil(tok::semi);
+    }
   
-  // Parse the third part of the for specifier.
-  if (Tok.is(tok::r_paren)) {  // for (...;...;)
-    // no third part.
-    Value = ExprResult();
-  } else {
-    Value = ParseExpression();
-    if (!Value.isInvalid) {
-      // Turn the expression into a stmt.
-      StmtResult R = Actions.ActOnExprStmt(Value.Val);
-      if (!R.isInvalid)
-        ThirdPart = R.Val;
+    // Parse the third part of the for specifier.
+    if (Tok.is(tok::r_paren)) {  // for (...;...;)
+      // no third part.
+      Value = ExprResult();
+    } else {
+      Value = ParseExpression();
+      if (!Value.isInvalid) {
+        // Turn the expression into a stmt.
+        StmtResult R = Actions.ActOnExprStmt(Value.Val);
+        if (!R.isInvalid)
+          ThirdPart = R.Val;
+      }
     }
   }
-  
   // Match the ')'.
   SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
   
@@ -826,8 +842,12 @@
   if (Body.isInvalid)
     return Body;
   
-  return Actions.ActOnForStmt(ForLoc, LParenLoc, FirstPart, SecondPart,
-                              ThirdPart, RParenLoc, Body.Val);
+  return !foreach ? Actions.ActOnForStmt(ForLoc, LParenLoc, FirstPart, 
+                                         SecondPart, ThirdPart, RParenLoc, 
+                                         Body.Val)
+                  : Actions.ActOnObjcForCollectionStmt(ForLoc, LParenLoc, 
+                                                       FirstPart, SecondPart, 
+                                                       RParenLoc, Body.Val);
 }
 
 /// ParseGotoStatement

Modified: cfe/trunk/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Sema/Sema.h?rev=45539&r1=45538&r2=45539&view=diff

==============================================================================
--- cfe/trunk/Sema/Sema.h (original)
+++ cfe/trunk/Sema/Sema.h Thu Jan  3 11:55:25 2008
@@ -325,6 +325,11 @@
                                   SourceLocation LParenLoc, 
                                   StmtTy *First, ExprTy *Second, ExprTy *Third,
                                   SourceLocation RParenLoc, StmtTy *Body);
+  virtual StmtResult ActOnObjcForCollectionStmt(SourceLocation ForColLoc, 
+                                  SourceLocation LParenLoc, 
+                                  StmtTy *First, ExprTy *Second,
+                                  SourceLocation RParenLoc, StmtTy *Body);
+  
   virtual StmtResult ActOnGotoStmt(SourceLocation GotoLoc,
                                    SourceLocation LabelLoc,
                                    IdentifierInfo *LabelII);

Modified: cfe/trunk/Sema/SemaStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Sema/SemaStmt.cpp?rev=45539&r1=45538&r2=45539&view=diff

==============================================================================
--- cfe/trunk/Sema/SemaStmt.cpp (original)
+++ cfe/trunk/Sema/SemaStmt.cpp Thu Jan  3 11:55:25 2008
@@ -530,6 +530,39 @@
   return new ForStmt(First, Second, Third, Body, ForLoc);
 }
 
+Action::StmtResult 
+Sema::ActOnObjcForCollectionStmt(SourceLocation ForColLoc, 
+                                 SourceLocation LParenLoc, 
+                                 StmtTy *first, ExprTy *second,
+                                 SourceLocation RParenLoc, StmtTy *body) {
+  Stmt *First  = static_cast<Stmt*>(first);
+  Expr *Second = static_cast<Expr*>(second);
+  Stmt *Body  = static_cast<Stmt*>(body);
+  
+  if (DeclStmt *DS = dyn_cast_or_null<DeclStmt>(First)) {
+    // C99 6.8.5p3: The declaration part of a 'for' statement shall only declare
+    // identifiers for objects having storage class 'auto' or 'register'.
+    for (ScopedDecl *D = DS->getDecl(); D; D = D->getNextDeclarator()) {
+      BlockVarDecl *BVD = dyn_cast<BlockVarDecl>(D);
+      if (BVD && !BVD->hasLocalStorage())
+        BVD = 0;
+      if (BVD == 0)
+        Diag(dyn_cast<ScopedDecl>(D)->getLocation(), 
+             diag::err_non_variable_decl_in_for);
+      // FIXME: mark decl erroneous!
+    }
+  }
+  if (Second) {
+    DefaultFunctionArrayConversion(Second);
+    QualType SecondType = Second->getType();
+#if 0
+    if (!SecondType->isScalarType()) // C99 6.8.5p2
+      return Diag(ForColLoc, diag::err_typecheck_statement_requires_scalar,
+                  SecondType.getAsString(), Second->getSourceRange());
+#endif
+  }
+  return new ObjcForCollectionStmt(First, Second, Body, ForColLoc);
+}
 
 Action::StmtResult 
 Sema::ActOnGotoStmt(SourceLocation GotoLoc, SourceLocation LabelLoc,

Modified: cfe/trunk/include/clang/Parse/Action.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Action.h?rev=45539&r1=45538&r2=45539&view=diff

==============================================================================
--- cfe/trunk/include/clang/Parse/Action.h (original)
+++ cfe/trunk/include/clang/Parse/Action.h Thu Jan  3 11:55:25 2008
@@ -265,6 +265,12 @@
                                   SourceLocation RParenLoc, StmtTy *Body) {
     return 0;
   }
+  virtual StmtResult ActOnObjcForCollectionStmt(SourceLocation ForColLoc, 
+                                  SourceLocation LParenLoc, 
+                                  StmtTy *First, ExprTy *Second,
+                                  SourceLocation RParenLoc, StmtTy *Body) {
+    return 0;
+  }
   virtual StmtResult ActOnGotoStmt(SourceLocation GotoLoc,
                                    SourceLocation LabelLoc,
                                    IdentifierInfo *LabelII) {





More information about the cfe-commits mailing list