From 46311016894d30b5898382f1f5bada88fb00a34d Mon Sep 17 00:00:00 2001
From: Ian Lance Taylor <ian@gcc.gnu.org>
Date: Sat, 4 Feb 2012 01:41:24 +0000
Subject: [PATCH] compiler, reflect: Fix hash codes of named types, fix PtrTo
 hash.

From-SVN: r183889
---
 gcc/go/gofrontend/types.cc   |  7 ++++++-
 libgo/go/reflect/all_test.go | 12 ++++++++++++
 libgo/go/reflect/type.go     | 18 ++++++++++++++++--
 3 files changed, 34 insertions(+), 3 deletions(-)

diff --git a/gcc/go/gofrontend/types.cc b/gcc/go/gofrontend/types.cc
index 0bbe3c5b7cab..41bf491dff9e 100644
--- a/gcc/go/gofrontend/types.cc
+++ b/gcc/go/gofrontend/types.cc
@@ -1658,7 +1658,12 @@ Type::type_descriptor_constructor(Gogo* gogo, int runtime_type_kind,
 
   ++p;
   go_assert(p->is_field_name("hash"));
-  mpz_set_ui(iv, this->hash_for_method(gogo));
+  unsigned int h;
+  if (name != NULL)
+    h = name->hash_for_method(gogo);
+  else
+    h = this->hash_for_method(gogo);
+  mpz_set_ui(iv, h);
   vals->push_back(Expression::make_integer(&iv, p->type(), bloc));
 
   ++p;
diff --git a/libgo/go/reflect/all_test.go b/libgo/go/reflect/all_test.go
index 902a359786db..11dfb3fe516d 100644
--- a/libgo/go/reflect/all_test.go
+++ b/libgo/go/reflect/all_test.go
@@ -1528,6 +1528,18 @@ func TestAddr(t *testing.T) {
 	if p.X != 4 {
 		t.Errorf("Addr.Elem.Set valued to set value in top value")
 	}
+
+	// Verify that taking the address of a type gives us a pointer
+	// which we can convert back using the usual interface
+	// notation.
+	var s struct {
+		B *bool
+	}
+	ps := ValueOf(&s).Elem().Field(0).Addr().Interface()
+	*(ps.(**bool)) = new(bool)
+	if s.B == nil {
+		t.Errorf("Addr.Interface direct assignment failed")
+	}
 }
 
 /* gccgo does do allocations here.
diff --git a/libgo/go/reflect/type.go b/libgo/go/reflect/type.go
index e30cf088bb15..02855df0f390 100644
--- a/libgo/go/reflect/type.go
+++ b/libgo/go/reflect/type.go
@@ -999,6 +999,17 @@ func (ct *commonType) ptrTo() *commonType {
 		return &p.commonType
 	}
 
+	s := "*" + *ct.string
+
+	canonicalTypeLock.RLock()
+	r, ok := canonicalType[s]
+	canonicalTypeLock.RUnlock()
+	if ok {
+		ptrMap.m[ct] = (*ptrType)(unsafe.Pointer(r.(*commonType)))
+		ptrMap.Unlock()
+		return r.(*commonType)
+	}
+
 	rp := new(runtime.PtrType)
 
 	// initialize p using *byte's ptrType as a prototype.
@@ -1008,7 +1019,6 @@ func (ct *commonType) ptrTo() *commonType {
 	bp := (*ptrType)(unsafe.Pointer(unsafe.Typeof((*byte)(nil)).(*runtime.PtrType)))
 	*p = *bp
 
-	s := "*" + *ct.string
 	p.string = &s
 
 	// For the type structures linked into the binary, the
@@ -1016,12 +1026,16 @@ func (ct *commonType) ptrTo() *commonType {
 	// Create a good hash for the new string by using
 	// the FNV-1 hash's mixing function to combine the
 	// old hash and the new "*".
-	p.hash = ct.hash*16777619 ^ '*'
+	// p.hash = ct.hash*16777619 ^ '*'
+	// This is the gccgo version.
+	p.hash = (ct.hash << 4) + 9
 
 	p.uncommonType = nil
 	p.ptrToThis = nil
 	p.elem = (*runtime.Type)(unsafe.Pointer(ct))
 
+	p = canonicalize(p).(*ptrType)
+
 	ptrMap.m[ct] = p
 	ptrMap.Unlock()
 	return &p.commonType
-- 
GitLab