Patchwork [gccgo] Dereference field if necessary to find methods

login
register
mail settings
Submitter Ian Taylor
Date Nov. 10, 2010, 10:35 p.m.
Message ID <mcrlj50vmb9.fsf@google.com>
Download mbox | patch
Permalink /patch/70700/
State New
Headers show

Comments

Ian Taylor - Nov. 10, 2010, 10:35 p.m.
In Go code like

type S struct {
	i int
}
func (p *S) Get() int {
	return p.i
}
type T struct {
	p **S
}
func f(t *T) int {
	return t.p.Get()
}

gccgo was failing to dereference t.p when looking for the method.  The
dereference is required because selector expressions like t.p
dereference if necessary, and in this case the method is on the type *S
and the field has the type **S.  This patch fixes the problem.
Committed to gccgo branch.

Ian

Patch

diff -r a40c51507619 go/types.cc
--- a/go/types.cc	Tue Nov 09 21:53:45 2010 -0800
+++ b/go/types.cc	Wed Nov 10 14:24:04 2010 -0800
@@ -7450,6 +7450,21 @@ 
   const Struct_type* st = type->deref()->struct_type();
   const Interface_type* it = type->deref()->interface_type();
 
+  // If this is a pointer to a pointer, then it is possible that the
+  // pointed-to type has methods.
+  if (nt == NULL
+      && st == NULL
+      && it == NULL
+      && type->points_to() != NULL
+      && type->points_to()->points_to() != NULL)
+    {
+      expr = Expression::make_unary(OPERATOR_MULT, expr, location);
+      type = type->points_to();
+      nt = type->points_to()->named_type();
+      st = type->points_to()->struct_type();
+      it = type->points_to()->interface_type();
+    }
+
   bool receiver_can_be_pointer = (expr->type()->points_to() != NULL
 				  || expr->is_addressable());
   bool is_method = false;