aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2014-10-09 23:56:07 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2014-10-09 23:56:07 +0000
commitea411f8480a938fffab00a22b4405032689a6e50 (patch)
tree3d641cc1b7ab99508201c2ccffe850a875d924f4 /gcc
parent3369b9193606b86677e65bc96699939fb6a8d13e (diff)
downloadgcc-ea411f8480a938fffab00a22b4405032689a6e50.zip
gcc-ea411f8480a938fffab00a22b4405032689a6e50.tar.gz
gcc-ea411f8480a938fffab00a22b4405032689a6e50.tar.bz2
compiler: Permit "for range x" clauses.
Fixes Issue 8370. From-SVN: r216051
Diffstat (limited to 'gcc')
-rw-r--r--gcc/go/gofrontend/parse.cc15
-rw-r--r--gcc/go/gofrontend/statements.cc40
2 files changed, 36 insertions, 19 deletions
diff --git a/gcc/go/gofrontend/parse.cc b/gcc/go/gofrontend/parse.cc
index fd54edf..d77f462 100644
--- a/gcc/go/gofrontend/parse.cc
+++ b/gcc/go/gofrontend/parse.cc
@@ -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,
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,
may_be_composite_lit,
@@ -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.
@@ -5291,7 +5297,6 @@ Parse::range_clause_decl(const Typed_identifier_list* til,
p_range_clause->found = true;
- go_assert(til->size() >= 1);
if (til->size() > 2)
error_at(this->location(), "too many variables for range clause");
@@ -5300,6 +5305,9 @@ Parse::range_clause_decl(const Typed_identifier_list* til,
NULL);
p_range_clause->range = expr;
+ if (til->empty())
+ return;
+
bool any_new = false;
const Typed_identifier* pti = &til->front();
@@ -5347,6 +5355,9 @@ Parse::range_clause_expr(const Expression_list* vals,
p_range_clause->range = this->expression(PRECEDENCE_NORMAL, false, false,
NULL, NULL);
+ if (vals->empty())
+ return;
+
p_range_clause->index = vals->front();
if (vals->size() == 1)
p_range_clause->value = NULL;
diff --git a/gcc/go/gofrontend/statements.cc b/gcc/go/gofrontend/statements.cc
index f847805..69073b5 100644
--- a/gcc/go/gofrontend/statements.cc
+++ b/gcc/go/gofrontend/statements.cc
@@ -5305,8 +5305,12 @@ Statement::make_for_statement(Block* init, Expression* cond, Block* post,
int
For_range_statement::do_traverse(Traverse* traverse)
{
- if (this->traverse_expression(traverse, &this->index_var_) == TRAVERSE_EXIT)
- return TRAVERSE_EXIT;
+ if (this->index_var_ != NULL)
+ {
+ if (this->traverse_expression(traverse, &this->index_var_)
+ == TRAVERSE_EXIT)
+ return TRAVERSE_EXIT;
+ }
if (this->value_var_ != NULL)
{
if (this->traverse_expression(traverse, &this->value_var_)
@@ -5434,25 +5438,27 @@ For_range_statement::do_lower(Gogo* gogo, Named_object*, Block* enclosing,
if (iter_init != NULL)
body->add_statement(Statement::make_block_statement(iter_init, loc));
- Statement* assign;
- Expression* index_ref = Expression::make_temporary_reference(index_temp, loc);
- if (this->value_var_ == NULL)
+ if (this->index_var_ != NULL)
{
- assign = Statement::make_assignment(this->index_var_, index_ref, loc);
- }
- else
- {
- Expression_list* lhs = new Expression_list();
- lhs->push_back(this->index_var_);
- lhs->push_back(this->value_var_);
+ Statement* assign;
+ 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);
+ else
+ {
+ Expression_list* lhs = new Expression_list();
+ lhs->push_back(this->index_var_);
+ lhs->push_back(this->value_var_);
- Expression_list* rhs = new Expression_list();
- rhs->push_back(index_ref);
- rhs->push_back(Expression::make_temporary_reference(value_temp, loc));
+ Expression_list* rhs = new Expression_list();
+ rhs->push_back(index_ref);
+ 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));