compiler: Permit "for range x" clauses.
authorIan Lance Taylor <ian@gcc.gnu.org>
Thu, 9 Oct 2014 23:56:07 +0000 (23:56 +0000)
committerIan Lance Taylor <ian@gcc.gnu.org>
Thu, 9 Oct 2014 23:56:07 +0000 (23:56 +0000)
Fixes Issue 8370.

From-SVN: r216051

gcc/go/gofrontend/parse.cc
gcc/go/gofrontend/statements.cc

index fd54edfadfa93fa398a9036ce5576acccc21e46a..d77f462ee3e110d735777dbc886cee68a1309b00 100644 (file)
@@ -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;
index f8478051f94df264a6686869fc21274c6f7b17bc..69073b509130babccec5f3583797178986e8610c 100644 (file)
@@ -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));