Warn about packages which are imported but not used.

R=iant
https://golang.org/cl/194163
diff --git a/go/go.cc b/go/go.cc
index ebedf51..a174b7b 100644
--- a/go/go.cc
+++ b/go/go.cc
@@ -93,6 +93,8 @@
 	fclose(file);
     }
 
+  ::gogo->clear_file_scope();
+
   // If the global predeclared names are referenced but not defined,
   // define them now.
   ::gogo->define_global_names();
diff --git a/go/gogo.cc b/go/gogo.cc
index 1febfe8..0d7bb34 100644
--- a/go/gogo.cc
+++ b/go/gogo.cc
@@ -254,6 +254,7 @@
     {
       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())
@@ -289,6 +290,7 @@
   imp.register_builtin_types(this);
   Package* package = imp.import(this, local_name, is_local_name_exported);
   this->imports_.insert(std::make_pair(filename, package));
+  package->set_is_imported();
 }
 
 // Return whether we are at the global binding level.
@@ -364,7 +366,11 @@
     {
       Named_object* ret = this->package_->bindings()->lookup(name);
       if (ret != NULL)
-	return ret;
+	{
+	  if (ret->package() != NULL)
+	    ret->package()->set_used();
+	  return ret;
+	}
     }
 
   // We do not look in the global namespace.  If we did, the global
@@ -425,7 +431,11 @@
       return this->register_package(real_name, unique_prefix, location);
     }
   else if (alias_arg == "_")
-    return this->register_package(real_name, unique_prefix, location);
+    {
+      Package* ret = this->register_package(real_name, unique_prefix, location);
+      ret->set_uses_sink_alias();
+      return ret;
+    }
   else
     {
       *padd_to_globals = false;
@@ -958,6 +968,23 @@
 Gogo::clear_file_scope()
 {
   this->package_->bindings()->clear_file_scope();
+
+  // Warn about packages which were imported but not used.
+  for (Packages::iterator p = this->packages_.begin();
+       p != this->packages_.end();
+       ++p)
+    {
+      Package* package = p->second;
+      if (package != this->package_
+	  && package->is_imported()
+	  && !package->used()
+	  && !package->uses_sink_alias())
+	error_at(package->location(), "imported and not used: %s",
+		 package->name().c_str());
+      package->clear_is_imported();
+      package->clear_uses_sink_alias();
+      package->clear_used();
+    }
 }
 
 // Traverse the tree.
@@ -3735,7 +3762,7 @@
 Package::Package(const std::string& name, const std::string& unique_prefix,
 		 source_location location)
   : name_(name), unique_prefix_(unique_prefix), bindings_(new Bindings(NULL)),
-    priority_(0), location_(location)
+    priority_(0), location_(location), used_(false), is_imported_(false)
 {
   gcc_assert(!name.empty() && !unique_prefix.empty());
 }
diff --git a/go/gogo.h b/go/gogo.h
index 703f7a7..6cbb6f2 100644
--- a/go/gogo.h
+++ b/go/gogo.h
@@ -2191,6 +2191,51 @@
   bindings()
   { return this->bindings_; }
 
+  // Whether some symbol from the package was used.
+  bool
+  used() const
+  { return this->used_; }
+
+  // Note that some symbol from this package was used.
+  void
+  set_used() const
+  { this->used_ = true; }
+
+  // Clear the used field for the next file.
+  void
+  clear_used()
+  { this->used_ = false; }
+
+  // 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*
@@ -2246,6 +2291,14 @@
   int priority_;
   // The location of the import statement.
   source_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_;
+  // 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
diff --git a/go/parse.cc b/go/parse.cc
index d52ee63..43c0345 100644
--- a/go/parse.cc
+++ b/go/parse.cc
@@ -193,6 +193,8 @@
       return false;
     }
 
+  package->package_value()->set_used();
+
   token = this->advance_token();
   if (!token->is_identifier())
     {
@@ -2023,6 +2025,7 @@
 		return Expression::make_error(location);
 	      }
 	    package = named_object->package_value();
+	    package->set_used();
 	    id = this->peek_token()->identifier();
 	    is_exported = this->peek_token()->is_identifier_exported();
 	    packed = this->gogo_->pack_hidden_name(id, is_exported);
diff --git a/go/unsafe.cc b/go/unsafe.cc
index d23aeda..be5b7cd 100644
--- a/go/unsafe.cc
+++ b/go/unsafe.cc
@@ -26,6 +26,7 @@
 						is_local_name_exported,
 						"libgo_unsafe",
 						location, &add_to_globals);
+  package->set_is_imported();
 
   Bindings* bindings = package->bindings();
 
@@ -35,6 +36,7 @@
     {
       Type* type = Type::make_pointer_type(Type::make_void_type());
       no = bindings->add_type("Pointer", package, type, UNKNOWN_LOCATION);
+      no->set_package(package);
     }
   else
     {
diff --git a/libgo/testsuite/gotest b/libgo/testsuite/gotest
index ec35e8d..89afd92 100755
--- a/libgo/testsuite/gotest
+++ b/libgo/testsuite/gotest
@@ -142,20 +142,6 @@
 
 # They all compile; now generate the code to call them.
 {
-	# package spec
-	echo 'package main'
-	echo
-        echo 'import "./_gotest_"'
-	if $havex; then
-		echo 'import "./_xtest_"'
-	fi
-        if test "$package" != "testing"; then
-		echo 'import "testing"'
-	fi
-	# test array
-	echo
-	echo 'var tests = []testing.Test {'
-
 	# test functions are named TestFoo
 	# the grep -v eliminates methods and other special names
 	# that have multiple dots.
@@ -163,12 +149,29 @@
 	tests=$(nm -s _gotest_.o $xofile | egrep ' T .*\.'$pattern'$' | grep -v '\..*\..*\.' | sed 's/.* //' | sed 's/.*\.\(.*\.\)/\1/')
 	if [ "x$tests" = x ]; then
 		echo 'gotest: warning: no tests matching '$pattern in _gotest_.o $xofile 1>&2
-	else
-		for i in $tests
-		do
-			echo '	testing.Test{ "'$i'", '$i' },'
-		done
+		exit 2
 	fi
+
+	# package spec
+	echo 'package main'
+	echo
+	# imports
+	if echo "$tests" | egrep -v '_test\.' >/dev/null; then
+		echo 'import "./_gotest_"'
+	fi
+	if $havex; then
+		echo 'import "./_xtest_"'
+	fi
+	if [ $package != "testing" ]; then
+		echo 'import "testing"'
+	fi
+	# test array
+	echo
+	echo 'var tests = []testing.Test {'
+	for i in $tests
+	do
+		echo '	testing.Test{ "'$i'", '$i' },'
+	done
 	echo '}'
 	# body
 	echo