Patchwork gccgo patch committed: Don't emit methods for identical unnamed structs

login
register
mail settings
Submitter Ian Taylor
Date Feb. 1, 2013, 12:23 a.m.
Message ID <mcr38xgvq4k.fsf@google.com>
Download mbox | patch
Permalink /patch/217310/
State New
Headers show

Comments

Ian Taylor - Feb. 1, 2013, 12:23 a.m.
When a source file has multiple identical unnamed structs, and those
structs have methods, gccgo would emit multiple copies of the methods.
That would be bad because each copy would have the same name, causing an
assembler error about multiply defined symbols.  This patch fixes the
problem.  Bootstrapped and ran Go testsuite on x86_64-unknown-linux-gnu.
Committed to mainline.

Ian

Patch

diff -r 73fde5ee3282 go/types.cc
--- a/go/types.cc	Thu Jan 31 15:11:34 2013 -0800
+++ b/go/types.cc	Thu Jan 31 16:20:32 2013 -0800
@@ -4170,6 +4170,11 @@ 
 
 // Class Struct_type.
 
+// A hash table used to find identical unnamed structs so that they
+// share method tables.
+
+Struct_type::Identical_structs Struct_type::identical_structs;
+
 // Traversal.
 
 int
@@ -4596,6 +4601,21 @@ 
 {
   if (this->all_methods_ != NULL)
     return;
+
+  // It is possible to have multiple identical structs that have
+  // methods.  We want them to share method tables.  Otherwise we will
+  // emit identical methods more than once, which is bad since they
+  // will even have the same names.
+  std::pair<Identical_structs::iterator, bool> ins =
+    Struct_type::identical_structs.insert(std::make_pair(this, this));
+  if (!ins.second)
+    {
+      // An identical struct was already entered into the hash table.
+      // Note that finalize_methods is, fortunately, not recursive.
+      this->all_methods_ = ins.first->second->all_methods_;
+      return;
+    }
+
   Type::finalize_methods(gogo, this, this->location_, &this->all_methods_);
 }
 
diff -r 73fde5ee3282 go/types.h
--- a/go/types.h	Thu Jan 31 15:11:34 2013 -0800
+++ b/go/types.h	Thu Jan 31 16:20:32 2013 -0800
@@ -2184,6 +2184,12 @@ 
   do_export(Export*) const;
 
  private:
+  // Used to merge method sets of identical unnamed structs.
+  typedef Unordered_map_hash(Struct_type*, Struct_type*, Type_hash_identical,
+			     Type_identical) Identical_structs;
+
+  static Identical_structs identical_structs;
+
   // Used to avoid infinite loops in field_reference_depth.
   struct Saw_named_type
   {