compiler: fix bug in importing blocks from inline functions

This patch fixes a buglet in the function body importer. Add hooks for
keeping a stack of blocks corresponding to the block nesting in the
imported function. This ensures that local variables and temps wind up
correctly scoped and don't introduce collisions.

New test case for this problem in CL 186717.

Fixes golang/go#33158.

Change-Id: I5a2bf9bdbc505aa9258b69381e24f21df71d12d1
Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/186757
Reviewed-by: Ian Lance Taylor <iant@golang.org>
diff --git a/go/import.cc b/go/import.cc
index ad7ba7f..be71f04 100644
--- a/go/import.cc
+++ b/go/import.cc
@@ -1535,6 +1535,26 @@
 
 // Class Import_function_body.
 
+Import_function_body::Import_function_body(Gogo* gogo,
+                                           Import* imp,
+                                           Named_object* named_object,
+                                           const std::string& body,
+                                           size_t off,
+                                           Block* block,
+                                           int indent)
+    : gogo_(gogo), imp_(imp), named_object_(named_object), body_(body),
+      off_(off), indent_(indent), temporaries_(), labels_(),
+      saw_error_(false)
+{
+  this->blocks_.push_back(block);
+}
+
+Import_function_body::~Import_function_body()
+{
+  // At this point we should be left with the original outer block only.
+  go_assert(saw_errors() || this->blocks_.size() == 1);
+}
+
 // The name of the function we are parsing.
 
 const std::string&
diff --git a/go/import.h b/go/import.h
index ea01bbc..a78e48b 100644
--- a/go/import.h
+++ b/go/import.h
@@ -593,11 +593,8 @@
  public:
   Import_function_body(Gogo* gogo, Import* imp, Named_object* named_object,
 		       const std::string& body, size_t off, Block* block,
-		       int indent)
-    : gogo_(gogo), imp_(imp), named_object_(named_object), body_(body),
-      off_(off), block_(block), indent_(indent), temporaries_(), labels_(),
-      saw_error_(false)
-  { }
+		       int indent);
+  ~Import_function_body();
 
   // The IR.
   Gogo*
@@ -637,7 +634,17 @@
   // The current block.
   Block*
   block()
-  { return this->block_; }
+  { return this->blocks_.back(); }
+
+  // Begin importing a new block BLOCK nested within the current block.
+  void
+  begin_block(Block *block)
+  { this->blocks_.push_back(block); }
+
+  // Record the fact that we're done importing the current block.
+  void
+  finish_block()
+  { this->blocks_.pop_back(); }
 
   // The current indentation.
   int
@@ -757,8 +764,8 @@
   const std::string& body_;
   // The current offset into body_.
   size_t off_;
-  // Current block.
-  Block* block_;
+  // Stack to record nesting of blocks being imported.
+  std::vector<Block *> blocks_;
   // Current expected indentation level.
   int indent_;
   // Temporary statements by index.
diff --git a/go/statements.cc b/go/statements.cc
index b0b576f..27c4b95 100644
--- a/go/statements.cc
+++ b/go/statements.cc
@@ -2176,7 +2176,9 @@
   ifb->set_off(nl + 1);
   ifb->increment_indent();
   Block* block = new Block(ifb->block(), loc);
+  ifb->begin_block(block);
   bool ok = Block::import_block(block, ifb, loc);
+  ifb->finish_block();
   ifb->decrement_indent();
   if (!ok)
     return NULL;