diff mbox

[gccgo] Thunk statements need not be the only statements in a block

Message ID mcr39sg2z4w.fsf@google.com
State New
Headers show

Commit Message

Ian Lance Taylor Oct. 8, 2010, 8:44 p.m. UTC
The Go parser arranges for thunk statements (from go and defer
statements in the language) to be the only statements in their block.
The code which simplifies these statements was assuming that.  However,
it is possible for the passes which enforce order of evaluation to break
the thunk statements into multiple statements.  This patch fixes the
simplification code to assume that the thunk statement is the last
statement in the block, rather than assuming that it is the only
statement in the block.  Committed to gccgo branch.

Ian
diff mbox

Patch

diff -r 5f836c41c4e8 go/gogo.h
--- a/go/gogo.h	Fri Oct 08 13:37:52 2010 -0700
+++ b/go/gogo.h	Fri Oct 08 13:42:06 2010 -0700
@@ -856,11 +856,6 @@ 
   void
   determine_types();
 
-  // Swap the block's statements with STATEMENTS.
-  void
-  swap_statements(std::vector<Statement*>& statements)
-  { this->statements_.swap(statements); }
-
   // Return true if execution of this block may fall through to the
   // next block.
   bool
diff -r 5f836c41c4e8 go/statements.cc
--- a/go/statements.cc	Fri Oct 08 13:37:52 2010 -0700
+++ b/go/statements.cc	Fri Oct 08 13:42:06 2010 -0700
@@ -1768,11 +1768,11 @@ 
 int
 Simplify_thunk_traverse::block(Block* b)
 {
-  // The parser ensures that thunk statements always appear in a block
-  // which has only a single statement.
-  if (b->statements()->size() != 1)
+  // The parser ensures that thunk statements always appear at the end
+  // of a block.
+  if (b->statements()->size() < 1)
     return TRAVERSE_CONTINUE;
-  Thunk_statement* stat = b->statements()->front()->thunk_statement();
+  Thunk_statement* stat = b->statements()->back()->thunk_statement();
   if (stat == NULL)
     return TRAVERSE_CONTINUE;
   if (stat->simplify_statement(this->gogo_, b))
@@ -1897,16 +1897,14 @@ 
   else
     gcc_unreachable();
 
-  // The current block should only have the go statement.
-  gcc_assert(block->statements()->size() == 1);
-  gcc_assert(block->statements()->front() == this);
-  std::vector<Statement*> statements;
-  statements.push_back(s);
-  block->swap_statements(statements);
+  // The current block should end with the go statement.
+  gcc_assert(block->statements()->size() >= 1);
+  gcc_assert(block->statements()->back() == this);
+  block->replace_statement(block->statements()->size() - 1, s);
 
   // We already ran the determine_types pass, so we need to run it now
-  // for this new block.
-  block->determine_types();
+  // for the new statement.
+  s->determine_types();
 
   // Sanity check.
   gogo->check_types_in_block(block);