[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