{
Package* package = p->second;
package->set_location(location);
- package->set_is_imported();
std::string ln = local_name;
bool is_ln_exported = is_local_name_exported;
if (ln.empty())
go_assert(!ln.empty());
is_ln_exported = Lex::is_exported_name(ln);
}
- if (ln == ".")
+ if (ln == "_")
+ ;
+ else if (ln == ".")
{
Bindings* bindings = package->bindings();
for (Bindings::const_declarations_iterator p =
p != bindings->end_declarations();
++p)
this->add_dot_import_object(p->second);
+ std::string dot_alias = "." + package->package_name();
+ package->add_alias(dot_alias, location);
}
- else if (ln == "_")
- package->set_uses_sink_alias();
else
{
+ package->add_alias(ln, location);
ln = this->pack_hidden_name(ln, is_ln_exported);
this->package_->bindings()->add_package(ln, package);
}
"being compiled (see -fgo-pkgpath option)"));
this->imports_.insert(std::make_pair(filename, package));
- package->set_is_imported();
}
delete stream;
if (ret != NULL)
{
if (ret->package() != NULL)
- ret->package()->note_usage();
+ {
+ std::string dot_alias = "." + ret->package()->package_name();
+ ret->package()->note_usage(dot_alias);
+ }
return ret;
}
}
*padd_to_globals = false;
- if (alias_arg == ".")
- *padd_to_globals = true;
- else if (alias_arg == "_")
- ret->set_uses_sink_alias();
+ if (alias_arg == "_")
+ ;
+ else if (alias_arg == ".")
+ {
+ *padd_to_globals = true;
+ std::string dot_alias = "." + real_name;
+ ret->add_alias(dot_alias, location);
+ }
else
{
std::string alias = alias_arg;
alias = real_name;
is_alias_exported = Lex::is_exported_name(alias);
}
+ ret->add_alias(alias, location);
alias = this->pack_hidden_name(alias, is_alias_exported);
Named_object* no = this->package_->bindings()->add_package(alias, ret);
if (!no->is_package())
++p)
{
Package* package = p->second;
- if (package != this->package_
- && package->is_imported()
- && !package->used()
- && !package->uses_sink_alias()
- && !quiet)
- error_at(package->location(), "imported and not used: %s",
- Gogo::message_name(package->package_name()).c_str());
- package->clear_is_imported();
- package->clear_uses_sink_alias();
+ if (package != this->package_ && !quiet)
+ {
+ for (Package::Aliases::const_iterator p1 = package->aliases().begin();
+ p1 != package->aliases().end();
+ ++p1)
+ {
+ if (!p1->second->used())
+ {
+ // Give a more refined error message if the alias name is known.
+ std::string pkg_name = package->package_name();
+ if (p1->first != pkg_name && p1->first[0] != '.')
+ {
+ error_at(p1->second->location(),
+ "imported and not used: %s as %s",
+ Gogo::message_name(pkg_name).c_str(),
+ Gogo::message_name(p1->first).c_str());
+ }
+ else
+ error_at(p1->second->location(),
+ "imported and not used: %s",
+ Gogo::message_name(pkg_name).c_str());
+ }
+ }
+ }
package->clear_used();
}
}
const std::string& pkgpath_symbol, Location location)
: pkgpath_(pkgpath), pkgpath_symbol_(pkgpath_symbol),
package_name_(), bindings_(new Bindings(NULL)), priority_(0),
- location_(location), used_(false), is_imported_(false),
- uses_sink_alias_(false)
+ location_(location)
{
go_assert(!pkgpath.empty());
this->priority_ = priority;
}
+// Note that symbol from this package was and qualified by ALIAS.
+
+void
+Package::note_usage(const std::string& alias) const
+{
+ Aliases::const_iterator p = this->aliases_.find(alias);
+ go_assert(p != this->aliases_.end());
+ p->second->note_usage();
+}
+
// Forget a given usage. If forgetting this usage means this package becomes
// unused, report that error.
if (this->fake_uses_.empty())
error_at(this->location(), "imported and not used: %s",
- Gogo::message_name(this->package_name()).c_str());
+ Gogo::message_name(this->package_name()).c_str());
}
// Clear the used field for the next file. If the only usages of this package
void
Package::clear_used()
{
- if (this->used_ > this->fake_uses_.size())
+ std::string dot_alias = "." + this->package_name();
+ Aliases::const_iterator p = this->aliases_.find(dot_alias);
+ if (p != this->aliases_.end() && p->second->used() > this->fake_uses_.size())
this->fake_uses_.clear();
- this->used_ = 0;
+ this->aliases_.clear();
+}
+
+Package_alias*
+Package::add_alias(const std::string& alias, Location location)
+{
+ Aliases::const_iterator p = this->aliases_.find(alias);
+ if (p == this->aliases_.end())
+ {
+ std::pair<Aliases::iterator, bool> ret;
+ ret = this->aliases_.insert(std::make_pair(alias,
+ new Package_alias(location)));
+ p = ret.first;
+ }
+ return p->second;
}
// Determine types of constants. Everything else in a package
Blabel* blabel_;
};
+// An alias for an imported package.
+
+class Package_alias
+{
+ public:
+ Package_alias(Location location)
+ : location_(location), used_(0)
+ { }
+
+ // The location of the import statement.
+ Location
+ location()
+ { return this->location_; }
+
+ // How many symbols from the package were used under this alias.
+ size_t
+ used() const
+ { return this->used_; }
+
+ // Note that some symbol was used under this alias.
+ void
+ note_usage()
+ { this->used_++; }
+
+ private:
+ // The location of the import statement.
+ Location location_;
+ // The amount of times some name from this package was used under this alias.
+ size_t used_;
+};
+
// An imported package.
class Package
void
set_pkgpath_symbol(const std::string&);
- // Return the location of the import statement.
+ // Return the location of the most recent import statement.
Location
location() const
{ return this->location_; }
bindings()
{ return this->bindings_; }
- // Whether some symbol from the package was used.
- bool
- used() const
- { return this->used_ > 0; }
+ // Type used to map import names to package aliases.
+ typedef std::map<std::string, Package_alias*> Aliases;
- // Note that some symbol from this package was used.
+ // Return the set of package aliases.
+ const Aliases&
+ aliases() const
+ { return this->aliases_; }
+
+ // Note that some symbol from this package was used and qualified by ALIAS.
+ // For dot imports, the ALIAS should be ".PACKAGE_NAME".
void
- note_usage() const
- { this->used_++; }
+ note_usage(const std::string& alias) const;
// Note that USAGE might be a fake usage of this package.
void
void
clear_used();
- // Whether this package was imported in the current file.
- bool
- is_imported() const
- { return this->is_imported_; }
-
- // Note that this package was imported in the current file.
- void
- set_is_imported()
- { this->is_imported_ = true; }
-
- // Clear the imported field for the next file.
- void
- clear_is_imported()
- { this->is_imported_ = false; }
-
- // Whether this package was imported with a name of "_".
- bool
- uses_sink_alias() const
- { return this->uses_sink_alias_; }
-
- // Note that this package was imported with a name of "_".
- void
- set_uses_sink_alias()
- { this->uses_sink_alias_ = true; }
-
- // Clear the sink alias field for the next file.
- void
- clear_uses_sink_alias()
- { this->uses_sink_alias_ = false; }
-
// Look up a name in the package. Returns NULL if the name is not
// found.
Named_object*
set_location(Location location)
{ this->location_ = location; }
+ // Add a package name as an ALIAS for this package.
+ Package_alias*
+ add_alias(const std::string& alias, Location);
+
// Add a constant to the package.
Named_object*
add_constant(const Typed_identifier& tid, Expression* expr)
// than the priority of all of the packages that it imports. This
// is used to run init functions in the right order.
int priority_;
- // The location of the import statement.
+ // The location of the most recent import statement.
Location location_;
- // The amount of times some name from this package was used. This is mutable
- // because we can use a package even if we have a const pointer to it.
- mutable size_t used_;
- // A set of possibly fake uses of this package. This is mutable because we
+ // The set of aliases associated with this package.
+ Aliases aliases_;
+ // A set of possibly fake uses of this package. This is mutable because we
// can track fake uses of a package even if we have a const pointer to it.
mutable std::set<Expression*> fake_uses_;
- // True if this package was imported in the current file.
- bool is_imported_;
- // True if this package was imported with a name of "_".
- bool uses_sink_alias_;
};
// Return codes for the traversal functions. This is not an enum