This patch to the Go frontend changes it to never build hash/equality
functions for structures created for thunks (go and defer statements).
These functions are never needed, and they can cause problems when a
thunk is used to pass an unexported type from a different package to a
function defined in that package.  The resulting struct type may need
to call the comparison routine from the other package, which will fail
because the type is not exported.  I will propose this as bug492 in
the master testsuite.  Bootstrapped and ran Go testsuite on
x86_64-unknown-linux-gnu.  Committed to mainline.

Ian
diff -r c549eac5acc2 go/statements.cc
--- a/go/statements.cc  Tue Dec 16 13:36:08 2014 -0800
+++ b/go/statements.cc  Tue Dec 16 14:47:08 2014 -0800
@@ -1884,6 +1884,8 @@
 // Class Thunk_statement.  This is the base class for go and defer
 // statements.
 
+Unordered_set(const Struct_type*) Thunk_statement::thunk_types;
+
 // Constructor.
 
 Thunk_statement::Thunk_statement(Statement_classification classification,
@@ -2265,7 +2267,20 @@
        }
     }
 
-  return Type::make_struct_type(fields, location);
+  Struct_type *st = Type::make_struct_type(fields, location);
+
+  Thunk_statement::thunk_types.insert(st);
+
+  return st;
+}
+
+// Return whether ST is a type created to hold thunk parameters.
+
+bool
+Thunk_statement::is_thunk_struct(const Struct_type* st)
+{
+  return (Thunk_statement::thunk_types.find(st)
+         != Thunk_statement::thunk_types.end());
 }
 
 // Build the thunk we are going to call.  This is a brand new, albeit
diff -r c549eac5acc2 go/statements.h
--- a/go/statements.h   Tue Dec 16 13:36:08 2014 -0800
+++ b/go/statements.h   Tue Dec 16 14:47:08 2014 -0800
@@ -985,6 +985,10 @@
   bool
   simplify_statement(Gogo*, Named_object*, Block*);
 
+  // Return whether ST is a type created to hold thunk parameters.
+  static bool
+  is_thunk_struct(const Struct_type *st);
+
  protected:
   int
   do_traverse(Traverse* traverse);
@@ -1023,6 +1027,9 @@
   void
   thunk_field_param(int n, char* buf, size_t buflen);
 
+  // A list of all the struct types created for thunk statements.
+  static Unordered_set(const Struct_type*) thunk_types;
+
   // The function call to be executed in a separate thread (go) or
   // later (defer).
   Expression* call_;
diff -r c549eac5acc2 go/types.cc
--- a/go/types.cc       Tue Dec 16 13:36:08 2014 -0800
+++ b/go/types.cc       Tue Dec 16 14:47:08 2014 -0800
@@ -1593,7 +1593,9 @@
       hash_fnname = "__go_type_hash_identity";
       equal_fnname = "__go_type_equal_identity";
     }
-  else if (!this->is_comparable())
+  else if (!this->is_comparable() ||
+          (this->struct_type() != NULL
+           && Thunk_statement::is_thunk_struct(this->struct_type())))
     {
       hash_fnname = "__go_type_hash_error";
       equal_fnname = "__go_type_equal_error";

Reply via email to