compiler: Fix -fgo-prefix handling.
authorIan Lance Taylor <ian@gcc.gnu.org>
Fri, 30 Jan 2015 00:35:44 +0000 (00:35 +0000)
committerIan Lance Taylor <ian@gcc.gnu.org>
Fri, 30 Jan 2015 00:35:44 +0000 (00:35 +0000)
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

gcc/go/gofrontend/export.cc
gcc/go/gofrontend/export.h
gcc/go/gofrontend/gogo.cc
gcc/go/gofrontend/gogo.h
gcc/go/gofrontend/import.cc
gcc/go/gofrontend/unsafe.cc

index 13c61a589fe2f03b956c6ffe5f453411bd305d83..e37f03446c1b3763b21daf511c95121297a5a857 100644 (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.
index c6a4810510a308f25aefd9c340e96a22ba03c9a0..c010a14686c115f608c539a7488e29f2327aa751 100644 (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,
index 252560d9e353ccd7194fd7d5032e079b843d51f5..9039ce3ab9d3db958fb05e29b1739f9f36a489e8 100644 (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.
 
index 8a1663703aac4661e8810efc3767d557d51b3a3f..c5a71abea94c97d8dd496e08b999581a26990d43 100644 (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
index c83ebe29853e7663163d41f7b4602514768e0ea1..cfc042976f3e7b77fcd77bfb1858f04101c4b424 100644 (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());
index 9b5ec44ad09f510c74322522d200f46a61bd031f..ca9622569bd3860414b0c4a2c9db404a57b593d9 100644 (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)