compiler: Fix -fgo-prefix handling.

There was bug in the fix for PR 61880: it only worked fully
correctly for code compiled with -fgo-pkgpath.  For code that
used -fgo-prefix, or that used neither option, the '.'
separating the prefix and the package name was converted to an
underscore, which did not happen before.  This broke SWIG and
any other code that expected specific symbol names.
Fortunately all code compiled in libgo and all code compiled
by the go tool uses -fgo-pkgpath, so this probably did not
affect very many people.

This is an incomplete fix that does not modify the package
file format, for use on both mainline and the GCC 4.9 branch.
A follow on patch will fully fix the problem.

From-SVN: r220268
This commit is contained in:
Ian Lance Taylor 2015-01-30 00:35:44 +00:00
parent 15b127290b
commit 2e29434de9
6 changed files with 103 additions and 25 deletions

View File

@ -91,6 +91,7 @@ should_export(Named_object* no)
void
Export::export_globals(const std::string& package_name,
const std::string& prefix,
const std::string& pkgpath,
int package_priority,
const std::map<std::string, Package*>& imports,
@ -140,9 +141,18 @@ Export::export_globals(const std::string& package_name,
this->write_string(package_name);
this->write_c_string(";\n");
// The package path, used for all global symbols.
this->write_c_string("pkgpath ");
this->write_string(pkgpath);
// The prefix or package path, used for all global symbols.
if (prefix.empty())
{
go_assert(!pkgpath.empty());
this->write_c_string("pkgpath ");
this->write_string(pkgpath);
}
else
{
this->write_c_string("prefix ");
this->write_string(prefix);
}
this->write_c_string(";\n");
// The package priority.

View File

@ -117,14 +117,17 @@ class Export : public String_dump
// Export the identifiers in BINDINGS which are marked for export.
// The exporting is done via a series of calls to THIS->STREAM_. If
// is nothing to export, this->stream_->write will not be called.
// PKGPATH is the package path.
// PREFIX is the package prefix. PKGPATH is the package path.
// Only one of PREFIX and PKGPATH will be non-empty.
// PACKAGE_PRIORITY is the priority to use for this package.
// IMPORTS is the explicitly imported packages.
// IMPORT_INIT_FN is the name of the import initialization function
// for this package; it will be empty if none is needed.
// IMPORTED_INIT_FNS is the list of initialization functions for
// imported packages.
void
export_globals(const std::string& package_name,
const std::string& prefix,
const std::string& pkgpath,
int package_priority,
const std::map<std::string, Package*>& imports,

View File

@ -341,22 +341,28 @@ Gogo::set_package_name(const std::string& package_name,
// Now that we know the name of the package we are compiling, set
// the package path to use for reflect.Type.PkgPath and global
// symbol names.
if (!this->pkgpath_set_)
if (this->pkgpath_set_)
this->pkgpath_symbol_ = Gogo::pkgpath_for_symbol(this->pkgpath_);
else
{
if (!this->prefix_from_option_ && package_name == "main")
this->pkgpath_ = package_name;
{
this->pkgpath_ = package_name;
this->pkgpath_symbol_ = Gogo::pkgpath_for_symbol(package_name);
}
else
{
if (!this->prefix_from_option_)
this->prefix_ = "go";
this->pkgpath_ = this->prefix_ + '.' + package_name;
this->pkgpath_symbol_ = (Gogo::pkgpath_for_symbol(this->prefix_) + '.'
+ Gogo::pkgpath_for_symbol(package_name));
}
this->pkgpath_set_ = true;
}
this->pkgpath_symbol_ = Gogo::pkgpath_for_symbol(this->pkgpath_);
this->package_ = this->register_package(this->pkgpath_, location);
this->package_ = this->register_package(this->pkgpath_,
this->pkgpath_symbol_, location);
this->package_->set_package_name(package_name, location);
if (this->is_main_package())
@ -1524,10 +1530,11 @@ Gogo::add_imported_package(const std::string& real_name,
const std::string& alias_arg,
bool is_alias_exported,
const std::string& pkgpath,
const std::string& pkgpath_symbol,
Location location,
bool* padd_to_globals)
{
Package* ret = this->register_package(pkgpath, location);
Package* ret = this->register_package(pkgpath, pkgpath_symbol, location);
ret->set_package_name(real_name, location);
*padd_to_globals = false;
@ -1556,10 +1563,13 @@ Gogo::add_imported_package(const std::string& real_name,
// Register a package. This package may or may not be imported. This
// returns the Package structure for the package, creating if it
// necessary. LOCATION is the location of the import statement that
// led us to see this package.
// led us to see this package. PKGPATH_SYMBOL is the symbol to use
// for names in the package; it may be the empty string, in which case
// we either get it later or make a guess when we need it.
Package*
Gogo::register_package(const std::string& pkgpath, Location location)
Gogo::register_package(const std::string& pkgpath,
const std::string& pkgpath_symbol, Location location)
{
Package* package = NULL;
std::pair<Packages::iterator, bool> ins =
@ -1569,13 +1579,15 @@ Gogo::register_package(const std::string& pkgpath, Location location)
// We have seen this package name before.
package = ins.first->second;
go_assert(package != NULL && package->pkgpath() == pkgpath);
if (!pkgpath_symbol.empty())
package->set_pkgpath_symbol(pkgpath_symbol);
if (Linemap::is_unknown_location(package->location()))
package->set_location(location);
}
else
{
// First time we have seen this package name.
package = new Package(pkgpath, location);
package = new Package(pkgpath, pkgpath_symbol, location);
go_assert(ins.first->second == NULL);
ins.first->second = package;
}
@ -4333,10 +4345,24 @@ Gogo::do_exports()
// support streaming to a separate file.
Stream_to_section stream;
// Write out either the prefix or pkgpath depending on how we were
// invoked.
std::string prefix;
std::string pkgpath;
if (this->pkgpath_from_option_)
pkgpath = this->pkgpath_;
else if (this->prefix_from_option_)
prefix = this->prefix_;
else if (this->is_main_package())
pkgpath = "main";
else
prefix = "go";
Export exp(&stream);
exp.register_builtin_types(this);
exp.export_globals(this->package_name(),
this->pkgpath(),
prefix,
pkgpath,
this->package_priority(),
this->imports_,
(this->need_init_fn_ && !this->is_main_package()
@ -7478,8 +7504,9 @@ Unnamed_label::get_goto(Translate_context* context, Location location)
// Class Package.
Package::Package(const std::string& pkgpath, Location location)
: pkgpath_(pkgpath), pkgpath_symbol_(Gogo::pkgpath_for_symbol(pkgpath)),
Package::Package(const std::string& pkgpath,
const std::string& pkgpath_symbol, Location location)
: pkgpath_(pkgpath), pkgpath_symbol_(pkgpath_symbol),
package_name_(), bindings_(new Bindings(NULL)), priority_(0),
location_(location), used_(false), is_imported_(false),
uses_sink_alias_(false)
@ -7503,6 +7530,34 @@ Package::set_package_name(const std::string& package_name, Location location)
package_name.c_str());
}
// Return the pkgpath symbol, which is a prefix for symbols defined in
// this package.
std::string
Package::pkgpath_symbol() const
{
if (this->pkgpath_symbol_.empty())
{
// In the general case, this is wrong, because the package might
// have been compiled with -fprefix. However, it is what we
// used to do, so it is no more wrong than we were before.
return Gogo::pkgpath_for_symbol(this->pkgpath_);
}
return this->pkgpath_symbol_;
}
// Set the package path symbol.
void
Package::set_pkgpath_symbol(const std::string& pkgpath_symbol)
{
go_assert(!pkgpath_symbol.empty());
if (this->pkgpath_symbol_.empty())
this->pkgpath_symbol_ = pkgpath_symbol;
else
go_assert(this->pkgpath_symbol_ == pkgpath_symbol);
}
// Set the priority. We may see multiple priorities for an imported
// package; we want to use the largest one.

View File

@ -276,6 +276,7 @@ class Gogo
add_imported_package(const std::string& real_name, const std::string& alias,
bool is_alias_exported,
const std::string& pkgpath,
const std::string& pkgpath_symbol,
Location location,
bool* padd_to_globals);
@ -283,7 +284,8 @@ class Gogo
// This returns the Package structure for the package, creating if
// it necessary.
Package*
register_package(const std::string& pkgpath, Location);
register_package(const std::string& pkgpath,
const std::string& pkgpath_symbol, Location);
// Start compiling a function. ADD_METHOD_TO_TYPE is true if a
// method function should be added to the type of its receiver.
@ -2622,7 +2624,8 @@ class Unnamed_label
class Package
{
public:
Package(const std::string& pkgpath, Location location);
Package(const std::string& pkgpath, const std::string& pkgpath_symbol,
Location location);
// Get the package path used for all symbols exported from this
// package.
@ -2631,9 +2634,12 @@ class Package
{ return this->pkgpath_; }
// Return the package path to use for a symbol name.
const std::string&
pkgpath_symbol() const
{ return this->pkgpath_symbol_; }
std::string
pkgpath_symbol() const;
// Set the package path symbol.
void
set_pkgpath_symbol(const std::string&);
// Return the location of the import statement.
Location

View File

@ -301,23 +301,27 @@ Import::import(Gogo* gogo, const std::string& local_name,
this->require_c_string(";\n");
std::string pkgpath;
std::string pkgpath_symbol;
if (this->match_c_string("prefix "))
{
this->advance(7);
std::string unique_prefix = this->read_identifier();
this->require_c_string(";\n");
pkgpath = unique_prefix + '.' + package_name;
pkgpath_symbol = (Gogo::pkgpath_for_symbol(unique_prefix) + '.'
+ Gogo::pkgpath_for_symbol(package_name));
}
else
{
this->require_c_string("pkgpath ");
pkgpath = this->read_identifier();
this->require_c_string(";\n");
pkgpath_symbol = Gogo::pkgpath_for_symbol(pkgpath);
}
this->package_ = gogo->add_imported_package(package_name, local_name,
is_local_name_exported,
pkgpath,
pkgpath, pkgpath_symbol,
this->location_,
&this->add_to_globals_);
if (this->package_ == NULL)
@ -392,7 +396,7 @@ Import::read_one_import()
stream->advance(1);
this->require_c_string("\";\n");
Package* p = this->gogo_->register_package(pkgpath,
Package* p = this->gogo_->register_package(pkgpath, "",
Linemap::unknown_location());
p->set_package_name(package_name, this->location());
}
@ -649,7 +653,7 @@ Import::read_type()
package = this->package_;
else
{
package = this->gogo_->register_package(pkgpath,
package = this->gogo_->register_package(pkgpath, "",
Linemap::unknown_location());
if (!package_name.empty())
package->set_package_name(package_name, this->location());

View File

@ -22,7 +22,7 @@ Gogo::import_unsafe(const std::string& local_name, bool is_local_name_exported,
bool add_to_globals;
Package* package = this->add_imported_package("unsafe", local_name,
is_local_name_exported,
"unsafe", location,
"unsafe", "unsafe", location,
&add_to_globals);
if (package == NULL)