forked from OSchip/llvm-project
Patch to parse/build AST ObjC2's foreach statement.
llvm-svn: 45539
This commit is contained in:
parent
9b92e93d36
commit
732b8c2dc5
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in New Issue