aboutsummaryrefslogtreecommitdiff
path: root/gcc/go
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@google.com>2012-05-09 21:17:23 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2012-05-09 21:17:23 +0000
commit097b12fb975ba045fffebc2cb1de407d3dba4bbc (patch)
tree35b68564005a08b6b179869395daba334368b0bc /gcc/go
parent1b8b126f386ffff12b02f7c9cb2a00c38996f1ea (diff)
downloadgcc-097b12fb975ba045fffebc2cb1de407d3dba4bbc.zip
gcc-097b12fb975ba045fffebc2cb1de407d3dba4bbc.tar.gz
gcc-097b12fb975ba045fffebc2cb1de407d3dba4bbc.tar.bz2
compiler: Add -fgo-pkgpath option.
* 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. From-SVN: r187356
Diffstat (limited to 'gcc/go')
-rw-r--r--gcc/go/ChangeLog16
-rw-r--r--gcc/go/gccgo.texi28
-rw-r--r--gcc/go/go-c.h4
-rw-r--r--gcc/go/go-gcc.cc8
-rw-r--r--gcc/go/go-lang.c13
-rw-r--r--gcc/go/gofrontend/backend.h16
-rw-r--r--gcc/go/gofrontend/export.cc35
-rw-r--r--gcc/go/gofrontend/export.h6
-rw-r--r--gcc/go/gofrontend/go.cc35
-rw-r--r--gcc/go/gofrontend/gogo-tree.cc28
-rw-r--r--gcc/go/gofrontend/gogo.cc256
-rw-r--r--gcc/go/gofrontend/gogo.h115
-rw-r--r--gcc/go/gofrontend/import.cc101
-rw-r--r--gcc/go/gofrontend/parse.cc12
-rw-r--r--gcc/go/gofrontend/types.cc98
-rw-r--r--gcc/go/gofrontend/unsafe.cc2
-rw-r--r--gcc/go/lang.opt4
17 files changed, 457 insertions, 320 deletions
diff --git a/gcc/go/ChangeLog b/gcc/go/ChangeLog
index 951d3f9..67989fdb 100644
--- a/gcc/go/ChangeLog
+++ b/gcc/go/ChangeLog
@@ -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-30 Jan Hubicka <jh@suse.cz>
* gogo-tree.cc (Gogo::write_globals): Use finalize_compilation_unit.
diff --git a/gcc/go/gccgo.texi b/gcc/go/gccgo.texi
index 5d0efb4..a5e37e7 100644
--- a/gcc/go/gccgo.texi
+++ b/gcc/go/gccgo.texi
@@ -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
diff --git a/gcc/go/go-c.h b/gcc/go/go-c.h
index e123d52..d46a087 100644
--- a/gcc/go/go-c.h
+++ b/gcc/go/go-c.h
@@ -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,
diff --git a/gcc/go/go-gcc.cc b/gcc/go/go-gcc.cc
index 08950b8..4729a3b 100644
--- a/gcc/go/go-gcc.cc
+++ b/gcc/go/go-gcc.cc
@@ -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;
diff --git a/gcc/go/go-lang.c b/gcc/go/go-lang.c
index 895e39d..f02f769 100644
--- a/gcc/go/go-lang.c
+++ b/gcc/go/go-lang.c
@@ -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:
diff --git a/gcc/go/gofrontend/backend.h b/gcc/go/gofrontend/backend.h
index d314045..2b14132 100644
--- a/gcc/go/gofrontend/backend.h
+++ b/gcc/go/gofrontend/backend.h
@@ -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,
diff --git a/gcc/go/gofrontend/export.cc b/gcc/go/gofrontend/export.cc
index 1745967..13c61a5 100644
--- a/gcc/go/gofrontend/export.cc
+++ b/gcc/go/gofrontend/export.cc
@@ -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.
diff --git a/gcc/go/gofrontend/export.h b/gcc/go/gofrontend/export.h
index 0e03f48..c6a4810 100644
--- a/gcc/go/gofrontend/export.h
+++ b/gcc/go/gofrontend/export.h
@@ -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.
diff --git a/gcc/go/gofrontend/go.cc b/gcc/go/gofrontend/go.cc
index bfa3afd..1f2ce8a 100644
--- a/gcc/go/gofrontend/go.cc
+++ b/gcc/go/gofrontend/go.cc
@@ -13,11 +13,6 @@
#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
diff --git a/gcc/go/gofrontend/gogo-tree.cc b/gcc/go/gofrontend/gogo-tree.cc
index 9dea885..5f74de5 100644
--- a/gcc/go/gofrontend/gogo-tree.cc
+++ b/gcc/go/gofrontend/gogo-tree.cc
@@ -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;
}
@@ -984,7 +982,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_);
@@ -1277,9 +1275,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));
}
@@ -1382,10 +1386,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));
}
diff --git a/gcc/go/gofrontend/gogo.cc b/gcc/go/gofrontend/gogo.cc
index f9982cc..80ffe24 100644
--- a/gcc/go/gofrontend/gogo.cc
+++ b/gcc/go/gofrontend/gogo.cc
@@ -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
diff --git a/gcc/go/gofrontend/gogo.h b/gcc/go/gofrontend/gogo.h
index 4990bf2..deb9968 100644
--- a/gcc/go/gofrontend/gogo.h
+++ b/gcc/go/gofrontend/gogo.h
@@ -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
diff --git a/gcc/go/gofrontend/import.cc b/gcc/go/gofrontend/import.cc
index b0d1008..9febf23 100644
--- a/gcc/go/gofrontend/import.cc
+++ b/gcc/go/gofrontend/import.cc
@@ -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;
}
diff --git a/gcc/go/gofrontend/parse.cc b/gcc/go/gofrontend/parse.cc
index fc2c229..29323f0 100644
--- a/gcc/go/gofrontend/parse.cc
+++ b/gcc/go/gofrontend/parse.cc
@@ -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,
diff --git a/gcc/go/gofrontend/types.cc b/gcc/go/gofrontend/types.cc
index 74bab41..35770c7 100644
--- a/gcc/go/gofrontend/types.cc
+++ b/gcc/go/gofrontend/types.cc
@@ -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];
diff --git a/gcc/go/gofrontend/unsafe.cc b/gcc/go/gofrontend/unsafe.cc
index 930723e..5d0c658 100644
--- a/gcc/go/gofrontend/unsafe.cc
+++ b/gcc/go/gofrontend/unsafe.cc
@@ -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)
diff --git a/gcc/go/lang.opt b/gcc/go/lang.opt
index c14df9c..eb9ed9a 100644
--- a/gcc/go/lang.opt
+++ b/gcc/go/lang.opt
@@ -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