OSDN Git Service

compiler: Add -fgo-pkgpath option.
authorian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 9 May 2012 23:30:17 +0000 (23:30 +0000)
committerian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 9 May 2012 23:30:17 +0000 (23:30 +0000)
* lang.opt: Add -fgo-pkgpath.
* go-lang.c (go_pkgpath): New static variable.
(go_prefix): New static variable.
(go_langhook_init): Pass go_pkgpath and go_prefix to
go_create_gogo.
(go_langhook_handle_option): Handle -fgo-pkgpath.  Change
-fgo-prefix handling to just set go_prefix.
* go-c.h (go_set_prefix): Don't declare.
(go_create_gogo): Add pkgpath and prefix to declaration.
* go-gcc.cc (Gcc_backend::global_variable): Change unique_prefix
to pkgpath.  Don't include the package name in the asm name.
* gccgo.texi (Invoking gccgo): Document -fgo-pkgpath.  Update the
docs for -fgo-prefix.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/gcc-4_7-branch@187357 138bc75d-0d04-0410-961f-82ee72b054a4

17 files changed:
gcc/go/ChangeLog
gcc/go/gccgo.texi
gcc/go/go-c.h
gcc/go/go-gcc.cc
gcc/go/go-lang.c
gcc/go/gofrontend/backend.h
gcc/go/gofrontend/export.cc
gcc/go/gofrontend/export.h
gcc/go/gofrontend/go.cc
gcc/go/gofrontend/gogo-tree.cc
gcc/go/gofrontend/gogo.cc
gcc/go/gofrontend/gogo.h
gcc/go/gofrontend/import.cc
gcc/go/gofrontend/parse.cc
gcc/go/gofrontend/types.cc
gcc/go/gofrontend/unsafe.cc
gcc/go/lang.opt

index 668735b..464ad9d 100644 (file)
@@ -1,3 +1,19 @@
+2012-05-09  Ian Lance Taylor  <iant@google.com>
+
+       * lang.opt: Add -fgo-pkgpath.
+       * go-lang.c (go_pkgpath): New static variable.
+       (go_prefix): New static variable.
+       (go_langhook_init): Pass go_pkgpath and go_prefix to
+       go_create_gogo.
+       (go_langhook_handle_option): Handle -fgo-pkgpath.  Change
+       -fgo-prefix handling to just set go_prefix.
+       * go-c.h (go_set_prefix): Don't declare.
+       (go_create_gogo): Add pkgpath and prefix to declaration.
+       * go-gcc.cc (Gcc_backend::global_variable): Change unique_prefix
+       to pkgpath.  Don't include the package name in the asm name.
+       * gccgo.texi (Invoking gccgo): Document -fgo-pkgpath.  Update the
+       docs for -fgo-prefix.
+
 2012-04-23  Ian Lance Taylor  <iant@google.com>
 
        * go-lang.c (go_langhook_init): Set MPFR precision to 256.
index 2a71cd2..a5e37e7 100644 (file)
@@ -12,7 +12,7 @@
 @include gcc-common.texi
 
 @c Copyright years for this manual.
-@set copyrights-go 2010
+@set copyrights-go 2010, 2011, 2012
 
 @copying
 @c man begin COPYRIGHT
@@ -157,14 +157,32 @@ compile time.
 When linking, specify a library search directory, as with
 @command{gcc}.
 
+@item -fgo-pkgpath=@var{string}
+@cindex @option{-fgo-pkgpath}
+Set the package path to use.  This sets the value returned by the
+PkgPath method of reflect.Type objects.  It is also used for the names
+of globally visible symbols.  The argument to this option should
+normally be the string that will be used to import this package after
+it has been installed; in other words, a pathname within the
+directories specified by the @option{-I} option.
+
 @item -fgo-prefix=@var{string}
 @cindex @option{-fgo-prefix}
+An alternative to @option{-fgo-pkgpath}.  The argument will be
+combined with the package name from the source file to produce the
+package path.  If @option{-fgo-pkgpath} is used, @option{-fgo-prefix}
+will be ignored.
+
 Go permits a single program to include more than one package with the
-same name.  This option is required to make this work with
-@command{gccgo}.  The argument to this option may be any string.  Each
-package with the same name must use a distinct @option{-fgo-prefix}
-option.  The argument is typically the full path under which the
-package will be installed, as that must obviously be unique.
+same name in the @code{package} clause in the source file, though
+obviously the two packages must be imported using different pathnames.
+In order for this to work with @command{gccgo}, either
+@option{-fgo-pkgpath} or @option{-fgo-prefix} must be specified when
+compiling a package.
+
+Using either @option{-fgo-pkgpath} or @option{-fgo-prefix} disables
+the special treatment of the @code{main} package and permits that
+package to be imported like any other.
 
 @item -frequire-return-statement
 @itemx -fno-require-return-statement
index e123d52..d46a087 100644 (file)
@@ -38,11 +38,11 @@ extern "C"
 
 extern int go_enable_dump (const char*);
 extern int go_enable_optimize (const char*);
-extern void go_set_prefix (const char*);
 
 extern void go_add_search_path (const char*);
 
-extern void go_create_gogo (int int_type_size, int pointer_size);
+extern void go_create_gogo (int int_type_size, int pointer_size,
+                           const char* pkgpath, const char *prefix);
 
 extern void go_parse_input_files (const char**, unsigned int,
                                  bool only_check_syntax,
index 96c1718..1867993 100644 (file)
@@ -271,7 +271,7 @@ class Gcc_backend : public Backend
 
   Bvariable*
   global_variable(const std::string& package_name,
-                 const std::string& unique_prefix,
+                 const std::string& pkgpath,
                  const std::string& name,
                  Btype* btype,
                  bool is_external,
@@ -1281,7 +1281,7 @@ Gcc_backend::non_zero_size_type(tree type)
 
 Bvariable*
 Gcc_backend::global_variable(const std::string& package_name,
-                            const std::string& unique_prefix,
+                            const std::string& pkgpath,
                             const std::string& name,
                             Btype* btype,
                             bool is_external,
@@ -1310,9 +1310,9 @@ Gcc_backend::global_variable(const std::string& package_name,
     {
       TREE_PUBLIC(decl) = 1;
 
-      std::string asm_name(unique_prefix);
+      std::string asm_name(pkgpath);
       asm_name.push_back('.');
-      asm_name.append(var_name);
+      asm_name.append(name);
       SET_DECL_ASSEMBLER_NAME(decl, get_identifier_from_string(asm_name));
     }
   TREE_USED(decl) = 1;
index 895e39d..f02f769 100644 (file)
@@ -81,6 +81,11 @@ struct GTY(()) language_function
   int dummy;
 };
 
+/* Option information we need to pass to go_create_gogo.  */
+
+static const char *go_pkgpath = NULL;
+static const char *go_prefix = NULL;
+
 /* Language hooks.  */
 
 static bool
@@ -96,7 +101,7 @@ go_langhook_init (void)
      to, e.g., unsigned_char_type_node) but before calling
      build_common_builtin_nodes (because it calls, indirectly,
      go_type_for_size).  */
-  go_create_gogo (INT_TYPE_SIZE, POINTER_SIZE);
+  go_create_gogo (INT_TYPE_SIZE, POINTER_SIZE, go_pkgpath, go_prefix);
 
   build_common_builtin_nodes ();
 
@@ -227,8 +232,12 @@ go_langhook_handle_option (
       ret = go_enable_optimize (arg) ? true : false;
       break;
 
+    case OPT_fgo_pkgpath_:
+      go_pkgpath = arg;
+      break;
+
     case OPT_fgo_prefix_:
-      go_set_prefix (arg);
+      go_prefix = arg;
       break;
 
     default:
index d314045..2b14132 100644 (file)
@@ -321,16 +321,16 @@ class Backend
   error_variable() = 0;
 
   // Create a global variable.  PACKAGE_NAME is the name of the
-  // package where the variable is defined.  UNIQUE_PREFIX is the
-  // prefix for that package, from the -fgo-prefix option.  NAME is
-  // the name of the variable.  BTYPE is the type of the variable.
-  // IS_EXTERNAL is true if the variable is defined in some other
-  // package.  IS_HIDDEN is true if the variable is not exported (name
-  // begins with a lower case letter).  LOCATION is where the variable
-  // was defined.
+  // package where the variable is defined.  PKGPATH is the package
+  // path for that package, from the -fgo-pkgpath or -fgo-prefix
+  // option.  NAME is the name of the variable.  BTYPE is the type of
+  // the variable.  IS_EXTERNAL is true if the variable is defined in
+  // some other package.  IS_HIDDEN is true if the variable is not
+  // exported (name begins with a lower case letter).  LOCATION is
+  // where the variable was defined.
   virtual Bvariable*
   global_variable(const std::string& package_name,
-                 const std::string& unique_prefix,
+                 const std::string& pkgpath,
                  const std::string& name,
                  Btype* btype,
                  bool is_external,
index 1745967..13c61a5 100644 (file)
@@ -33,7 +33,7 @@ const int Export::v1_checksum_len;
 // Constructor.
 
 Export::Export(Stream* stream)
-  : stream_(stream), type_refs_(), type_index_(1)
+  : stream_(stream), type_refs_(), type_index_(1), packages_()
 {
 }
 
@@ -91,7 +91,7 @@ should_export(Named_object* no)
 
 void
 Export::export_globals(const std::string& package_name,
-                      const std::string& unique_prefix,
+                      const std::string& pkgpath,
                       int package_priority,
                       const std::map<std::string, Package*>& imports,
                       const std::string& import_init_fn,
@@ -140,9 +140,9 @@ Export::export_globals(const std::string& package_name,
   this->write_string(package_name);
   this->write_c_string(";\n");
 
-  // The unique prefix.  This prefix is used for all global symbols.
-  this->write_c_string("prefix ");
-  this->write_string(unique_prefix);
+  // The package path, used for all global symbols.
+  this->write_c_string("pkgpath ");
+  this->write_string(pkgpath);
   this->write_c_string(";\n");
 
   // The package priority.
@@ -209,12 +209,14 @@ Export::write_imports(const std::map<std::string, Package*>& imports)
        ++p)
     {
       this->write_c_string("import ");
-      this->write_string(p->second->name());
+      this->write_string(p->second->package_name());
       this->write_c_string(" ");
-      this->write_string(p->second->unique_prefix());
+      this->write_string(p->second->pkgpath());
       this->write_c_string(" \"");
       this->write_string(p->first);
       this->write_c_string("\";\n");
+
+      this->packages_.insert(p->second);
     }
 }
 
@@ -333,7 +335,7 @@ Export::write_type(const Type* type)
        {
          // The builtin types should have been predefined.
          go_assert(!Linemap::is_predeclared_location(named_type->location())
-                    || (named_type->named_object()->package()->name()
+                    || (named_type->named_object()->package()->package_name()
                         == "unsafe"));
          named_object = named_type->named_object();
        }
@@ -345,15 +347,26 @@ Export::write_type(const Type* type)
       std::string s = "\"";
       if (package != NULL && !Gogo::is_hidden_name(named_object->name()))
        {
-         s += package->unique_prefix();
-         s += '.';
-         s += package->name();
+         s += package->pkgpath();
          s += '.';
        }
       s += named_object->name();
       s += "\" ";
       this->write_string(s);
 
+      // It is possible that this type was imported indirectly, and is
+      // not in a package in the import list.  If we have not
+      // mentioned this package before, write out the package name
+      // here so that any package importing this one will know it.
+      if (package != NULL
+         && this->packages_.find(package) == this->packages_.end())
+       {
+         this->write_c_string("\"");
+         this->write_string(package->package_name());
+         this->packages_.insert(package);
+         this->write_c_string("\" ");
+       }
+
       // We must add a named type to the table now, since the
       // definition of the type may refer to the named type via a
       // pointer.
index 0e03f48..c6a4810 100644 (file)
@@ -117,7 +117,7 @@ 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.
-  // UNIQUE_PREFIX is a prefix for all global symbols.
+  // PKGPATH is the package path.
   // PACKAGE_PRIORITY is the priority to use for this package.
   // IMPORT_INIT_FN is the name of the import initialization function
   // for this package; it will be empty if none is needed.
@@ -125,7 +125,7 @@ class Export : public String_dump
   // imported packages.
   void
   export_globals(const std::string& package_name,
-                const std::string& unique_prefix,
+                const std::string& pkgpath,
                 int package_priority,
                 const std::map<std::string, Package*>& imports,
                 const std::string& import_init_fn,
@@ -182,6 +182,8 @@ class Export : public String_dump
   Type_refs type_refs_;
   // Index number of next type.
   int type_index_;
+  // Packages we have written out.
+  Unordered_set(const Package*) packages_;
 };
 
 // An export streamer which puts the export stream in a named section.
index bfa3afd..1f2ce8a 100644 (file)
 #include "backend.h"
 #include "gogo.h"
 
-// The unique prefix to use for exported symbols.  This is set during
-// option processing.
-
-static std::string unique_prefix;
-
 // The data structures we build to represent the file.
 static Gogo* gogo;
 
@@ -25,38 +20,22 @@ static Gogo* gogo;
 
 GO_EXTERN_C
 void
-go_create_gogo(int int_type_size, int pointer_size)
+go_create_gogo(int int_type_size, int pointer_size, const char *pkgpath,
+              const char *prefix)
 {
   go_assert(::gogo == NULL);
   Linemap* linemap = go_get_linemap();
   ::gogo = new Gogo(go_get_backend(), linemap, int_type_size, pointer_size);
-  if (!unique_prefix.empty())
-    ::gogo->set_unique_prefix(unique_prefix);
+
+  if (pkgpath != NULL)
+    ::gogo->set_pkgpath(pkgpath);
+  else if (prefix != NULL)
+    ::gogo->set_prefix(prefix);
 
   // FIXME: This should be in the gcc dependent code.
   ::gogo->define_builtin_function_trees();
 }
 
-// Set the unique prefix we use for exported symbols.
-
-GO_EXTERN_C
-void
-go_set_prefix(const char* arg)
-{
-  unique_prefix = arg;
-  for (size_t i = 0; i < unique_prefix.length(); ++i)
-    {
-      char c = unique_prefix[i];
-      if ((c >= 'a' && c <= 'z')
-         || (c >= 'A' && c <= 'Z')
-         || (c >= '0' && c <= '9')
-         || c == '_')
-       ;
-      else
-       unique_prefix[i] = '_';
-    }
-}
-
 // Parse the input files.
 
 GO_EXTERN_C
index b379b95..20e5b55 100644 (file)
@@ -260,9 +260,7 @@ Gogo::get_init_fn_name()
        }
       else
        {
-         std::string s = this->unique_prefix();
-         s.append(1, '.');
-         s.append(this->package_name());
+         std::string s = this->pkgpath_symbol();
          s.append("..import");
          this->init_fn_name_ = s;
        }
@@ -985,7 +983,7 @@ Named_object::get_id(Gogo* gogo)
       if (this->package_ == NULL)
        package_name = gogo->package_name();
       else
-       package_name = this->package_->name();
+       package_name = this->package_->package_name();
 
       decl_name = package_name + '.' + Gogo::unpack_hidden_name(this->name_);
 
@@ -1278,9 +1276,15 @@ Function::get_or_make_decl(Gogo* gogo, Named_object* no, tree id)
                   || this->type_->is_method())
            {
              TREE_PUBLIC(decl) = 1;
-             std::string asm_name = gogo->unique_prefix();
+             std::string asm_name = gogo->pkgpath_symbol();
              asm_name.append(1, '.');
-             asm_name.append(IDENTIFIER_POINTER(id), IDENTIFIER_LENGTH(id));
+             asm_name.append(Gogo::unpack_hidden_name(no->name()));
+             if (this->type_->is_method())
+               {
+                 asm_name.append(1, '.');
+                 Type* rtype = this->type_->receiver()->type();
+                 asm_name.append(rtype->mangled_name(gogo));
+               }
              SET_DECL_ASSEMBLER_NAME(decl,
                                      get_identifier_from_string(asm_name));
            }
@@ -1383,10 +1387,16 @@ Function_declaration::get_or_make_decl(Gogo* gogo, Named_object* no, tree id)
          if (this->asm_name_.empty())
            {
              std::string asm_name = (no->package() == NULL
-                                     ? gogo->unique_prefix()
-                                     : no->package()->unique_prefix());
+                                     ? gogo->pkgpath_symbol()
+                                     : no->package()->pkgpath_symbol());
              asm_name.append(1, '.');
-             asm_name.append(IDENTIFIER_POINTER(id), IDENTIFIER_LENGTH(id));
+             asm_name.append(Gogo::unpack_hidden_name(no->name()));
+             if (this->fntype_->is_method())
+               {
+                 asm_name.append(1, '.');
+                 Type* rtype = this->fntype_->receiver()->type();
+                 asm_name.append(rtype->mangled_name(gogo));
+               }
              SET_DECL_ASSEMBLER_NAME(decl,
                                      get_identifier_from_string(asm_name));
            }
index f9982cc..80ffe24 100644 (file)
@@ -36,8 +36,12 @@ Gogo::Gogo(Backend* backend, Linemap* linemap, int int_type_size,
     need_init_fn_(false),
     init_fn_name_(),
     imported_init_fns_(),
-    unique_prefix_(),
-    unique_prefix_specified_(false),
+    pkgpath_(),
+    pkgpath_symbol_(),
+    prefix_(),
+    pkgpath_set_(false),
+    pkgpath_from_option_(false),
+    prefix_from_option_(false),
     verify_types_(),
     interface_types_(),
     specific_type_functions_(),
@@ -233,6 +237,72 @@ Gogo::Gogo(Backend* backend, Linemap* linemap, int int_type_size,
   this->globals_->add_function_declaration("delete", NULL, delete_type, loc);
 }
 
+// Convert a pkgpath into a string suitable for a symbol.  Note that
+// this transformation is convenient but imperfect.  A -fgo-pkgpath
+// option of a/b_c will conflict with a -fgo-pkgpath option of a_b/c,
+// possibly leading to link time errors.
+
+std::string
+Gogo::pkgpath_for_symbol(const std::string& pkgpath)
+{
+  std::string s = pkgpath;
+  for (size_t i = 0; i < s.length(); ++i)
+    {
+      char c = s[i];
+      if ((c >= 'a' && c <= 'z')
+         || (c >= 'A' && c <= 'Z')
+         || (c >= '0' && c <= '9')
+         || c == '_'
+         || c == '.'
+         || c == '$')
+       ;
+      else
+       s[i] = '_';
+    }
+  return s;
+}
+
+// Get the package path to use for type reflection data.  This should
+// ideally be unique across the entire link.
+
+const std::string&
+Gogo::pkgpath() const
+{
+  go_assert(this->pkgpath_set_);
+  return this->pkgpath_;
+}
+
+// Set the package path from the -fgo-pkgpath command line option.
+
+void
+Gogo::set_pkgpath(const std::string& arg)
+{
+  go_assert(!this->pkgpath_set_);
+  this->pkgpath_ = arg;
+  this->pkgpath_set_ = true;
+  this->pkgpath_from_option_ = true;
+}
+
+// Get the package path to use for symbol names.
+
+const std::string&
+Gogo::pkgpath_symbol() const
+{
+  go_assert(this->pkgpath_set_);
+  return this->pkgpath_symbol_;
+}
+
+// Set the unique prefix to use to determine the package path, from
+// the -fgo-prefix command line option.
+
+void
+Gogo::set_prefix(const std::string& arg)
+{
+  go_assert(!this->prefix_from_option_);
+  this->prefix_ = arg;
+  this->prefix_from_option_ = true;
+}
+
 // Munge name for use in an error message.
 
 std::string
@@ -247,7 +317,7 @@ const std::string&
 Gogo::package_name() const
 {
   go_assert(this->package_ != NULL);
-  return this->package_->name();
+  return this->package_->package_name();
 }
 
 // Set the package name.
@@ -256,24 +326,29 @@ void
 Gogo::set_package_name(const std::string& package_name,
                       Location location)
 {
-  if (this->package_ != NULL && this->package_->name() != package_name)
+  if (this->package_ != NULL)
     {
-      error_at(location, "expected package %<%s%>",
-              Gogo::message_name(this->package_->name()).c_str());
+      if (this->package_->package_name() != package_name)
+       error_at(location, "expected package %<%s%>",
+                Gogo::message_name(this->package_->package_name()).c_str());
       return;
     }
 
-  // If the user did not specify a unique prefix, we always use "go".
-  // This in effect requires that the package name be unique.
-  if (this->unique_prefix_.empty())
-    this->unique_prefix_ = "go";
+  // 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->prefix_from_option_)
+       this->prefix_ = "go";
+      this->pkgpath_ = this->prefix_ + '.' + package_name;
+      this->pkgpath_set_ = true;
+    }
 
-  this->package_ = this->register_package(package_name, this->unique_prefix_,
-                                         location);
+  this->pkgpath_symbol_ = Gogo::pkgpath_for_symbol(this->pkgpath_);
 
-  // We used to permit people to qualify symbols with the current
-  // package name (e.g., P.x), but we no longer do.
-  // this->globals_->add_package(package_name, this->package_);
+  this->package_ = this->register_package(this->pkgpath_, location);
+  this->package_->set_package_name(package_name, location);
 
   if (this->is_main_package())
     {
@@ -287,12 +362,14 @@ Gogo::set_package_name(const std::string& package_name,
 }
 
 // Return whether this is the "main" package.  This is not true if
-// -fgo-prefix was used.
+// -fgo-pkgpath or -fgo-prefix was used.
 
 bool
 Gogo::is_main_package() const
 {
-  return this->package_name() == "main" && !this->unique_prefix_specified_;
+  return (this->package_name() == "main"
+         && !this->pkgpath_from_option_
+         && !this->prefix_from_option_);
 }
 
 // Import a package.
@@ -319,7 +396,8 @@ Gogo::import_package(const std::string& filename,
       bool is_ln_exported = is_local_name_exported;
       if (ln.empty())
        {
-         ln = package->name();
+         ln = package->package_name();
+         go_assert(!ln.empty());
          is_ln_exported = Lex::is_exported_name(ln);
        }
       if (ln == ".")
@@ -353,11 +431,10 @@ Gogo::import_package(const std::string& filename,
   Package* package = imp.import(this, local_name, is_local_name_exported);
   if (package != NULL)
     {
-      if (package->name() == this->package_name()
-         && package->unique_prefix() == this->unique_prefix())
+      if (package->pkgpath() == this->pkgpath())
        error_at(location,
-                ("imported package uses same package name and prefix "
-                 "as package being compiled (see -fgo-prefix option)"));
+                ("imported package uses same package path as package "
+                 "being compiled (see -fgo-pkgpath option)"));
 
       this->imports_.insert(std::make_pair(filename, package));
       package->set_is_imported();
@@ -510,38 +587,21 @@ Package*
 Gogo::add_imported_package(const std::string& real_name,
                           const std::string& alias_arg,
                           bool is_alias_exported,
-                          const std::string& unique_prefix,
+                          const std::string& pkgpath,
                           Location location,
                           bool* padd_to_globals)
 {
-  // FIXME: Now that we compile packages as a whole, should we permit
-  // importing the current package?
-  if (this->package_name() == real_name
-      && this->unique_prefix() == unique_prefix)
-    {
-      *padd_to_globals = false;
-      if (!alias_arg.empty() && alias_arg != ".")
-       {
-         std::string alias = this->pack_hidden_name(alias_arg,
-                                                    is_alias_exported);
-         this->package_->bindings()->add_package(alias, this->package_);
-       }
-      return this->package_;
-    }
-  else if (alias_arg == ".")
-    {
-      *padd_to_globals = true;
-      return this->register_package(real_name, unique_prefix, location);
-    }
+  Package* ret = this->register_package(pkgpath, location);
+  ret->set_package_name(real_name, location);
+
+  *padd_to_globals = false;
+
+  if (alias_arg == ".")
+    *padd_to_globals = true;
   else if (alias_arg == "_")
-    {
-      Package* ret = this->register_package(real_name, unique_prefix, location);
-      ret->set_uses_sink_alias();
-      return ret;
-    }
+    ret->set_uses_sink_alias();
   else
     {
-      *padd_to_globals = false;
       std::string alias = alias_arg;
       if (alias.empty())
        {
@@ -549,57 +609,37 @@ Gogo::add_imported_package(const std::string& real_name,
          is_alias_exported = Lex::is_exported_name(alias);
        }
       alias = this->pack_hidden_name(alias, is_alias_exported);
-      Named_object* no = this->add_package(real_name, alias, unique_prefix,
-                                          location);
+      Named_object* no = this->package_->bindings()->add_package(alias, ret);
       if (!no->is_package())
        return NULL;
-      return no->package_value();
     }
-}
 
-// Add a package.
-
-Named_object*
-Gogo::add_package(const std::string& real_name, const std::string& alias,
-                 const std::string& unique_prefix, Location location)
-{
-  go_assert(this->in_global_scope());
-
-  // Register the package.  Note that we might have already seen it in
-  // an earlier import.
-  Package* package = this->register_package(real_name, unique_prefix, location);
-
-  return this->package_->bindings()->add_package(alias, package);
+  return ret;
 }
 
 // Register a package.  This package may or may not be imported.  This
 // returns the Package structure for the package, creating if it
-// necessary.
+// necessary.  LOCATION is the location of the import statement that
+// led us to see this package.
 
 Package*
-Gogo::register_package(const std::string& package_name,
-                      const std::string& unique_prefix,
-                      Location location)
+Gogo::register_package(const std::string& pkgpath, Location location)
 {
-  go_assert(!unique_prefix.empty() && !package_name.empty());
-  std::string name = unique_prefix + '.' + package_name;
   Package* package = NULL;
   std::pair<Packages::iterator, bool> ins =
-    this->packages_.insert(std::make_pair(name, package));
+    this->packages_.insert(std::make_pair(pkgpath, package));
   if (!ins.second)
     {
       // We have seen this package name before.
       package = ins.first->second;
-      go_assert(package != NULL);
-      go_assert(package->name() == package_name
-                && package->unique_prefix() == unique_prefix);
+      go_assert(package != NULL && package->pkgpath() == pkgpath);
       if (Linemap::is_unknown_location(package->location()))
        package->set_location(location);
     }
   else
     {
       // First time we have seen this package name.
-      package = new Package(package_name, unique_prefix, location);
+      package = new Package(pkgpath, location);
       go_assert(ins.first->second == NULL);
       ins.first->second = package;
     }
@@ -1151,7 +1191,7 @@ Gogo::clear_file_scope()
          && !package->uses_sink_alias()
          && !saw_errors())
        error_at(package->location(), "imported and not used: %s",
-                Gogo::message_name(package->name()).c_str());
+                Gogo::message_name(package->package_name()).c_str());
       package->clear_is_imported();
       package->clear_uses_sink_alias();
       package->clear_used();
@@ -2822,27 +2862,6 @@ Gogo::check_return_statements()
   this->traverse(&traverse);
 }
 
-// Get the unique prefix to use before all exported symbols.  This
-// must be unique across the entire link.
-
-const std::string&
-Gogo::unique_prefix() const
-{
-  go_assert(!this->unique_prefix_.empty());
-  return this->unique_prefix_;
-}
-
-// Set the unique prefix to use before all exported symbols.  This
-// comes from the command line option -fgo-prefix=XXX.
-
-void
-Gogo::set_unique_prefix(const std::string& arg)
-{
-  go_assert(this->unique_prefix_.empty());
-  this->unique_prefix_ = arg;
-  this->unique_prefix_specified_ = true;
-}
-
 // Work out the package priority.  It is one more than the maximum
 // priority of an imported package.
 
@@ -2870,7 +2889,7 @@ Gogo::do_exports()
   Export exp(&stream);
   exp.register_builtin_types(this);
   exp.export_globals(this->package_name(),
-                    this->unique_prefix(),
+                    this->pkgpath(),
                     this->package_priority(),
                     this->imports_,
                     (this->need_init_fn_ && !this->is_main_package()
@@ -4199,10 +4218,10 @@ Variable::get_backend_variable(Gogo* gogo, Named_object* function,
          if (this->is_global_)
            bvar = backend->global_variable((package == NULL
                                             ? gogo->package_name()
-                                            : package->name()),
+                                            : package->package_name()),
                                            (package == NULL
-                                            ? gogo->unique_prefix()
-                                            : package->unique_prefix()),
+                                            ? gogo->pkgpath_symbol()
+                                            : package->pkgpath_symbol()),
                                            n,
                                            btype,
                                            package != NULL,
@@ -4556,7 +4575,12 @@ Named_object::message_name() const
 {
   if (this->package_ == NULL)
     return Gogo::message_name(this->name_);
-  std::string ret = Gogo::message_name(this->package_->name());
+  std::string ret;
+  if (this->package_->has_package_name())
+    ret = this->package_->package_name();
+  else
+    ret = this->package_->pkgpath();
+  ret = Gogo::message_name(ret);
   ret += '.';
   ret += Gogo::message_name(this->name_);
   return ret;
@@ -5213,13 +5237,29 @@ Unnamed_label::get_goto(Translate_context* context, Location location)
 
 // Class Package.
 
-Package::Package(const std::string& name, const std::string& unique_prefix,
-                Location location)
-  : name_(name), unique_prefix_(unique_prefix), bindings_(new Bindings(NULL)),
-    priority_(0), location_(location), used_(false), is_imported_(false),
+Package::Package(const std::string& pkgpath, Location location)
+  : pkgpath_(pkgpath), pkgpath_symbol_(Gogo::pkgpath_for_symbol(pkgpath)),
+    package_name_(), bindings_(new Bindings(NULL)), priority_(0),
+    location_(location), used_(false), is_imported_(false),
     uses_sink_alias_(false)
 {
-  go_assert(!name.empty() && !unique_prefix.empty());
+  go_assert(!pkgpath.empty());
+  
+}
+
+// Set the package name.
+
+void
+Package::set_package_name(const std::string& package_name, Location location)
+{
+  go_assert(!package_name.empty());
+  if (this->package_name_.empty())
+    this->package_name_ = package_name;
+  else if (this->package_name_ != package_name)
+    error_at(location,
+            "saw two different packages with the same package path %s: %s, %s",
+            this->pkgpath_.c_str(), this->package_name_.c_str(),
+            package_name.c_str());
 }
 
 // Set the priority.  We may see multiple priorities for an imported
index 4990bf2..deb9968 100644 (file)
@@ -138,16 +138,14 @@ class Gogo
   is_main_package() const;
 
   // If necessary, adjust the name to use for a hidden symbol.  We add
-  // a prefix of the package name, so that hidden symbols in different
-  // packages do not collide.
+  // the package name, so that hidden symbols in different packages do
+  // not collide.
   std::string
   pack_hidden_name(const std::string& name, bool is_exported) const
   {
     return (is_exported
            ? name
-           : ('.' + this->unique_prefix()
-              + '.' + this->package_name()
-              + '.' + name));
+           : '.' + this->pkgpath() + '.' + name);
   }
 
   // Unpack a name which may have been hidden.  Returns the
@@ -161,9 +159,9 @@ class Gogo
   is_hidden_name(const std::string& name)
   { return name[0] == '.'; }
 
-  // Return the package prefix of a hidden name.
+  // Return the package path of a hidden name.
   static std::string
-  hidden_name_prefix(const std::string& name)
+  hidden_name_pkgpath(const std::string& name)
   {
     go_assert(Gogo::is_hidden_name(name));
     return name.substr(1, name.rfind('.') - 1);
@@ -183,13 +181,30 @@ class Gogo
            && name[name.length() - 2] == '.');
   }
 
-  // Return the unique prefix to use for all exported symbols.
+  // Convert a pkgpath into a string suitable for a symbol
+  static std::string
+  pkgpath_for_symbol(const std::string& pkgpath);
+
+  // Return the package path to use for reflect.Type.PkgPath.
+  const std::string&
+  pkgpath() const;
+
+  // Return the package path to use for a symbol name.
   const std::string&
-  unique_prefix() const;
+  pkgpath_symbol() const;
+
+  // Set the package path from a command line option.
+  void
+  set_pkgpath(const std::string&);
 
-  // Set the unique prefix.
+  // Set the prefix from a command line option.
   void
-  set_unique_prefix(const std::string&);
+  set_prefix(const std::string&);
+
+  // Return whether pkgpath was set from a command line option.
+  bool
+  pkgpath_from_option() const
+  { return this->pkgpath_from_option_; }
 
   // Return the priority to use for the package we are compiling.
   // This is two more than the largest priority of any package we
@@ -229,7 +244,7 @@ class Gogo
   Package*
   add_imported_package(const std::string& real_name, const std::string& alias,
                       bool is_alias_exported,
-                      const std::string& unique_prefix,
+                      const std::string& pkgpath,
                       Location location,
                       bool* padd_to_globals);
 
@@ -237,8 +252,7 @@ class Gogo
   // This returns the Package structure for the package, creating if
   // it necessary.
   Package*
-  register_package(const std::string& name, const std::string& unique_prefix,
-                  Location);
+  register_package(const std::string& pkgpath, Location);
 
   // Start compiling a function.  ADD_METHOD_TO_TYPE is true if a
   // method function should be added to the type of its receiver.
@@ -609,11 +623,6 @@ class Gogo
   void
   import_unsafe(const std::string&, bool is_exported, Location);
 
-  // Add a new imported package.
-  Named_object*
-  add_package(const std::string& real_name, const std::string& alias,
-             const std::string& unique_prefix, Location location);
-
   // Return the current binding contour.
   Bindings*
   current_bindings();
@@ -711,10 +720,18 @@ class Gogo
   std::string init_fn_name_;
   // A list of import control variables for packages that we import.
   std::set<Import_init> imported_init_fns_;
-  // The unique prefix used for all global symbols.
-  std::string unique_prefix_;
-  // Whether an explicit unique prefix was set by -fgo-prefix.
-  bool unique_prefix_specified_;
+  // The package path used for reflection data.
+  std::string pkgpath_;
+  // The package path to use for a symbol name.
+  std::string pkgpath_symbol_;
+  // The prefix to use for symbols, from the -fgo-prefix option.
+  std::string prefix_;
+  // Whether pkgpath_ has been set.
+  bool pkgpath_set_;
+  // Whether an explicit package path was set by -fgo-pkgpath.
+  bool pkgpath_from_option_;
+  // Whether an explicit prefix was set by -fgo-prefix.
+  bool prefix_from_option_;
   // A list of types to verify.
   std::vector<Type*> verify_types_;
   // A list of interface types defined while parsing.
@@ -2409,28 +2426,37 @@ class Unnamed_label
 class Package
 {
  public:
-  Package(const std::string& name, const std::string& unique_prefix,
-         Location location);
+  Package(const std::string& pkgpath, Location location);
 
-  // The real name of this package.  This may be different from the
-  // name in the associated Named_object if the import statement used
-  // an alias.
+  // Get the package path used for all symbols exported from this
+  // package.
   const std::string&
-  name() const
-  { return this->name_; }
+  pkgpath() const
+  { return this->pkgpath_; }
+
+  // Return the package path to use for a symbol name.
+  const std::string&
+  pkgpath_symbol() const
+  { return this->pkgpath_symbol_; }
 
   // Return the location of the import statement.
   Location
   location() const
   { return this->location_; }
 
-  // Get the unique prefix used for all symbols exported from this
-  // package.
+  // Return whether we know the name of this package yet.
+  bool
+  has_package_name() const
+  { return !this->package_name_.empty(); }
+
+  // The name that this package uses in its package clause.  This may
+  // be different from the name in the associated Named_object if the
+  // import statement used an alias.
   const std::string&
-  unique_prefix() const
+  package_name() const
   {
-    go_assert(!this->unique_prefix_.empty());
-    return this->unique_prefix_;
+    go_assert(!this->package_name_.empty());
+    return this->package_name_;
   }
 
   // The priority of this package.  The init function of packages with
@@ -2500,8 +2526,12 @@ class Package
   lookup(const std::string& name) const
   { return this->bindings_->lookup(name); }
 
-  // Set the location of the package.  This is used if it is seen in a
-  // different import before it is really imported.
+  // Set the name of the package.
+  void
+  set_package_name(const std::string& name, Location);
+
+  // Set the location of the package.  This is used to record the most
+  // recent import location.
   void
   set_location(Location location)
   { this->location_ = location; }
@@ -2537,10 +2567,13 @@ class Package
   determine_types();
 
  private:
-  // The real name of this package.
-  std::string name_;
-  // The unique prefix for all exported global symbols.
-  std::string unique_prefix_;
+  // The package path for type reflection data.
+  std::string pkgpath_;
+  // The package path for symbol names.
+  std::string pkgpath_symbol_;
+  // The name that this package uses in the package clause.  This may
+  // be the empty string if it is not yet known.
+  std::string package_name_;
   // The names in this package.
   Bindings* bindings_;
   // The priority of this package.  A package has a priority higher
index b0d1008..9febf23 100644 (file)
@@ -281,13 +281,24 @@ Import::import(Gogo* gogo, const std::string& local_name,
       std::string package_name = this->read_identifier();
       this->require_c_string(";\n");
 
-      this->require_c_string("prefix ");
-      std::string unique_prefix = this->read_identifier();
-      this->require_c_string(";\n");
+      std::string pkgpath;
+      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;
+       }
+      else
+       {
+         this->require_c_string("pkgpath ");
+         pkgpath = this->read_identifier();
+         this->require_c_string(";\n");
+       }
 
       this->package_ = gogo->add_imported_package(package_name, local_name,
                                                  is_local_name_exported,
-                                                 unique_prefix,
+                                                 pkgpath,
                                                  this->location_,
                                                  &this->add_to_globals_);
       if (this->package_ == NULL)
@@ -353,10 +364,18 @@ void
 Import::read_one_import()
 {
   this->require_c_string("import ");
+  std::string package_name = this->read_identifier();
+  this->require_c_string(" ");
+  std::string pkgpath = this->read_identifier();
+  this->require_c_string(" \"");
   Stream* stream = this->stream_;
-  while (stream->peek_char() != ';')
+  while (stream->peek_char() != '"')
     stream->advance(1);
-  this->require_c_string(";\n");
+  this->require_c_string("\";\n");
+
+  Package* p = this->gogo_->register_package(pkgpath,
+                                            Linemap::unknown_location());
+  p->set_package_name(package_name, this->location());
 }
 
 // Read the list of import control functions.
@@ -572,55 +591,50 @@ Import::read_type()
   while ((c = stream->get_char()) != '"')
     type_name += c;
 
-  // If this type is in the current package, the name will be
-  // .PREFIX.PACKAGE.NAME or simply NAME with no dots.  Otherwise, a
-  // non-hidden symbol will be PREFIX.PACKAGE.NAME and a hidden symbol
-  // will be .PREFIX.PACKAGE.NAME.
-  std::string package_name;
-  std::string unique_prefix;
+  // If this type is in the package we are currently importing, the
+  // name will be .PKGPATH.NAME or simply NAME with no dots.
+  // Otherwise, a non-hidden symbol will be PKGPATH.NAME and a hidden
+  // symbol will be .PKGPATH.NAME.
+  std::string pkgpath;
   if (type_name.find('.') != std::string::npos)
     {
-      bool is_hidden = false;
       size_t start = 0;
       if (type_name[0] == '.')
-       {
-         ++start;
-         is_hidden = true;
-       }
-      size_t dot1 = type_name.find('.', start);
-      size_t dot2;
-      if (dot1 == std::string::npos)
-       dot2 = std::string::npos;
-      else
-       dot2 = type_name.find('.', dot1 + 1);
-      if (dot1 == std::string::npos || dot2 == std::string::npos)
-       {
-         error_at(this->location_,
-                  ("error at import data at %d: missing dot in type name"),
-                  stream->pos());
-         stream->set_saw_error();
-       }
-      else
-       {
-         unique_prefix = type_name.substr(start, dot1 - start);
-         package_name = type_name.substr(dot1 + 1, dot2 - (dot1 + 1));
-       }
-      if (!is_hidden)
-       type_name.erase(0, dot2 + 1);
+       start = 1;
+      size_t dot = type_name.rfind('.');
+      pkgpath = type_name.substr(start, dot - start);
+      if (type_name[0] != '.')
+       type_name.erase(0, dot + 1);
     }
 
   this->require_c_string(" ");
 
+  // The package name may follow.  This is the name of the package in
+  // the package clause of that package.  The type name will include
+  // the pkgpath, which may be different.
+  std::string package_name;
+  if (stream->peek_char() == '"')
+    {
+      stream->advance(1);
+      while ((c = stream->get_char()) != '"')
+       package_name += c;
+      this->require_c_string(" ");
+    }
+
   // Declare the type in the appropriate package.  If we haven't seen
   // it before, mark it as invisible.  We declare it before we read
   // the actual definition of the type, since the definition may refer
   // to the type itself.
   Package* package;
-  if (package_name.empty())
+  if (pkgpath.empty() || pkgpath == this->gogo_->pkgpath())
     package = this->package_;
   else
-    package = this->gogo_->register_package(package_name, unique_prefix,
-                                           Linemap::unknown_location());
+    {
+      package = this->gogo_->register_package(pkgpath,
+                                             Linemap::unknown_location());
+      if (!package_name.empty())
+       package->set_package_name(package_name, this->location());
+    }
 
   Named_object* no = package->bindings()->lookup(type_name);
   if (no == NULL)
@@ -628,8 +642,7 @@ Import::read_type()
   else if (!no->is_type_declaration() && !no->is_type())
     {
       error_at(this->location_, "imported %<%s.%s%> both type and non-type",
-              Gogo::message_name(package->name()).c_str(),
-              Gogo::message_name(type_name).c_str());
+              pkgpath.c_str(), Gogo::message_name(type_name).c_str());
       stream->set_saw_error();
       return Type::make_error_type();
     }
@@ -772,9 +785,7 @@ Import::read_name()
   if (ret == "?")
     ret.clear();
   else if (!Lex::is_exported_name(ret))
-    ret = ('.' + this->package_->unique_prefix()
-          + '.' + this->package_->name()
-          + '.' + ret);
+    ret = '.' + this->package_->pkgpath() + '.' + ret;
   return ret;
 }
 
index fc2c229..29323f0 100644 (file)
@@ -323,13 +323,13 @@ Parse::type_name(bool issue_error)
          && package->name() != this->gogo_->package_name())
        {
          // Check whether the name is there but hidden.
-         std::string s = ('.' + package->package_value()->unique_prefix()
-                          + '.' + package->package_value()->name()
+         std::string s = ('.' + package->package_value()->pkgpath()
                           + '.' + name);
          named_object = package->package_value()->lookup(s);
          if (named_object != NULL)
            {
-             const std::string& packname(package->package_value()->name());
+             Package* p = package->package_value();
+             const std::string& packname(p->package_name());
              error_at(location, "invalid reference to hidden type %<%s.%s%>",
                       Gogo::message_name(packname).c_str(),
                       Gogo::message_name(name).c_str());
@@ -345,7 +345,7 @@ Parse::type_name(bool issue_error)
        named_object = this->gogo_->add_unknown_name(name, location);
       else
        {
-         const std::string& packname(package->package_value()->name());
+         const std::string& packname(package->package_value()->package_name());
          error_at(location, "reference to undefined identifier %<%s.%s%>",
                   Gogo::message_name(packname).c_str(),
                   Gogo::message_name(name).c_str());
@@ -2384,7 +2384,7 @@ Parse::operand(bool may_be_sink)
          {
            go_assert(package != NULL);
            error_at(location, "invalid reference to hidden type %<%s.%s%>",
-                    Gogo::message_name(package->name()).c_str(),
+                    Gogo::message_name(package->package_name()).c_str(),
                     Gogo::message_name(id).c_str());
            return Expression::make_error(location);
          }
@@ -2394,7 +2394,7 @@ Parse::operand(bool may_be_sink)
          {
            if (package != NULL)
              {
-               std::string n1 = Gogo::message_name(package->name());
+               std::string n1 = Gogo::message_name(package->package_name());
                std::string n2 = Gogo::message_name(id);
                if (!is_exported)
                  error_at(location,
index 74bab41..35770c7 100644 (file)
@@ -1301,15 +1301,10 @@ Type::type_descriptor_var_name(Gogo* gogo, Named_type* nt)
     go_assert(in_function == NULL);
   else
     {
-      const std::string& unique_prefix(no->package() == NULL
-                                      ? gogo->unique_prefix()
-                                      : no->package()->unique_prefix());
-      const std::string& package_name(no->package() == NULL
-                                     ? gogo->package_name()
-                                     : no->package()->name());
-      ret.append(unique_prefix);
-      ret.append(1, '.');
-      ret.append(package_name);
+      const std::string& pkgpath(no->package() == NULL
+                                ? gogo->pkgpath_symbol()
+                                : no->package()->pkgpath_symbol());
+      ret.append(pkgpath);
       ret.append(1, '.');
       if (in_function != NULL)
        {
@@ -1317,7 +1312,20 @@ Type::type_descriptor_var_name(Gogo* gogo, Named_type* nt)
          ret.append(1, '.');
        }
     }
-  ret.append(no->name());
+
+  // FIXME: This adds in pkgpath twice for hidden symbols, which is
+  // pointless.
+  const std::string& name(no->name());
+  if (!Gogo::is_hidden_name(name))
+    ret.append(name);
+  else
+    {
+      ret.append(1, '.');
+      ret.append(Gogo::pkgpath_for_symbol(Gogo::hidden_name_pkgpath(name)));
+      ret.append(1, '.');
+      ret.append(Gogo::unpack_hidden_name(name));
+    }
+
   return ret;
 }
 
@@ -1977,15 +1985,10 @@ Type::uncommon_type_constructor(Gogo* gogo, Type* uncommon_type,
       else
        {
          const Package* package = no->package();
-         const std::string& unique_prefix(package == NULL
-                                          ? gogo->unique_prefix()
-                                          : package->unique_prefix());
-         const std::string& package_name(package == NULL
-                                         ? gogo->package_name()
-                                         : package->name());
-         n.assign(unique_prefix);
-         n.append(1, '.');
-         n.append(package_name);
+         const std::string& pkgpath(package == NULL
+                                    ? gogo->pkgpath()
+                                    : package->pkgpath());
+         n.assign(pkgpath);
          if (name->in_function() != NULL)
            {
              n.append(1, '.');
@@ -2096,7 +2099,8 @@ Type::method_constructor(Gogo*, Type* method_type,
     vals->push_back(Expression::make_nil(bloc));
   else
     {
-      s = Expression::make_string(Gogo::hidden_name_prefix(method_name), bloc);
+      s = Expression::make_string(Gogo::hidden_name_pkgpath(method_name),
+                                 bloc);
       vals->push_back(Expression::make_unary(OPERATOR_AND, s, bloc));
     }
 
@@ -4668,7 +4672,7 @@ Struct_type::do_type_descriptor(Gogo* gogo, Named_type* name)
        fvals->push_back(Expression::make_nil(bloc));
       else
        {
-         std::string n = Gogo::hidden_name_prefix(pf->field_name());
+         std::string n = Gogo::hidden_name_pkgpath(pf->field_name());
          Expression* s = Expression::make_string(n, bloc);
          fvals->push_back(Expression::make_unary(OPERATOR_AND, s, bloc));
        }
@@ -7056,7 +7060,7 @@ Interface_type::do_type_descriptor(Gogo* gogo, Named_type* name)
            mvals->push_back(Expression::make_nil(bloc));
          else
            {
-             s = Gogo::hidden_name_prefix(pm->name());
+             s = Gogo::hidden_name_pkgpath(pm->name());
              e = Expression::make_string(s, bloc);
              mvals->push_back(Expression::make_unary(OPERATOR_AND, e, bloc));
            }
@@ -7105,11 +7109,15 @@ Interface_type::do_reflection(Gogo* gogo, std::string* ret) const
            {
              if (!Gogo::is_hidden_name(p->name()))
                ret->append(p->name());
+             else if (gogo->pkgpath_from_option())
+               ret->append(p->name().substr(1));
              else
                {
-                 // This matches what the gc compiler does.
-                 std::string prefix = Gogo::hidden_name_prefix(p->name());
-                 ret->append(prefix.substr(prefix.find('.') + 1));
+                 // If no -fgo-pkgpath option, backward compatibility
+                 // for how this used to work before -fgo-pkgpath was
+                 // introduced.
+                 std::string pkgpath = Gogo::hidden_name_pkgpath(p->name());
+                 ret->append(pkgpath.substr(pkgpath.find('.') + 1));
                  ret->push_back('.');
                  ret->append(Gogo::unpack_hidden_name(p->name()));
                }
@@ -7939,20 +7947,14 @@ Named_type::do_hash_for_method(Gogo* gogo) const
   // where we are going to be comparing named types for equality.  In
   // other cases, which are cases where the runtime is going to
   // compare hash codes to see if the types are the same, we need to
-  // include the package prefix and name in the hash.
+  // include the pkgpath in the hash.
   if (gogo != NULL && !Gogo::is_hidden_name(name) && !this->is_builtin())
     {
       const Package* package = this->named_object()->package();
       if (package == NULL)
-       {
-         ret = Type::hash_string(gogo->unique_prefix(), ret);
-         ret = Type::hash_string(gogo->package_name(), ret);
-       }
+       ret = Type::hash_string(gogo->pkgpath(), ret);
       else
-       {
-         ret = Type::hash_string(package->unique_prefix(), ret);
-         ret = Type::hash_string(package->name(), ret);
-       }
+       ret = Type::hash_string(package->pkgpath(), ret);
     }
 
   return ret;
@@ -8324,11 +8326,16 @@ Named_type::do_reflection(Gogo* gogo, std::string* ret) const
     }
   if (!this->is_builtin())
     {
+      // We handle -fgo-prefix and -fgo-pkgpath differently here for
+      // compatibility with how the compiler worked before
+      // -fgo-pkgpath was introduced.
       const Package* package = this->named_object_->package();
-      if (package != NULL)
-       ret->append(package->name());
+      if (gogo->pkgpath_from_option())
+       ret->append(package != NULL ? package->pkgpath() : gogo->pkgpath());
       else
-       ret->append(gogo->package_name());
+       ret->append(package != NULL
+                   ? package->package_name()
+                   : gogo->package_name());
       ret->push_back('.');
     }
   if (this->in_function_ != NULL)
@@ -8355,15 +8362,10 @@ Named_type::do_mangled_name(Gogo* gogo, std::string* ret) const
     go_assert(this->in_function_ == NULL);
   else
     {
-      const std::string& unique_prefix(no->package() == NULL
-                                      ? gogo->unique_prefix()
-                                      : no->package()->unique_prefix());
-      const std::string& package_name(no->package() == NULL
-                                     ? gogo->package_name()
-                                     : no->package()->name());
-      name = unique_prefix;
-      name.append(1, '.');
-      name.append(package_name);
+      const std::string& pkgpath(no->package() == NULL
+                                ? gogo->pkgpath_symbol()
+                                : no->package()->pkgpath_symbol());
+      name = pkgpath;
       name.append(1, '.');
       if (this->in_function_ != NULL)
        {
@@ -9487,9 +9489,9 @@ Forward_declaration_type::do_mangled_name(Gogo* gogo, std::string* ret) const
       const Named_object* no = this->named_object();
       std::string name;
       if (no->package() == NULL)
-       name = gogo->package_name();
+       name = gogo->pkgpath_symbol();
       else
-       name = no->package()->name();
+       name = no->package()->pkgpath_symbol();
       name += '.';
       name += Gogo::unpack_hidden_name(no->name());
       char buf[20];
index 930723e..5d0c658 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,
-                                               "libgo_unsafe",
+                                               "libgo_unsafe.unsafe",
                                                location, &add_to_globals);
 
   if (package == NULL)
index 66b39cd..eb9ed9a 100644 (file)
@@ -1,6 +1,6 @@
 ; lang.opt -- Options for the gcc Go front end.
 
-; Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc.
+; Copyright (C) 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
 ;
 ; This file is part of GCC.
 ;
@@ -53,6 +53,10 @@ fgo-optimize-
 Go Joined RejectNegative
 -fgo-optimize-<type>   Turn on optimization passes in the frontend
 
+fgo-pkgpath=
+Go Joined RejectNegative
+-fgo-pkgpath=<string>  Set Go package path
+
 fgo-prefix=
 Go Joined RejectNegative
 -fgo-prefix=<string>   Set package-specific prefix for exported Go names