Commit 097b12fb by Ian Lance Taylor Committed by Ian Lance Taylor

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
parent 1b8b126f
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.
......
......@@ -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
......
......@@ -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,
......
......@@ -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;
......
......@@ -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:
......
......@@ -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,
......
......@@ -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.
......
......@@ -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.
......
......@@ -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
......
......@@ -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));
}
......
......@@ -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
......
......@@ -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;
}
......
......@@ -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,
......
......@@ -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];
......
......@@ -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)
......
......@@ -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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment