Patchwork [gccgo] Give an error for conflicting initialization functions

login
register
mail settings
Submitter Ian Taylor
Date Nov. 10, 2010, 11:38 p.m.
Message ID <mcr4obovjfo.fsf@google.com>
Download mbox | patch
Permalink /patch/70732/
State New
Headers show

Comments

Ian Taylor - Nov. 10, 2010, 11:38 p.m.
Go permits importing multiple packages with the same name.  Doing this
with gccgo requires using the -fgo-prefix command line option to give
each package a unique prefix.  If somebody forgets to do that, then
there will be name conflicts.  This patch detects a particular nefarious
case of that, in which there is a conflict in the package initialization
function.  Initializing a package twice can have various bad effects.
Committed to gccgo branch.

Ian

Patch

diff -r fbdd25514551 go/gogo.cc
--- a/go/gogo.cc	Wed Nov 10 14:55:00 2010 -0800
+++ b/go/gogo.cc	Wed Nov 10 15:35:38 2010 -0800
@@ -329,6 +329,33 @@ 
   delete stream;
 }
 
+// Add an import control function for an imported package to the list.
+
+void
+Gogo::add_import_init_fn(const std::string& package_name,
+			 const std::string& init_name, int prio)
+{
+  for (std::set<Import_init>::const_iterator p =
+	 this->imported_init_fns_.begin();
+       p != this->imported_init_fns_.end();
+       ++p)
+    {
+      if (p->init_name() == init_name
+	  && (p->package_name() != package_name || p->priority() != prio))
+	{
+	  error("duplicate package initialization name %qs", init_name.c_str());
+	  inform(UNKNOWN_LOCATION, "used by package %qs at priority %d",
+		 p->package_name().c_str(), p->priority());
+	  inform(UNKNOWN_LOCATION, " and by package %qs at priority %d",
+		 package_name.c_str(), prio);
+	  return;
+	}
+    }
+
+  this->imported_init_fns_.insert(Import_init(package_name, init_name,
+					      prio));
+}
+
 // Return whether we are at the global binding level.
 
 bool
diff -r fbdd25514551 go/gogo.h
--- a/go/gogo.h	Wed Nov 10 14:55:00 2010 -0800
+++ b/go/gogo.h	Wed Nov 10 15:35:38 2010 -0800
@@ -374,11 +374,7 @@ 
   // list.
   void
   add_import_init_fn(const std::string& package_name,
-		     const std::string& init_name, int prio)
-  {
-    this->imported_init_fns_.insert(Import_init(package_name, init_name,
-						prio));
-  }
+		     const std::string& init_name, int prio);
 
   // Turn short-cut operators (&&, ||) into explicit if statements.
   void