When generating hash and equality functions for types, it's not necessary to generate them for private fields of named structs defined in different packages. There is no way that the code can call those functions directly anyhow. Generating them is problematic because it may lead to calls to functions which are not visible from the current package. This patch implements this fix. Bootstrapped and ran Go testsuite on x86_64-unknown-linux-gnu. Committed to mainline.
Ian
diff -r 7d54213ce42e go/gogo.cc --- a/go/gogo.cc Thu Jan 26 12:23:11 2012 -0800 +++ b/go/gogo.cc Thu Jan 26 13:02:49 2012 -0800 @@ -1205,13 +1205,13 @@ { case Type::TYPE_NAMED: { + Named_type* nt = t->named_type(); if (!t->compare_is_identity(this->gogo_) && t->is_comparable()) - t->type_functions(this->gogo_, t->named_type(), NULL, NULL, &hash_fn, - &equal_fn); + t->type_functions(this->gogo_, nt, NULL, NULL, &hash_fn, &equal_fn); // If this is a struct type, we don't want to make functions // for the unnamed struct. - Type* rt = t->named_type()->real_type(); + Type* rt = nt->real_type(); if (rt->struct_type() == NULL) { if (Type::traverse(rt, this) == TRAVERSE_EXIT) @@ -1219,8 +1219,20 @@ } else { - if (rt->struct_type()->traverse_field_types(this) == TRAVERSE_EXIT) - return TRAVERSE_EXIT; + // If this type is defined in another package, then we don't + // need to worry about the unexported fields. + bool is_defined_elsewhere = nt->named_object()->package() != NULL; + const Struct_field_list* fields = rt->struct_type()->fields(); + for (Struct_field_list::const_iterator p = fields->begin(); + p != fields->end(); + ++p) + { + if (is_defined_elsewhere + && Gogo::is_hidden_name(p->field_name())) + continue; + if (Type::traverse(p->type(), this) == TRAVERSE_EXIT) + return TRAVERSE_EXIT; + } } return TRAVERSE_SKIP_COMPONENTS;