mirror of
https://github.com/golang/go
synced 2024-11-21 23:04:39 -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:
parent
101f499fa5
commit
5d754bfaea
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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,8 +459,11 @@ reswitch:
|
|||||||
n->op = ODOTPTR;
|
n->op = ODOTPTR;
|
||||||
checkwidth(t);
|
checkwidth(t);
|
||||||
}
|
}
|
||||||
if(!lookdot(n, t)) {
|
if(!lookdot(n, t, 0)) {
|
||||||
yyerror("%#N undefined (type %T has no field %S)", n, t, n->right->sym);
|
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);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
switch(n->op) {
|
switch(n->op) {
|
||||||
@ -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
20
test/fixedbugs/bug229.go
Normal 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
25
test/fixedbugs/bug230.go
Normal 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
22
test/fixedbugs/bug231.go
Normal 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
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user