diff mbox

Go patch committed: Fix interface method representation

Message ID mcr39a9z0uz.fsf@dhcp-172-18-216-180.mtv.corp.google.com
State New
Headers show

Commit Message

Ian Lance Taylor Feb. 17, 2012, 8 p.m. UTC
In Go an interface method always takes a receiver parameter.  The gccgo
frontend was not correctly representing that in the backend type
information generated for an interface value.  This didn't make any
difference for code generation, but it would mess up debug info and
perhaps other things as well.  This patch fixes the problem.
Bootstrapped and ran Go testusite on x86_64-unknown-linux-gnu.
Committed to mainline.

Ian
diff mbox

Patch

diff -r ec4ce2b28cd0 go/types.cc
--- a/go/types.cc	Fri Feb 17 11:25:56 2012 -0800
+++ b/go/types.cc	Fri Feb 17 11:46:23 2012 -0800
@@ -6886,10 +6886,37 @@ 
        p != type->methods()->end();
        ++p, ++i)
     {
+      // The type of the method in Go only includes the parameters.
+      // The actual method also has a receiver, which is always a
+      // pointer.  We need to add that pointer type here in order to
+      // generate the correct type for the backend.
+      Function_type* ft = p->type()->function_type();
+      go_assert(ft->receiver() == NULL);
+
+      const Typed_identifier_list* params = ft->parameters();
+      Typed_identifier_list* mparams = new Typed_identifier_list();
+      if (params != NULL)
+	mparams->reserve(params->size() + 1);
+      Type* vt = Type::make_pointer_type(Type::make_void_type());
+      mparams->push_back(Typed_identifier("", vt, ft->location()));
+      if (params != NULL)
+	{
+	  for (Typed_identifier_list::const_iterator pp = params->begin();
+	       pp != params->end();
+	       ++pp)
+	    mparams->push_back(*pp);
+	}
+
+      Typed_identifier_list* mresults = (ft->results() == NULL
+					 ? NULL
+					 : ft->results()->copy());
+      Function_type* mft = Type::make_function_type(NULL, mparams, mresults,
+						    ft->location());
+
       mfields[i].name = Gogo::unpack_hidden_name(p->name());
       mfields[i].btype = (use_placeholder
-			  ? p->type()->get_backend_placeholder(gogo)
-			  : p->type()->get_backend(gogo));
+			  ? mft->get_backend_placeholder(gogo)
+			  : mft->get_backend(gogo));
       mfields[i].location = loc;
       // Sanity check: the names should be sorted.
       go_assert(p->name() > last_name);