diff mbox

Go patch committed: Fix identical unnamed structs with methods

Message ID mcr1u4l23ul.fsf@iant-glaptop.roam.corp.google.com
State New
Headers show

Commit Message

Ian Lance Taylor Sept. 18, 2013, 9:54 p.m. UTC
When gccgo saw multiple identical unnamed structs with methods assigned
to interfaces that used those methods, it would emit multiple copies of
the interface method table, causing a duplicate symbol error from the
assembler.  This patch fixes the bug.  I added a test case to the master
testsuite that will be copied in the gccgo testsuite in due course.
Bootstrapped and ran Go testsuite on x86_64-unknown-linux-gnu.
Committed to mainline and 4.8 branch.

Ian
diff mbox

Patch

diff -r 6791d7b7151c go/types.cc
--- a/go/types.cc	Wed Sep 18 11:34:51 2013 -0700
+++ b/go/types.cc	Wed Sep 18 14:50:19 2013 -0700
@@ -4229,6 +4229,11 @@ 
 
 Struct_type::Identical_structs Struct_type::identical_structs;
 
+// A hash table used to merge method sets for identical unnamed
+// structs.
+
+Struct_type::Struct_method_tables Struct_type::struct_method_tables;
+
 // Traversal.
 
 int
@@ -4693,9 +4698,24 @@ 
 				    const Interface_type* interface,
 				    bool is_pointer)
 {
+  std::pair<Struct_type*, Struct_type::Struct_method_table_pair*>
+    val(this, NULL);
+  std::pair<Struct_type::Struct_method_tables::iterator, bool> ins =
+    Struct_type::struct_method_tables.insert(val);
+
+  Struct_method_table_pair* smtp;
+  if (!ins.second)
+    smtp = ins.first->second;
+  else
+    {
+      smtp = new Struct_method_table_pair();
+      smtp->first = NULL;
+      smtp->second = NULL;
+      ins.first->second = smtp;
+    }
+
   return Type::interface_method_table(gogo, this, interface, is_pointer,
-				      &this->interface_method_tables_,
-				      &this->pointer_interface_method_tables_);
+				      &smtp->first, &smtp->second);
 }
 
 // Convert struct fields to the backend representation.  This is not
diff -r 6791d7b7151c go/types.h
--- a/go/types.h	Wed Sep 18 11:34:51 2013 -0700
+++ b/go/types.h	Wed Sep 18 14:50:19 2013 -0700
@@ -2041,8 +2041,7 @@ 
  public:
   Struct_type(Struct_field_list* fields, Location location)
     : Type(TYPE_STRUCT),
-      fields_(fields), location_(location), all_methods_(NULL),
-      interface_method_tables_(NULL), pointer_interface_method_tables_(NULL)
+      fields_(fields), location_(location), all_methods_(NULL)
   { }
 
   // Return the field NAME.  This only looks at local fields, not at
@@ -2200,6 +2199,16 @@ 
 
   static Identical_structs identical_structs;
 
+  // Used to manage method tables for identical unnamed structs.
+  typedef std::pair<Interface_method_tables*, Interface_method_tables*>
+    Struct_method_table_pair;
+
+  typedef Unordered_map_hash(Struct_type*, Struct_method_table_pair*,
+			     Type_hash_identical, Type_identical)
+    Struct_method_tables;
+
+  static Struct_method_tables struct_method_tables;
+
   // Used to avoid infinite loops in field_reference_depth.
   struct Saw_named_type
   {
@@ -2218,13 +2227,6 @@ 
   Location location_;
   // If this struct is unnamed, a list of methods.
   Methods* all_methods_;
-  // A mapping from interfaces to the associated interface method
-  // tables for this type.  Only used if this struct is unnamed.
-  Interface_method_tables* interface_method_tables_;
-  // A mapping from interfaces to the associated interface method
-  // tables for pointers to this type.  Only used if this struct is
-  // unnamed.
-  Interface_method_tables* pointer_interface_method_tables_;
 };
 
 // The type of an array.