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

Submitted by Ian Taylor on Feb. 1, 2013, 12:23 a.m.

Details

Message ID mcr38xgvq4k.fsf@google.com
State New
Headers show

Commit Message

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 hide | download patch | download mbox

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
   {