aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2014-11-13 00:10:37 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2014-11-13 00:10:37 +0000
commitecd7b400c959b1ba0e006e48fac6b82253fe8834 (patch)
treec52785286d6b2d294585d421b228ed1b7ea46041 /gcc
parentbe8de8946ed904c92c09dadb158e76c9c5044d11 (diff)
downloadgcc-ecd7b400c959b1ba0e006e48fac6b82253fe8834.zip
gcc-ecd7b400c959b1ba0e006e48fac6b82253fe8834.tar.gz
gcc-ecd7b400c959b1ba0e006e48fac6b82253fe8834.tar.bz2
compiler: Do not count package uses from ambiguous lookups.
When using dot imports, it is possible to have an imported symbol name that matches the name of a struct field in a composite literal. Do not consider the imported package to be used in this situation. Fixes issue 6427. From-SVN: r217453
Diffstat (limited to 'gcc')
-rw-r--r--gcc/go/gofrontend/expressions.cc10
-rw-r--r--gcc/go/gofrontend/gogo.cc32
-rw-r--r--gcc/go/gofrontend/gogo.h28
-rw-r--r--gcc/go/gofrontend/parse.cc9
4 files changed, 66 insertions, 13 deletions
diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc
index 7124646..dba5ea0 100644
--- a/gcc/go/gofrontend/expressions.cc
+++ b/gcc/go/gofrontend/expressions.cc
@@ -12791,6 +12791,16 @@ Composite_literal_expression::lower_struct(Gogo* gogo, Type* type)
{
case EXPRESSION_UNKNOWN_REFERENCE:
name = name_expr->unknown_expression()->name();
+ if (type->named_type() != NULL)
+ {
+ // If the named object found for this field name comes from a
+ // different package than the struct it is a part of, do not count
+ // this incorrect lookup as a usage of the object's package.
+ no = name_expr->unknown_expression()->named_object();
+ if (no->package() != NULL
+ && no->package() != type->named_type()->named_object()->package())
+ no->package()->forget_usage(name_expr);
+ }
break;
case EXPRESSION_CONST_REFERENCE:
diff --git a/gcc/go/gofrontend/gogo.cc b/gcc/go/gofrontend/gogo.cc
index d6ba272..7c318ab 100644
--- a/gcc/go/gofrontend/gogo.cc
+++ b/gcc/go/gofrontend/gogo.cc
@@ -1412,7 +1412,7 @@ Gogo::lookup(const std::string& name, Named_object** pfunction) const
if (ret != NULL)
{
if (ret->package() != NULL)
- ret->package()->set_used();
+ ret->package()->note_usage();
return ret;
}
}
@@ -7426,6 +7426,36 @@ Package::set_priority(int priority)
this->priority_ = priority;
}
+// Forget a given usage. If forgetting this usage means this package becomes
+// unused, report that error.
+
+void
+Package::forget_usage(Expression* usage) const
+{
+ if (this->fake_uses_.empty())
+ return;
+
+ std::set<Expression*>::iterator p = this->fake_uses_.find(usage);
+ go_assert(p != this->fake_uses_.end());
+ this->fake_uses_.erase(p);
+
+ if (this->fake_uses_.empty())
+ error_at(this->location(), "imported and not used: %s",
+ Gogo::message_name(this->package_name()).c_str());
+}
+
+// Clear the used field for the next file. If the only usages of this package
+// are possibly fake, keep the fake usages for lowering.
+
+void
+Package::clear_used()
+{
+ if (this->used_ > this->fake_uses_.size())
+ this->fake_uses_.clear();
+
+ this->used_ = 0;
+}
+
// Determine types of constants. Everything else in a package
// (variables, function declarations) should already have a fixed
// type. Constants may have abstract types.
diff --git a/gcc/go/gofrontend/gogo.h b/gcc/go/gofrontend/gogo.h
index 4453d13..10aea69 100644
--- a/gcc/go/gofrontend/gogo.h
+++ b/gcc/go/gofrontend/gogo.h
@@ -2645,17 +2645,25 @@ class Package
// Whether some symbol from the package was used.
bool
used() const
- { return this->used_; }
+ { return this->used_ > 0; }
// Note that some symbol from this package was used.
void
- set_used() const
- { this->used_ = true; }
+ note_usage() const
+ { this->used_++; }
+
+ // Note that USAGE might be a fake usage of this package.
+ void
+ note_fake_usage(Expression* usage) const
+ { this->fake_uses_.insert(usage); }
+
+ // Forget a given USAGE of this package.
+ void
+ forget_usage(Expression* usage) const;
// Clear the used field for the next file.
void
- clear_used()
- { this->used_ = false; }
+ clear_used();
// Whether this package was imported in the current file.
bool
@@ -2749,10 +2757,12 @@ class Package
int priority_;
// The location of the import statement.
Location location_;
- // True if 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 bool used_;
+ // 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
+ // 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 "_".
diff --git a/gcc/go/gofrontend/parse.cc b/gcc/go/gofrontend/parse.cc
index d806b47..5731025 100644
--- a/gcc/go/gofrontend/parse.cc
+++ b/gcc/go/gofrontend/parse.cc
@@ -199,7 +199,7 @@ Parse::qualified_ident(std::string* pname, Named_object** ppackage)
return false;
}
- package->package_value()->set_used();
+ package->package_value()->note_usage();
token = this->advance_token();
if (!token->is_identifier())
@@ -2401,7 +2401,7 @@ Parse::operand(bool may_be_sink, bool* is_parenthesized)
return Expression::make_error(location);
}
package = named_object->package_value();
- package->set_used();
+ package->note_usage();
id = this->peek_token()->identifier();
is_exported = this->peek_token()->is_identifier_exported();
packed = this->gogo_->pack_hidden_name(id, is_exported);
@@ -3242,9 +3242,12 @@ Parse::id_to_expression(const std::string& name, Location location,
case Named_object::NAMED_OBJECT_TYPE_DECLARATION:
{
// These cases can arise for a field name in a composite
- // literal.
+ // literal. Keep track of these as they might be fake uses of
+ // the related package.
Unknown_expression* ue =
Expression::make_unknown_reference(named_object, location);
+ if (named_object->package() != NULL)
+ named_object->package()->note_fake_usage(ue);
if (this->is_erroneous_function_)
ue->set_no_error_message();
return ue;