Commit f04dbf05 authored by Erik Verbruggen's avatar Erik Verbruggen
Browse files

Fix for ObjC fast-enumeration parsing.

parent 61123092
......@@ -2554,6 +2554,10 @@ unsigned ObjCFastEnumerationAST::lastToken() const
return in_token + 1;
else if (initializer)
return initializer->lastToken();
else if (declarator)
return declarator->lastToken();
else if (type_specifiers)
return type_specifiers->lastToken();
else if (lparen_token)
return lparen_token + 1;
else
......
......@@ -3208,7 +3208,13 @@ class CPLUSPLUS_EXPORT ObjCFastEnumerationAST: public StatementAST
public:
unsigned for_token;
unsigned lparen_token;
StatementAST *initializer;
// declaration
SpecifierAST *type_specifiers;
DeclaratorAST *declarator;
// or an expression
ExpressionAST *initializer;
unsigned in_token;
ExpressionAST *fast_enumeratable_expression;
unsigned rparen_token;
......
......@@ -1541,14 +1541,13 @@ ObjCFastEnumerationAST *ObjCFastEnumerationAST::clone(MemoryPool *pool) const
ObjCFastEnumerationAST *ast = new (pool) ObjCFastEnumerationAST;
ast->for_token = for_token;
ast->lparen_token = lparen_token;
if (initializer)
ast->initializer = initializer->clone(pool);
if (type_specifiers) ast->type_specifiers = type_specifiers->clone(pool);
if (declarator) ast->declarator = declarator->clone(pool);
if (initializer) ast->initializer = initializer->clone(pool);
ast->in_token = in_token;
if (fast_enumeratable_expression)
ast->fast_enumeratable_expression = fast_enumeratable_expression->clone(pool);
if (fast_enumeratable_expression) ast->fast_enumeratable_expression = fast_enumeratable_expression->clone(pool);
ast->rparen_token = rparen_token;
if (body_statement)
ast->body_statement = body_statement->clone(pool);
if (body_statement) ast->body_statement = body_statement->clone(pool);
return ast;
}
......
......@@ -1511,6 +1511,10 @@ void ObjCFastEnumerationAST::accept0(ASTVisitor *visitor)
{
if (visitor->visit(this)) {
// visit ObjCFastEnumerationAST
if (type_specifiers)
accept(type_specifiers, visitor);
if (declarator)
accept(declarator, visitor);
if (initializer)
accept(initializer, visitor);
if (fast_enumeratable_expression)
......
......@@ -2178,38 +2178,55 @@ bool Parser::parseForStatement(StatementAST *&node)
unsigned lparen_token = 0;
match(T_LPAREN, &lparen_token);
// FIXME: for ObjC fast enumeration, this needs a semicolon before the "in" token, which is obviously wrong.
StatementAST *initializer = 0;
parseForInitStatement(initializer);
unsigned in_token = 0;
unsigned startOfTypeSpecifier = cursor();
bool blocked = blockErrors(true);
if (parseObjCContextKeyword(Token_in, in_token)) {
if (objCEnabled()) {
ObjCFastEnumerationAST *ast = new (_pool) ObjCFastEnumerationAST;
ast->for_token = for_token;
ast->lparen_token = lparen_token;
ast->initializer = initializer;
ast->in_token = in_token;
parseExpression(ast->fast_enumeratable_expression);
match(T_RPAREN, &ast->rparen_token);
parseStatement(ast->body_statement);
node = ast;
} else {
ForStatementAST *ast = new (_pool) ForStatementAST;
if (parseTypeSpecifier(ast->type_specifiers))
parseDeclarator(ast->declarator);
ast->for_token = for_token;
ast->lparen_token = lparen_token;
ast->initializer = initializer;
parseExpression(ast->condition);
match(T_SEMICOLON, &ast->semicolon_token);
parseExpression(ast->expression);
match(T_RPAREN, &ast->rparen_token);
parseStatement(ast->statement);
if (! ast->type_specifiers || ! ast->declarator) {
ast->type_specifiers = 0;
ast->declarator = 0;
node = ast;
rewind(startOfTypeSpecifier);
parseAssignmentExpression(ast->initializer);
}
if (parseObjCContextKeyword(Token_in, ast->in_token)) {
blockErrors(blocked);
parseExpression(ast->fast_enumeratable_expression);
match(T_RPAREN, &ast->rparen_token);
parseStatement(ast->body_statement);
node = ast;
return true;
}
// there was no "in" token, so we continue with a normal for-statement
rewind(startOfTypeSpecifier);
}
blockErrors(blocked);
// Normal C/C++ for-statement parsing
ForStatementAST *ast = new (_pool) ForStatementAST;
ast->for_token = for_token;
ast->lparen_token = lparen_token;
parseForInitStatement(ast->initializer);
parseExpression(ast->condition);
match(T_SEMICOLON, &ast->semicolon_token);
parseExpression(ast->expression);
match(T_RPAREN, &ast->rparen_token);
parseStatement(ast->statement);
node = ast;
return true;
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment