1
# DP: Backport fix for the generated hash functions of types that are
2
# DP: aliases for structures containing unexported fields.
4
--- a/src/gcc/go/gofrontend/types.cc
5
+++ b/src/gcc/go/gofrontend/types.cc
6
@@ -1834,7 +1834,9 @@ Type::write_specific_type_functions(Gogo* gogo, Named_type* name,
8
gogo->start_block(bloc);
10
- if (this->struct_type() != NULL)
11
+ if (name != NULL && name->real_type()->named_type() != NULL)
12
+ this->write_named_hash(gogo, name, hash_fntype, equal_fntype);
13
+ else if (this->struct_type() != NULL)
14
this->struct_type()->write_hash_function(gogo, name, hash_fntype,
16
else if (this->array_type() != NULL)
17
@@ -1852,7 +1854,9 @@ Type::write_specific_type_functions(Gogo* gogo, Named_type* name,
19
gogo->start_block(bloc);
21
- if (this->struct_type() != NULL)
22
+ if (name != NULL && name->real_type()->named_type() != NULL)
23
+ this->write_named_equal(gogo, name);
24
+ else if (this->struct_type() != NULL)
25
this->struct_type()->write_equal_function(gogo, name);
26
else if (this->array_type() != NULL)
27
this->array_type()->write_equal_function(gogo, name);
28
@@ -1865,6 +1869,100 @@ Type::write_specific_type_functions(Gogo* gogo, Named_type* name,
29
gogo->finish_function(bloc);
32
+// Write a hash function that simply calls the hash function for a
33
+// named type. This is used when one named type is defined as
34
+// another. This ensures that this case works when the other named
35
+// type is defined in another package and relies on calling hash
36
+// functions defined only in that package.
39
+Type::write_named_hash(Gogo* gogo, Named_type* name,
40
+ Function_type* hash_fntype, Function_type* equal_fntype)
42
+ Location bloc = Linemap::predeclared_location();
44
+ Named_type* base_type = name->real_type()->named_type();
45
+ go_assert(base_type != NULL);
47
+ // The pointer to the type we are going to hash. This is an
49
+ Named_object* key_arg = gogo->lookup("key", NULL);
50
+ go_assert(key_arg != NULL);
52
+ // The size of the type we are going to hash.
53
+ Named_object* keysz_arg = gogo->lookup("key_size", NULL);
54
+ go_assert(keysz_arg != NULL);
56
+ Named_object* hash_fn;
57
+ Named_object* equal_fn;
58
+ name->real_type()->type_functions(gogo, base_type, hash_fntype, equal_fntype,
59
+ &hash_fn, &equal_fn);
61
+ // Call the hash function for the base type.
62
+ Expression* key_ref = Expression::make_var_reference(key_arg, bloc);
63
+ Expression* keysz_ref = Expression::make_var_reference(keysz_arg, bloc);
64
+ Expression_list* args = new Expression_list();
65
+ args->push_back(key_ref);
66
+ args->push_back(keysz_ref);
67
+ Expression* func = Expression::make_func_reference(hash_fn, NULL, bloc);
68
+ Expression* call = Expression::make_call(func, args, false, bloc);
70
+ // Return the hash of the base type.
71
+ Expression_list* vals = new Expression_list();
72
+ vals->push_back(call);
73
+ Statement* s = Statement::make_return_statement(vals, bloc);
74
+ gogo->add_statement(s);
77
+// Write an equality function that simply calls the equality function
78
+// for a named type. This is used when one named type is defined as
79
+// another. This ensures that this case works when the other named
80
+// type is defined in another package and relies on calling equality
81
+// functions defined only in that package.
84
+Type::write_named_equal(Gogo* gogo, Named_type* name)
86
+ Location bloc = Linemap::predeclared_location();
88
+ // The pointers to the types we are going to compare. These have
89
+ // type unsafe.Pointer.
90
+ Named_object* key1_arg = gogo->lookup("key1", NULL);
91
+ Named_object* key2_arg = gogo->lookup("key2", NULL);
92
+ go_assert(key1_arg != NULL && key2_arg != NULL);
94
+ Named_type* base_type = name->real_type()->named_type();
95
+ go_assert(base_type != NULL);
97
+ // Build temporaries with the base type.
98
+ Type* pt = Type::make_pointer_type(base_type);
100
+ Expression* ref = Expression::make_var_reference(key1_arg, bloc);
101
+ ref = Expression::make_cast(pt, ref, bloc);
102
+ Temporary_statement* p1 = Statement::make_temporary(pt, ref, bloc);
103
+ gogo->add_statement(p1);
105
+ ref = Expression::make_var_reference(key2_arg, bloc);
106
+ ref = Expression::make_cast(pt, ref, bloc);
107
+ Temporary_statement* p2 = Statement::make_temporary(pt, ref, bloc);
108
+ gogo->add_statement(p2);
110
+ // Compare the values for equality.
111
+ Expression* t1 = Expression::make_temporary_reference(p1, bloc);
112
+ t1 = Expression::make_unary(OPERATOR_MULT, t1, bloc);
114
+ Expression* t2 = Expression::make_temporary_reference(p2, bloc);
115
+ t2 = Expression::make_unary(OPERATOR_MULT, t2, bloc);
117
+ Expression* cond = Expression::make_binary(OPERATOR_EQEQ, t1, t2, bloc);
119
+ // Return the equality comparison.
120
+ Expression_list* vals = new Expression_list();
121
+ vals->push_back(cond);
122
+ Statement* s = Statement::make_return_statement(vals, bloc);
123
+ gogo->add_statement(s);
126
// Return a composite literal for the type descriptor for a plain type
127
// of kind RUNTIME_TYPE_KIND named NAME.
129
--- a/src/gcc/go/gofrontend/types.h
130
+++ b/src/gcc/go/gofrontend/types.h
131
@@ -1138,6 +1138,13 @@ class Type
132
Function_type* equal_fntype, Named_object** hash_fn,
133
Named_object** equal_fn);
136
+ write_named_hash(Gogo*, Named_type*, Function_type* hash_fntype,
137
+ Function_type* equal_fntype);
140
+ write_named_equal(Gogo*, Named_type*);
142
// Build a composite literal for the uncommon type information.
144
uncommon_type_constructor(Gogo*, Type* uncommon_type,