This Go frontend patch by Than McIntosh fixes a buglet in the function body importer. It adds 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.
There is a new test case for this problem in https://golang.org/cl/186717. This fixes https://golang.org/issue/33158. Bootstrapped and ran Go testsuite on x86_64-pc-linux-gnu. Committed to mainline. Ian
Index: gcc/go/gofrontend/MERGE =================================================================== --- gcc/go/gofrontend/MERGE (revision 273564) +++ gcc/go/gofrontend/MERGE (working copy) @@ -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: gcc/go/gofrontend/import.cc =================================================================== --- gcc/go/gofrontend/import.cc (revision 273534) +++ gcc/go/gofrontend/import.cc (working copy) @@ -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: gcc/go/gofrontend/import.h =================================================================== --- gcc/go/gofrontend/import.h (revision 273534) +++ gcc/go/gofrontend/import.h (working copy) @@ -593,11 +593,8 @@ class Import_function_body : public Impo 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 Impo // 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 Impo 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: gcc/go/gofrontend/statements.cc =================================================================== --- gcc/go/gofrontend/statements.cc (revision 273534) +++ gcc/go/gofrontend/statements.cc (working copy) @@ -2176,7 +2176,9 @@ Block_statement::do_import(Import_functi 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;