Patchwork Go patch committed: Don't look for break out of function literal

login
register
mail settings
Submitter Ian Taylor
Date Jan. 4, 2011, 10:17 p.m.
Message ID <mcrtyhonwjg.fsf@google.com>
Download mbox | patch
Permalink /patch/77541/
State New
Headers show

Comments

Ian Taylor - Jan. 4, 2011, 10:17 p.m.
This patch to the Go frontend avoids looking for the loop associated
with a break or continue statement outside of a function literal.
Bootstrapped and ran Go testsuite on x86_64-unknown-linux-gnu.
Committed to mainline.

Ian

Patch

diff -r 26a980d0c8d6 go/parse.cc
--- a/go/parse.cc	Tue Jan 04 14:15:00 2011 -0800
+++ b/go/parse.cc	Tue Jan 04 14:16:34 2011 -0800
@@ -46,8 +46,8 @@ 
     unget_token_(Token::make_invalid_token(0)),
     unget_token_valid_(false),
     gogo_(gogo),
-    break_stack_(),
-    continue_stack_(),
+    break_stack_(NULL),
+    continue_stack_(NULL),
     iota_(0),
     enclosing_vars_()
 {
@@ -2569,12 +2569,24 @@ 
   if (!this->peek_token()->is_op(OPERATOR_LCURLY))
     return Expression::make_type(type, location);
 
+  Bc_stack* hold_break_stack = this->break_stack_;
+  Bc_stack* hold_continue_stack = this->continue_stack_;
+  this->break_stack_ = NULL;
+  this->continue_stack_ = NULL;
+
   Named_object* no = this->gogo_->start_function("", type, true, location);
 
   source_location end_loc = this->block();
 
   this->gogo_->finish_function(end_loc);
 
+  if (this->break_stack_ != NULL)
+    delete this->break_stack_;
+  if (this->continue_stack_ != NULL)
+    delete this->continue_stack_;
+  this->break_stack_ = hold_break_stack;
+  this->continue_stack_ = hold_continue_stack;
+
   hold_enclosing_vars.swap(this->enclosing_vars_);
 
   Expression* closure = this->create_closure(no, &hold_enclosing_vars,
@@ -4515,7 +4527,9 @@ 
 void
 Parse::push_break_statement(Statement* enclosing, const Label* label)
 {
-  this->break_stack_.push_back(std::make_pair(enclosing, label));
+  if (this->break_stack_ == NULL)
+    this->break_stack_ = new Bc_stack();
+  this->break_stack_->push_back(std::make_pair(enclosing, label));
 }
 
 // Push a statement on the continue stack.
@@ -4523,7 +4537,9 @@ 
 void
 Parse::push_continue_statement(Statement* enclosing, const Label* label)
 {
-  this->continue_stack_.push_back(std::make_pair(enclosing, label));
+  if (this->continue_stack_ == NULL)
+    this->continue_stack_ = new Bc_stack();
+  this->continue_stack_->push_back(std::make_pair(enclosing, label));
 }
 
 // Pop the break stack.
@@ -4531,7 +4547,7 @@ 
 void
 Parse::pop_break_statement()
 {
-  this->break_stack_.pop_back();
+  this->break_stack_->pop_back();
 }
 
 // Pop the continue stack.
@@ -4539,7 +4555,7 @@ 
 void
 Parse::pop_continue_statement()
 {
-  this->continue_stack_.pop_back();
+  this->continue_stack_->pop_back();
 }
 
 // Find a break or continue statement given a label name.
@@ -4547,6 +4563,8 @@ 
 Statement*
 Parse::find_bc_statement(const Bc_stack* bc_stack, const std::string& label)
 {
+  if (bc_stack == NULL)
+    return NULL;
   for (Bc_stack::const_reverse_iterator p = bc_stack->rbegin();
        p != bc_stack->rend();
        ++p)
@@ -4567,17 +4585,17 @@ 
   Statement* enclosing;
   if (!token->is_identifier())
     {
-      if (this->break_stack_.empty())
+      if (this->break_stack_ == NULL || this->break_stack_->empty())
 	{
 	  error_at(this->location(),
 		   "break statement not within for or switch or select");
 	  return;
 	}
-      enclosing = this->break_stack_.back().first;
+      enclosing = this->break_stack_->back().first;
     }
   else
     {
-      enclosing = this->find_bc_statement(&this->break_stack_,
+      enclosing = this->find_bc_statement(this->break_stack_,
 					  token->identifier());
       if (enclosing == NULL)
 	{
@@ -4621,16 +4639,16 @@ 
   Statement* enclosing;
   if (!token->is_identifier())
     {
-      if (this->continue_stack_.empty())
+      if (this->continue_stack_ == NULL || this->continue_stack_->empty())
 	{
 	  error_at(this->location(), "continue statement not within for");
 	  return;
 	}
-      enclosing = this->continue_stack_.back().first;
+      enclosing = this->continue_stack_->back().first;
     }
   else
     {
-      enclosing = this->find_bc_statement(&this->continue_stack_,
+      enclosing = this->find_bc_statement(this->continue_stack_,
 					  token->identifier());
       if (enclosing == NULL)
 	{
diff -r 26a980d0c8d6 go/parse.h
--- a/go/parse.h	Tue Jan 04 14:15:00 2011 -0800
+++ b/go/parse.h	Tue Jan 04 14:16:34 2011 -0800
@@ -294,9 +294,9 @@ 
   // The code we are generating.
   Gogo* gogo_;
   // A stack of statements for which break may be used.
-  Bc_stack break_stack_;
+  Bc_stack* break_stack_;
   // A stack of statements for which continue may be used.
-  Bc_stack continue_stack_;
+  Bc_stack* continue_stack_;
   // The current iota value.
   int iota_;
   // References from the local function to variables defined in