1
0
mirror of https://github.com/golang/go synced 2024-11-22 03:34:40 -07:00

gc: eliminate duplicate ambiguous selector message

Also show actual expression in message when possible.

Fixes #2599.

R=ken2
CC=golang-dev
https://golang.org/cl/5654059
This commit is contained in:
Russ Cox 2012-02-10 22:46:56 -05:00
parent 5340510203
commit 7ae1fe420e
3 changed files with 38 additions and 10 deletions

View File

@ -2170,8 +2170,11 @@ adddot(Node *n)
goto ret; goto ret;
out: out:
if(c > 1) if(c > 1) {
yyerror("ambiguous selector %T.%S", t, s); yyerror("ambiguous selector %N", n);
n->left = N;
return n;
}
// rebuild elided dots // rebuild elided dots
for(c=d-1; c>=0; c--) for(c=d-1; c>=0; c--)

View File

@ -20,7 +20,7 @@ static int twoarg(Node*);
static int lookdot(Node*, Type*, int); static int lookdot(Node*, Type*, int);
static int looktypedot(Node*, Type*, int); static int looktypedot(Node*, Type*, int);
static void typecheckaste(int, Node*, int, Type*, NodeList*, char*); static void typecheckaste(int, Node*, int, Type*, NodeList*, char*);
static Type* lookdot1(Sym *s, Type *t, Type *f, int); static Type* lookdot1(Node*, Sym *s, Type *t, Type *f, int);
static int nokeys(NodeList*); static int nokeys(NodeList*);
static void typecheckcomplit(Node**); static void typecheckcomplit(Node**);
static void typecheckas2(Node*); static void typecheckas2(Node*);
@ -581,6 +581,8 @@ reswitch:
case OXDOT: case OXDOT:
n = adddot(n); n = adddot(n);
n->op = ODOT; n->op = ODOT;
if(n->left == N)
goto error;
// fall through // fall through
case ODOT: case ODOT:
typecheck(&n->left, Erv|Etype); typecheck(&n->left, Erv|Etype);
@ -1495,6 +1497,7 @@ implicitstar(Node **nn)
if(!isfixedarray(t)) if(!isfixedarray(t))
return; return;
n = nod(OIND, n, N); n = nod(OIND, n, N);
n->implicit = 1;
typecheck(&n, Erv); typecheck(&n, Erv);
*nn = n; *nn = n;
} }
@ -1554,7 +1557,7 @@ twoarg(Node *n)
} }
static Type* static Type*
lookdot1(Sym *s, Type *t, Type *f, int dostrcmp) lookdot1(Node *errnode, Sym *s, Type *t, Type *f, int dostrcmp)
{ {
Type *r; Type *r;
@ -1565,7 +1568,12 @@ lookdot1(Sym *s, Type *t, Type *f, int dostrcmp)
if(f->sym != s) if(f->sym != s)
continue; continue;
if(r != T) { if(r != T) {
yyerror("ambiguous selector %T.%S", t, s); if(errnode)
yyerror("ambiguous selector %N", errnode);
else if(isptr[t->etype])
yyerror("ambiguous selector (%T).%S", t, s);
else
yyerror("ambiguous selector %T.%S", t, s);
break; break;
} }
r = f; r = f;
@ -1582,7 +1590,7 @@ looktypedot(Node *n, Type *t, int dostrcmp)
s = n->right->sym; s = n->right->sym;
if(t->etype == TINTER) { if(t->etype == TINTER) {
f1 = lookdot1(s, t, t->type, dostrcmp); f1 = lookdot1(n, s, t, t->type, dostrcmp);
if(f1 == T) if(f1 == T)
return 0; return 0;
@ -1604,7 +1612,7 @@ looktypedot(Node *n, Type *t, int dostrcmp)
return 0; return 0;
expandmeth(f2->sym, f2); expandmeth(f2->sym, f2);
f2 = lookdot1(s, f2, f2->xmethod, dostrcmp); f2 = lookdot1(n, s, f2, f2->xmethod, dostrcmp);
if(f2 == T) if(f2 == T)
return 0; return 0;
@ -1643,7 +1651,7 @@ lookdot(Node *n, Type *t, int dostrcmp)
dowidth(t); dowidth(t);
f1 = T; f1 = T;
if(t->etype == TSTRUCT || t->etype == TINTER) if(t->etype == TSTRUCT || t->etype == TINTER)
f1 = lookdot1(s, t, t->type, dostrcmp); f1 = lookdot1(n, s, t, t->type, dostrcmp);
f2 = T; f2 = T;
if(n->left->type == t || n->left->type->sym == S) { if(n->left->type == t || n->left->type->sym == S) {
@ -1651,7 +1659,7 @@ lookdot(Node *n, Type *t, int dostrcmp)
if(f2 != T) { if(f2 != T) {
// Use f2->method, not f2->xmethod: adddot has // Use f2->method, not f2->xmethod: adddot has
// already inserted all the necessary embedded dots. // already inserted all the necessary embedded dots.
f2 = lookdot1(s, f2, f2->method, dostrcmp); f2 = lookdot1(n, s, f2, f2->method, dostrcmp);
} }
} }
@ -1666,6 +1674,7 @@ lookdot(Node *n, Type *t, int dostrcmp)
if(t->etype == TINTER) { if(t->etype == TINTER) {
if(isptr[n->left->type->etype]) { if(isptr[n->left->type->etype]) {
n->left = nod(OIND, n->left, N); // implicitstar n->left = nod(OIND, n->left, N); // implicitstar
n->left->implicit = 1;
typecheck(&n->left, Erv); typecheck(&n->left, Erv);
} }
n->op = ODOTINTER; n->op = ODOTINTER;
@ -2194,7 +2203,7 @@ typecheckcomplit(Node **np)
if(s->pkg != localpkg && exportname(s->name)) if(s->pkg != localpkg && exportname(s->name))
s = lookup(s->name); s = lookup(s->name);
f = lookdot1(s, t, t->type, 0); f = lookdot1(nil, s, t, t->type, 0);
if(f == nil) { if(f == nil) {
yyerror("unknown %T field '%S' in struct literal", t, s); yyerror("unknown %T field '%S' in struct literal", t, s);
continue; continue;

16
test/fixedbugs/bug412.go Normal file
View File

@ -0,0 +1,16 @@
// errchk $G $D/$F.go
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package p
type t struct {
x int // ERROR "duplicate field x"
x int
}
func f(t *t) int {
return t.x // ERROR "ambiguous selector t.x"
}