1
0
mirror of https://github.com/golang/go synced 2024-11-25 11:17:56 -07:00

gc: bug fixes.

* better error for lookup of unexported field
  * do not assign "ideal string" type to typed string literal
  * do not confuse methods and fields during interface check

Fixes #410.
Fixes #411.
Fixes #426.

R=ken2
https://golang.org/cl/179069
This commit is contained in:
Russ Cox 2009-12-15 16:22:04 -08:00
parent 101f499fa5
commit 5d754bfaea
5 changed files with 87 additions and 11 deletions

View File

@ -320,7 +320,7 @@ Sym*
restrictlookup(char *name, char *pkg) restrictlookup(char *name, char *pkg)
{ {
if(!exportname(name) && strcmp(pkg, package) != 0) if(!exportname(name) && strcmp(pkg, package) != 0)
yyerror("cannot refer to %s.%s", pkg, name); yyerror("cannot refer to unexported name %s.%s", pkg, name);
return pkglookup(name, pkg); return pkglookup(name, pkg);
} }
@ -2871,6 +2871,10 @@ ifacelookdot(Sym *s, Type *t, int *followptr)
break; break;
} }
} }
if(m->type->etype != TFUNC || m->type->thistuple == 0) {
yyerror("%T.%S is a field, not a method", t, s);
return T;
}
return m; return m;
} }
} }

View File

@ -18,10 +18,10 @@
static void implicitstar(Node**); static void implicitstar(Node**);
static int onearg(Node*); static int onearg(Node*);
static int lookdot(Node*, Type*); static int lookdot(Node*, Type*, int);
static void typecheckaste(int, Type*, NodeList*, char*); static void typecheckaste(int, Type*, NodeList*, char*);
static int exportassignok(Type*, char*); static int exportassignok(Type*, char*);
static Type* lookdot1(Sym *s, Type *t, Type *f); static Type* lookdot1(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 addrescapes(Node*); static void addrescapes(Node*);
@ -102,7 +102,7 @@ reswitch:
*/ */
case OLITERAL: case OLITERAL:
ok |= Erv; ok |= Erv;
if(n->val.ctype == CTSTR) if(n->type == T && n->val.ctype == CTSTR)
n->type = idealstring; n->type = idealstring;
goto ret; goto ret;
@ -459,7 +459,10 @@ reswitch:
n->op = ODOTPTR; n->op = ODOTPTR;
checkwidth(t); checkwidth(t);
} }
if(!lookdot(n, t)) { if(!lookdot(n, t, 0)) {
if(lookdot(n, t, 1))
yyerror("%#N undefined (cannot refer to unexported field %S)", n, n->right->sym);
else
yyerror("%#N undefined (type %T has no field %S)", n, t, n->right->sym); yyerror("%#N undefined (type %T has no field %S)", n, t, n->right->sym);
goto error; goto error;
} }
@ -1168,12 +1171,14 @@ onearg(Node *n)
} }
static Type* static Type*
lookdot1(Sym *s, Type *t, Type *f) lookdot1(Sym *s, Type *t, Type *f, int dostrcmp)
{ {
Type *r; Type *r;
r = T; r = T;
for(; f!=T; f=f->down) { for(; f!=T; f=f->down) {
if(dostrcmp && strcmp(f->sym->name, s->name) == 0)
return f;
if(f->sym != s) if(f->sym != s)
continue; continue;
if(r != T) { if(r != T) {
@ -1186,7 +1191,7 @@ lookdot1(Sym *s, Type *t, Type *f)
} }
static int static int
lookdot(Node *n, Type *t) lookdot(Node *n, Type *t, int dostrcmp)
{ {
Type *f1, *f2, *tt, *rcvr; Type *f1, *f2, *tt, *rcvr;
Sym *s; Sym *s;
@ -1196,11 +1201,11 @@ lookdot(Node *n, Type *t)
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); f1 = lookdot1(s, t, t->type, dostrcmp);
f2 = methtype(n->left->type); f2 = methtype(n->left->type);
if(f2 != T) if(f2 != T)
f2 = lookdot1(s, f2, f2->method); f2 = lookdot1(s, f2, f2->method, dostrcmp);
if(f1 != T) { if(f1 != T) {
if(f2 != T) if(f2 != T)
@ -1793,7 +1798,7 @@ typecheckcomplit(Node **np)
} }
l->left = newname(s); l->left = newname(s);
l->left->typecheck = 1; l->left->typecheck = 1;
f = lookdot1(s, t, t->type); f = lookdot1(s, t, t->type, 0);
typecheck(&l->right, Erv); typecheck(&l->right, Erv);
if(f == nil) { if(f == nil) {
yyerror("unknown %T field '%s' in struct literal", t, s->name); yyerror("unknown %T field '%s' in struct literal", t, s->name);

20
test/fixedbugs/bug229.go Normal file
View File

@ -0,0 +1,20 @@
// errchk $G -e $D/$F.go
// Copyright 2009 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 main
import "testing"
func main() {
var t testing.T
// make sure error mentions that
// ch is unexported, not just "ch not found".
t.ch = nil // ERROR "unexported"
println(testing.anyLowercaseName("asdf")) // ERROR "unexported"
}

25
test/fixedbugs/bug230.go Normal file
View File

@ -0,0 +1,25 @@
// $G $D/$F.go && $L $F.$A && ./$A.out
// Copyright 2009 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 main
type S string
type I int
type F float
func (S) m() {}
func (I) m() {}
func (F) m() {}
func main() {
c := make(chan interface { m() }, 10)
c <- I(0)
c <- F(1)
c <- S("hi")
<-c
<-c
<-c
}

22
test/fixedbugs/bug231.go Normal file
View File

@ -0,0 +1,22 @@
// errchk $G -e $D/$F.go
// Copyright 2009 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 main
type I interface { m() }
type T struct { m func() }
type M struct {}
func (M) m() {}
func main() {
var t T
var m M
var i I
i = m
i = t // ERROR "not a method"
_ = i
}