Commit ea411f84 by Ian Lance Taylor

compiler: Permit "for range x" clauses.

Fixes Issue 8370.

From-SVN: r216051
parent 3369b919
...@@ -3836,6 +3836,12 @@ Parse::simple_stat(bool may_be_composite_lit, bool* return_exp, ...@@ -3836,6 +3836,12 @@ Parse::simple_stat(bool may_be_composite_lit, bool* return_exp,
this->unget_token(Token::make_identifier_token(identifier, is_exported, this->unget_token(Token::make_identifier_token(identifier, is_exported,
location)); location));
} }
else if (p_range_clause != NULL && token->is_keyword(KEYWORD_RANGE))
{
Typed_identifier_list til;
this->range_clause_decl(&til, p_range_clause);
return NULL;
}
Expression* exp = this->expression(PRECEDENCE_NORMAL, true, Expression* exp = this->expression(PRECEDENCE_NORMAL, true,
may_be_composite_lit, may_be_composite_lit,
...@@ -5278,7 +5284,7 @@ Parse::for_clause(Expression** cond, Block** post) ...@@ -5278,7 +5284,7 @@ Parse::for_clause(Expression** cond, Block** post)
} }
} }
// RangeClause = IdentifierList ( "=" | ":=" ) "range" Expression . // RangeClause = [ IdentifierList ( "=" | ":=" ) ] "range" Expression .
// This is the := version. It is called with a list of identifiers. // This is the := version. It is called with a list of identifiers.
...@@ -5291,7 +5297,6 @@ Parse::range_clause_decl(const Typed_identifier_list* til, ...@@ -5291,7 +5297,6 @@ Parse::range_clause_decl(const Typed_identifier_list* til,
p_range_clause->found = true; p_range_clause->found = true;
go_assert(til->size() >= 1);
if (til->size() > 2) if (til->size() > 2)
error_at(this->location(), "too many variables for range clause"); error_at(this->location(), "too many variables for range clause");
...@@ -5300,6 +5305,9 @@ Parse::range_clause_decl(const Typed_identifier_list* til, ...@@ -5300,6 +5305,9 @@ Parse::range_clause_decl(const Typed_identifier_list* til,
NULL); NULL);
p_range_clause->range = expr; p_range_clause->range = expr;
if (til->empty())
return;
bool any_new = false; bool any_new = false;
const Typed_identifier* pti = &til->front(); const Typed_identifier* pti = &til->front();
...@@ -5347,6 +5355,9 @@ Parse::range_clause_expr(const Expression_list* vals, ...@@ -5347,6 +5355,9 @@ Parse::range_clause_expr(const Expression_list* vals,
p_range_clause->range = this->expression(PRECEDENCE_NORMAL, false, false, p_range_clause->range = this->expression(PRECEDENCE_NORMAL, false, false,
NULL, NULL); NULL, NULL);
if (vals->empty())
return;
p_range_clause->index = vals->front(); p_range_clause->index = vals->front();
if (vals->size() == 1) if (vals->size() == 1)
p_range_clause->value = NULL; p_range_clause->value = NULL;
......
...@@ -5305,8 +5305,12 @@ Statement::make_for_statement(Block* init, Expression* cond, Block* post, ...@@ -5305,8 +5305,12 @@ Statement::make_for_statement(Block* init, Expression* cond, Block* post,
int int
For_range_statement::do_traverse(Traverse* traverse) For_range_statement::do_traverse(Traverse* traverse)
{ {
if (this->traverse_expression(traverse, &this->index_var_) == TRAVERSE_EXIT) if (this->index_var_ != NULL)
return TRAVERSE_EXIT; {
if (this->traverse_expression(traverse, &this->index_var_)
== TRAVERSE_EXIT)
return TRAVERSE_EXIT;
}
if (this->value_var_ != NULL) if (this->value_var_ != NULL)
{ {
if (this->traverse_expression(traverse, &this->value_var_) if (this->traverse_expression(traverse, &this->value_var_)
...@@ -5434,25 +5438,27 @@ For_range_statement::do_lower(Gogo* gogo, Named_object*, Block* enclosing, ...@@ -5434,25 +5438,27 @@ For_range_statement::do_lower(Gogo* gogo, Named_object*, Block* enclosing,
if (iter_init != NULL) if (iter_init != NULL)
body->add_statement(Statement::make_block_statement(iter_init, loc)); body->add_statement(Statement::make_block_statement(iter_init, loc));
Statement* assign; if (this->index_var_ != NULL)
Expression* index_ref = Expression::make_temporary_reference(index_temp, loc);
if (this->value_var_ == NULL)
{ {
assign = Statement::make_assignment(this->index_var_, index_ref, loc); Statement* assign;
} Expression* index_ref =
else Expression::make_temporary_reference(index_temp, loc);
{ if (this->value_var_ == NULL)
Expression_list* lhs = new Expression_list(); assign = Statement::make_assignment(this->index_var_, index_ref, loc);
lhs->push_back(this->index_var_); else
lhs->push_back(this->value_var_); {
Expression_list* lhs = new Expression_list();
lhs->push_back(this->index_var_);
lhs->push_back(this->value_var_);
Expression_list* rhs = new Expression_list(); Expression_list* rhs = new Expression_list();
rhs->push_back(index_ref); rhs->push_back(index_ref);
rhs->push_back(Expression::make_temporary_reference(value_temp, loc)); rhs->push_back(Expression::make_temporary_reference(value_temp, loc));
assign = Statement::make_tuple_assignment(lhs, rhs, loc); assign = Statement::make_tuple_assignment(lhs, rhs, loc);
}
body->add_statement(assign);
} }
body->add_statement(assign);
body->add_statement(Statement::make_block_statement(this->statements_, loc)); body->add_statement(Statement::make_block_statement(this->statements_, loc));
......
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