diff options
author | Fariborz Jahanian <fjahanian@apple.com> | 2008-01-03 17:55:25 +0000 |
---|---|---|
committer | Fariborz Jahanian <fjahanian@apple.com> | 2008-01-03 17:55:25 +0000 |
commit | 3ba5a0f90a03d5e13d02cbee9abd2a1ba01b18bc (patch) | |
tree | 23f4c6f0e23087a103f1309e90cba10e7342d427 | |
parent | c89bf69c9289d2b2305f2c267daacc7312391898 (diff) |
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
-rw-r--r-- | Parse/ParseDecl.cpp | 4 | ||||
-rw-r--r-- | Parse/ParseObjc.cpp | 5 | ||||
-rw-r--r-- | Parse/ParseStmt.cpp | 82 | ||||
-rw-r--r-- | Sema/Sema.h | 5 | ||||
-rw-r--r-- | Sema/SemaStmt.cpp | 33 | ||||
-rw-r--r-- | include/clang/Parse/Action.h | 6 |
6 files changed, 102 insertions, 33 deletions
diff --git a/Parse/ParseDecl.cpp b/Parse/ParseDecl.cpp index b45ef47554..a2a3f3e7c0 100644 --- a/Parse/ParseDecl.cpp +++ b/Parse/ParseDecl.cpp @@ -296,7 +296,9 @@ ParseInitDeclaratorListAfterFirstDeclarator(Declarator &D) { 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 e661e8775b..c17e35e6f4 100644 --- a/Parse/ParseObjc.cpp +++ b/Parse/ParseObjc.cpp @@ -494,7 +494,10 @@ bool Parser::isObjCPropertyAttribute() { /// 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 4933ac72c6..762e499d81 100644 --- a/Parse/ParseStmt.cpp +++ b/Parse/ParseStmt.cpp @@ -721,6 +721,8 @@ Parser::StmtResult Parser::ParseDoStatement() { /// 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 @@ Parser::StmtResult Parser::ParseForStatement() { 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 @@ Parser::StmtResult Parser::ParseForStatement() { 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 @@ Parser::StmtResult Parser::ParseForStatement() { 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 @@ Parser::StmtResult Parser::ParseForStatement() { 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 diff --git a/Sema/Sema.h b/Sema/Sema.h index 5610b3a9e4..7faac13458 100644 --- a/Sema/Sema.h +++ b/Sema/Sema.h @@ -325,6 +325,11 @@ public: 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); diff --git a/Sema/SemaStmt.cpp b/Sema/SemaStmt.cpp index f83ff4b32d..cbb01bdb3c 100644 --- a/Sema/SemaStmt.cpp +++ b/Sema/SemaStmt.cpp @@ -530,6 +530,39 @@ Sema::ActOnForStmt(SourceLocation ForLoc, SourceLocation LParenLoc, 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, diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h index b711ec7401..bfd6624389 100644 --- a/include/clang/Parse/Action.h +++ b/include/clang/Parse/Action.h @@ -265,6 +265,12 @@ public: 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) { |