compiler: fix bug in importing blocks from inline functions
authorIan Lance Taylor <ian@gcc.gnu.org>
Thu, 18 Jul 2019 16:51:00 +0000 (16:51 +0000)
committerIan Lance Taylor <ian@gcc.gnu.org>
Thu, 18 Jul 2019 16:51:00 +0000 (16:51 +0000)
    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.

    Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/186757

From-SVN: r273577

gcc/go/gofrontend/MERGE
gcc/go/gofrontend/import.cc
gcc/go/gofrontend/import.h
gcc/go/gofrontend/statements.cc

index c5ace5accbed8fcd953867a3cce6899da26ef288..ccc1a24be26bce25d991a31a762502b53d84d362 100644 (file)
@@ -1,4 +1,4 @@
-19ed722fb3ae5e618c746da20efb79fc837337cd
+4df7c8d7af894ee93f50c3a50debdcf4e369a2c6
 
 The first line of this file holds the git revision number of the last
 merge done from the gofrontend repository.
index ad7ba7fe3a4d251e8fe9944e25b15e616c930113..be71f041050a7206d19145825213505f874da0d3 100644 (file)
@@ -1535,6 +1535,26 @@ Stream_from_file::do_advance(size_t skip)
 
 // 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&
index ea01bbcfb4616e54edee296b5ecd8311602e164f..a78e48b7ca0d49e1d93e190206dd3d41eb6e3b33 100644 (file)
@@ -593,11 +593,8 @@ class Import_function_body : public Import_expression
  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 @@ class Import_function_body : public Import_expression
   // 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 @@ class Import_function_body : public Import_expression
   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.
index b0b576f8cbed42845d36ec2cbebf4689e58f46a0..27c4b95781d7aa532c86a2cb63179255ab2ff514 100644 (file)
@@ -2176,7 +2176,9 @@ Block_statement::do_import(Import_function_body* ifb, Location loc,
   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;