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";