This patch to the Go frontend fixes it so that a name included because of a dot import (import . "package") is not merged with the same name defined in an earlier file. Without this patch, the Go compiler would incorrectly accept code that used a name defined by a dot import in a later file. I've sent out a change to add a test to the master testsuite: http://codereview.appspot.com/118000043 . For this patch, bootstrapped and ran Go testsuite on x86_64-unknown-linux-gnu. Committed to mainline.
Ian
diff -r 0e313c250b05 go/gogo.cc --- a/go/gogo.cc Sun Jul 20 08:08:44 2014 -0700 +++ b/go/gogo.cc Sun Jul 20 08:11:43 2014 -0700 @@ -473,7 +473,7 @@ bindings->begin_declarations(); p != bindings->end_declarations(); ++p) - this->add_named_object(p->second); + this->add_dot_import_object(p->second); } else if (ln == "_") package->set_uses_sink_alias(); @@ -1968,11 +1968,32 @@ return Named_object::make_sink(); } -// Add a named object. +// Add a named object for a dot import. void -Gogo::add_named_object(Named_object* no) -{ +Gogo::add_dot_import_object(Named_object* no) +{ + // If the name already exists, then it was defined in some file seen + // earlier. If the earlier name is just a declaration, don't add + // this name, because that will cause the previous declaration to + // merge to this imported name, which should not happen. Just add + // this name to the list of file block names to get appropriate + // errors if we see a later definition. + Named_object* e = this->package_->bindings()->lookup(no->name()); + if (e != NULL && e->package() == NULL) + { + if (e->is_unknown()) + e = e->resolve(); + if (e->package() == NULL + && (e->is_type_declaration() + || e->is_function_declaration() + || e->is_unknown())) + { + this->add_file_block_name(no->name(), no->location()); + return; + } + } + this->current_bindings()->add_named_object(no); } diff -r 0e313c250b05 go/gogo.h --- a/go/gogo.h Sun Jul 20 08:08:44 2014 -0700 +++ b/go/gogo.h Sun Jul 20 08:11:43 2014 -0700 @@ -397,7 +397,7 @@ // Add a named object to the current namespace. This is used for // import . "package". void - add_named_object(Named_object*); + add_dot_import_object(Named_object*); // Add an identifier to the list of names seen in the file block. void diff -r 0e313c250b05 go/import.cc --- a/go/import.cc Sun Jul 20 08:08:44 2014 -0700 +++ b/go/import.cc Sun Jul 20 08:11:43 2014 -0700 @@ -431,7 +431,7 @@ Typed_identifier tid(name, type, this->location_); Named_object* no = this->package_->add_constant(tid, expr); if (this->add_to_globals_) - this->gogo_->add_named_object(no); + this->gogo_->add_dot_import_object(no); } // Import a type. @@ -464,7 +464,7 @@ Named_object* no; no = this->package_->add_variable(name, var); if (this->add_to_globals_) - this->gogo_->add_named_object(no); + this->gogo_->add_dot_import_object(no); } // Import a function into PACKAGE. PACKAGE is normally @@ -518,7 +518,7 @@ { no = package->add_function_declaration(name, fntype, loc); if (this->add_to_globals_) - this->gogo_->add_named_object(no); + this->gogo_->add_dot_import_object(no); } return no; } diff -r 0e313c250b05 go/unsafe.cc --- a/go/unsafe.cc Sun Jul 20 08:08:44 2014 -0700 +++ b/go/unsafe.cc Sun Jul 20 08:11:43 2014 -0700 @@ -66,7 +66,7 @@ fntype->set_is_builtin(); no = bindings->add_function_declaration("Sizeof", package, fntype, bloc); if (add_to_globals) - this->add_named_object(no); + this->add_dot_import_object(no); // Offsetof. results = new Typed_identifier_list; @@ -76,7 +76,7 @@ fntype->set_is_builtin(); no = bindings->add_function_declaration("Offsetof", package, fntype, bloc); if (add_to_globals) - this->add_named_object(no); + this->add_dot_import_object(no); // Alignof. results = new Typed_identifier_list; @@ -86,7 +86,7 @@ fntype->set_is_builtin(); no = bindings->add_function_declaration("Alignof", package, fntype, bloc); if (add_to_globals) - this->add_named_object(no); + this->add_dot_import_object(no); if (!this->imported_unsafe_) {