cmd/gc: disallow call of *T method using **T variable

This brings cmd/gc in line with the spec on this question.
It might break existing code, but that code was not conformant
with the spec.

Credit to Rémy for finding the broken code.

Fixes #6366.

LGTM=r
R=golang-codereviews, r
CC=adonovan, golang-codereviews, gri
https://golang.org/cl/129550043
This commit is contained in:
Russ Cox 2014-10-20 22:04:12 -04:00
parent 70f2f1b470
commit 93fcb92257
2 changed files with 8 additions and 5 deletions

View file

@ -2127,13 +2127,16 @@ lookdot(Node *n, Type *t, int dostrcmp)
n->left = nod(OADDR, n->left, N);
n->left->implicit = 1;
typecheck(&n->left, Etype|Erv);
} else if(tt->etype == tptr && eqtype(tt->type, rcvr)) {
} else if(tt->etype == tptr && rcvr->etype != tptr && eqtype(tt->type, rcvr)) {
n->left = nod(OIND, n->left, N);
n->left->implicit = 1;
typecheck(&n->left, Etype|Erv);
} else if(tt->etype == tptr && tt->type->etype == tptr && eqtype(derefall(tt), rcvr)) {
} else if(tt->etype == tptr && tt->type->etype == tptr && eqtype(derefall(tt), derefall(rcvr))) {
yyerror("calling method %N with receiver %lN requires explicit dereference", n->right, n->left);
while(tt->etype == tptr) {
// Stop one level early for method with pointer receiver.
if(rcvr->etype == tptr && tt->type->etype != tptr)
break;
n->left = nod(OIND, n->left, N);
n->left->implicit = 1;
typecheck(&n->left, Etype|Erv);

View file

@ -20,5 +20,5 @@ func main() {
q := &p
q.m() // ERROR "requires explicit dereference"
q.pm()
q.pm() // ERROR "requires explicit dereference"
}