Patch to parse/build AST ObjC2's foreach statement.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@45539 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/Parse/ParseDecl.cpp b/Parse/ParseDecl.cpp
index b45ef47..a2a3f3e 100644
--- a/Parse/ParseDecl.cpp
+++ b/Parse/ParseDecl.cpp
@@ -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);
diff --git a/Parse/ParseObjc.cpp b/Parse/ParseObjc.cpp
index e661e87..c17e35e 100644
--- a/Parse/ParseObjc.cpp
+++ b/Parse/ParseObjc.cpp
@@ -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;
}
diff --git a/Parse/ParseStmt.cpp b/Parse/ParseStmt.cpp
index 4933ac7..762e499 100644
--- a/Parse/ParseStmt.cpp
+++ b/Parse/ParseStmt.cpp
@@ -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