more 6g reorg; checkpoint.

typecheck.c is now responsible for all type checking
except for assignment and function argument "..."

R=ken
OCL=32661
CL=32667
This commit is contained in:
Russ Cox 2009-08-03 11:58:52 -07:00
parent 178089056e
commit 9dc22b6d6f
25 changed files with 1178 additions and 1416 deletions

View file

@ -907,6 +907,8 @@ nodarg(Type *t, int fp)
n->class = PPARAM; n->class = PPARAM;
break; break;
} }
n->typecheck = 1;
return n; return n;
} }

View file

@ -200,8 +200,6 @@ bad:
defaultlit(&n, T); defaultlit(&n, T);
*np = n; *np = n;
} }
yyerror("cannot convert %T constant to %T", n->type, t);
n->diag = 1;
return; return;
} }
@ -336,6 +334,9 @@ evconst(Node *n)
switch(n->op) { switch(n->op) {
case OMAKE: case OMAKE:
case OMAKEMAP:
case OMAKESLICE:
case OMAKECHAN:
return; return;
} }
@ -557,7 +558,7 @@ evconst(Node *n)
if(cmpslit(nl, nr) > 0) if(cmpslit(nl, nr) > 0)
goto settrue; goto settrue;
goto setfalse; goto setfalse;
case TUP(OADD, CTSTR): case TUP(OADDSTR, CTSTR):
len = v.u.sval->len + nr->val.u.sval->len; len = v.u.sval->len + nr->val.u.sval->len;
str = mal(sizeof(*str) + len); str = mal(sizeof(*str) + len);
str->len = len; str->len = len;
@ -605,6 +606,7 @@ unary:
case TUP(OCONV, CTFLT): case TUP(OCONV, CTFLT):
case TUP(OCONV, CTSTR): case TUP(OCONV, CTSTR):
case TUP(OCONV, CTNIL): case TUP(OCONV, CTNIL):
case TUP(OARRAYBYTESTR, CTNIL):
convlit1(&nl, n->type, 1); convlit1(&nl, n->type, 1);
break; break;

View file

@ -672,9 +672,9 @@ funclit1(Node *ntype, NodeList *body)
for(l=func->cvars; l; l=l->next) { for(l=func->cvars; l; l=l->next) {
a = l->n; a = l->n;
d = oldname(a->sym); d = oldname(a->sym);
addrescapes(d);
args = list(args, nod(OADDR, d, N)); args = list(args, nod(OADDR, d, N));
} }
typechecklist(args, Erv);
n = nod(OCALL, clos, N); n = nod(OCALL, clos, N);
n->list = args; n->list = args;
@ -1642,7 +1642,7 @@ embedded(Sym *s)
NodeList* NodeList*
variter(NodeList *vl, Node *nt, NodeList *el) variter(NodeList *vl, Node *nt, NodeList *el)
{ {
int doexpr; int doexpr, lno;
Node *v, *e, *a; Node *v, *e, *a;
Type *tv; Type *tv;
NodeList *r; NodeList *r;
@ -1663,23 +1663,37 @@ variter(NodeList *vl, Node *nt, NodeList *el)
break; break;
} }
e = el->n; e = el->n;
el = el->next;
} else } else
e = N; e = N;
v = vl->n; v = vl->n;
tv = t; tv = t;
if(t == T) { if(e) {
lno = lineno;
lineno = v->lineno;
typecheck(&e, Erv); typecheck(&e, Erv);
defaultlit(&e, T); defaultlit(&e, t);
tv = e->type; if(t)
e = typecheckconv(nil, e, t, 0);
if(tv == nil)
tv = e->type;
if(tv && tv->etype == TNIL) {
yyerror("cannot initialize %#N to untyped nil", v);
tv = nil;
}
lineno = lno;
} }
a = N; a = N;
if(e != N || funcdepth > 0) if((e != N && tv != T) || funcdepth > 0)
a = nod(OAS, v, e); a = nod(OAS, v, e);
dodclvar(v, tv, &r); dodclvar(v, tv, &r);
if(a != N) if(a != N)
r = list(r, a); r = list(r, a);
if(el) {
el->n = e;
el = el->next;
}
} }
if(el != nil) if(el != nil)
yyerror("extra expr in var dcl"); yyerror("extra expr in var dcl");

View file

@ -328,36 +328,41 @@ enum
OLITERAL, OLITERAL,
// exprs // exprs
OADD, OSUB, OOR, OXOR, OADD, OSUB, OOR, OXOR, OADDSTR,
OADDR, OADDR,
OANDAND, OANDAND,
OAPPENDSTR,
OARRAY, OARRAY,
OARRAYBYTESTR, OARRAYRUNESTR,
OAS, OAS2, OASOP, OAS, OAS2, OASOP,
OBAD, OBAD,
OCALL, OCALLFUNC, OCALLMETH, OCALLINTER, OCALL, OCALLFUNC, OCALLMETH, OCALLINTER,
OCAP, OCAP,
OCLOSE, OCLOSE,
OCLOSED, OCLOSED,
OCOMPOS, OCOMPSLICE, OCOMPMAP, OCMPIFACE, OCMPSTR,
OCONV, OCONVNOP, OCONVRUNE, OCONVSTRB, OCONVSTRI, OCONVA2S, OCOMPLIT, OMAPLIT, OSTRUCTLIT, OARRAYLIT,
OCOMPSLICE, OCOMPMAP,
OCONV, OCONVNOP, OCONVA2S, OCONVIFACE, OCONVSLICE,
ODCL, ODCLFUNC, ODCLFIELD, ODCLARG, ODCL, ODCLFUNC, ODCLFIELD, ODCLARG,
ODOT, ODOTPTR, ODOTMETH, ODOTINTER, ODOT, ODOTPTR, ODOTMETH, ODOTINTER,
ODOTTYPE, ODOTTYPE,
OEQ, ONE, OLT, OLE, OGE, OGT, OEQ, ONE, OLT, OLE, OGE, OGT,
OFUNC, OFUNC,
OIND, OIND,
OINDEX, OINDEXSTR, OINDEXMAP, OINDEXARR, OINDEX, OINDEXSTR, OINDEXMAP,
OKEY, OPARAM, OKEY, OPARAM,
OLEN, OLEN,
OMAKE, OMAKE, OMAKECHAN, OMAKEMAP, OMAKESLICE,
OMUL, ODIV, OMOD, OLSH, ORSH, OAND, OANDNOT, OMUL, ODIV, OMOD, OLSH, ORSH, OAND, OANDNOT,
ONEW, ONEW,
ONOT, OCOM, OPLUS, OMINUS, ONOT, OCOM, OPLUS, OMINUS,
OOROR, OOROR,
OPANIC, OPANICN, OPRINT, OPRINTN, OPANIC, OPANICN, OPRINT, OPRINTN,
OSEND, OSEND, OSENDNB,
OSLICE, OSLICESTR, OSLICEARR, OSLICE, OSLICEARR, OSLICESTR,
ORECV, ORECV,
ORUNESTR,
// stmts // stmts
OBLOCK, OBLOCK,
@ -470,10 +475,9 @@ enum
enum enum
{ {
Etop = 1<<1, // evaluated at statement level Etop = 1<<1, // evaluated at statement level
Elv = 1<<2, // evaluated in lvalue context Erv = 1<<2, // evaluated in value context
Erv = 1<<3, // evaluated in rvalue context Etype = 1<<3,
Etype = 1<<4, Ecall = 1<<4,
Ecall = 1<<5,
}; };
#define BITS 5 #define BITS 5
@ -658,6 +662,8 @@ EXTERN ushort blockgen; // max block number
EXTERN ushort block; // current block number EXTERN ushort block; // current block number
EXTERN int hasdefer; // flag that curfn has defer statetment EXTERN int hasdefer; // flag that curfn has defer statetment
EXTERN Node* curfn;
EXTERN int maxround; EXTERN int maxround;
EXTERN int widthptr; EXTERN int widthptr;
@ -986,14 +992,12 @@ NodeList* ascompatet(int, NodeList*, Type**, int, NodeList**);
NodeList* ascompatte(int, Type**, NodeList*, int, NodeList**); NodeList* ascompatte(int, Type**, NodeList*, int, NodeList**);
int ascompat(Type*, Type*); int ascompat(Type*, Type*);
Node* newcompat(Node*); Node* newcompat(Node*);
Node* makecompat(Node*);
Node* stringop(Node*, NodeList**); Node* stringop(Node*, NodeList**);
Type* fixmap(Type*); Type* fixmap(Type*);
Node* mapop(Node*, NodeList**); Node* mapop(Node*, NodeList**);
Type* fixchan(Type*); Type* fixchan(Type*);
Node* chanop(Node*, NodeList**); Node* chanop(Node*, NodeList**);
Node* arrayop(Node*); Node* ifacecvt(Type*, Node*, int, NodeList**);
Node* ifacecvt(Type*, Node*, int);
Node* ifaceop(Node*); Node* ifaceop(Node*);
int ifaceas(Type*, Type*, int); int ifaceas(Type*, Type*, int);
int ifaceas1(Type*, Type*, int); int ifaceas1(Type*, Type*, int);
@ -1011,11 +1015,11 @@ Node* arraylit(Node*, Node*, NodeList**);
Node* maplit(Node*, Node*, NodeList**); Node* maplit(Node*, Node*, NodeList**);
Node* selectas(Node*, Node*, NodeList**); Node* selectas(Node*, Node*, NodeList**);
Node* old2new(Node*, Type*, NodeList**); Node* old2new(Node*, Type*, NodeList**);
void addrescapes(Node*);
void heapmoves(void); void heapmoves(void);
void walkdeflist(NodeList*); void walkdeflist(NodeList*);
void walkdef(Node*); void walkdef(Node*);
void typechecklist(NodeList*, int); void typechecklist(NodeList*, int);
Node* typecheckconv(Node*, Node*, Type*, int);
Node* typecheck(Node**, int); Node* typecheck(Node**, int);
/* /*

View file

@ -123,7 +123,8 @@ file:
{ {
if(debug['f']) if(debug['f'])
frame(1); frame(1);
fninit($4); if(nerrors == 0)
fninit($4);
if(nsyntaxerrors == 0) if(nsyntaxerrors == 0)
testdclstack(); testdclstack();
} }
@ -882,7 +883,7 @@ pexpr:
| convtype lbrace braced_keyval_list '}' | convtype lbrace braced_keyval_list '}'
{ {
// composite expression // composite expression
$$ = nod(OCOMPOS, N, $1); $$ = nod(OCOMPLIT, N, $1);
$$->list = $3; $$->list = $3;
// If the opening brace was an LBODY, // If the opening brace was an LBODY,
@ -894,7 +895,7 @@ pexpr:
| pexpr '{' braced_keyval_list '}' | pexpr '{' braced_keyval_list '}'
{ {
// composite expression // composite expression
$$ = nod(OCOMPOS, N, $1); $$ = nod(OCOMPLIT, N, $1);
$$->list = $3; $$->list = $3;
} }
| fnliteral | fnliteral

View file

@ -208,11 +208,12 @@ exprfmt(Fmt *f, Node *n, int prec)
exprfmt(f, n->left, 0); exprfmt(f, n->left, 0);
break; break;
case OCOMPOS: case OCOMPLIT:
fmtprint(f, "<compos>"); fmtprint(f, "<compos>");
break; break;
case ODOT: case ODOT:
case ODOTPTR:
case ODOTINTER: case ODOTINTER:
case ODOTMETH: case ODOTMETH:
exprfmt(f, n->left, 7); exprfmt(f, n->left, 7);

View file

@ -2,6 +2,10 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
/*
* static initialization
*/
#include "go.h" #include "go.h"
static struct static struct

View file

@ -1209,6 +1209,14 @@ Nconv(Fmt *fp)
goto out; goto out;
} }
if(fp->flags & FmtSign) {
if(n->type == T || n->type->etype == TNIL)
fmtprint(fp, "nil");
else
fmtprint(fp, "%#N (type %T)", n, n->type);
goto out;
}
if(fp->flags & FmtSharp) { if(fp->flags & FmtSharp) {
exprfmt(fp, n, 0); exprfmt(fp, n, 0);
goto out; goto out;
@ -1593,22 +1601,7 @@ eqtype(Type *t1, Type *t2)
int int
cvttype(Type *dst, Type *src) cvttype(Type *dst, Type *src)
{ {
Sym *ds, *ss; return eqtype1(dst, src, 0, 0);
int ret;
if(eqtype1(dst, src, 0, 0))
return 1;
// Can convert if assignment compatible when
// top-level names are ignored.
ds = dst->sym;
dst->sym = nil;
ss = src->sym;
src->sym = nil;
ret = ascompat(dst, src);
dst->sym = ds;
src->sym = ss;
return ret == 1;
} }
int int
@ -1746,6 +1739,7 @@ noconv(Type *t1, Type *t2)
void void
argtype(Node *on, Type *t) argtype(Node *on, Type *t)
{ {
dowidth(t);
if(!subtype(&on->type, t, 0)) if(!subtype(&on->type, t, 0))
fatal("argtype: failed %N %T\n", on, t); fatal("argtype: failed %N %T\n", on, t);
} }
@ -2274,7 +2268,7 @@ saferef(Node *n, NodeList **init)
r = nod(OXXX, N, N); r = nod(OXXX, N, N);
*r = *n; *r = *n;
r->left = l; r->left = l;
typecheck(&r, Elv); typecheck(&r, Erv);
walkexpr(&r, init); walkexpr(&r, init);
return r; return r;
@ -2288,7 +2282,7 @@ saferef(Node *n, NodeList **init)
walkexpr(&a, init); walkexpr(&a, init);
*init = list(*init, a); *init = list(*init, a);
r = nod(OIND, l, N); r = nod(OIND, l, N);
typecheck(&r, Elv); typecheck(&r, Erv);
walkexpr(&r, init); walkexpr(&r, init);
return r; return r;
} }

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -15,10 +15,10 @@ var (
func main() { func main() {
cr = c; // ok cr = c; // ok
cs = c; // ok cs = c; // ok
c = cr; // ERROR "illegal types|incompatible" c = cr; // ERROR "illegal types|incompatible|cannot"
c = cs; // ERROR "illegal types|incompatible" c = cs; // ERROR "illegal types|incompatible|cannot"
cr = cs; // ERROR "illegal types|incompatible" cr = cs; // ERROR "illegal types|incompatible|cannot"
cs = cr; // ERROR "illegal types|incompatible" cs = cr; // ERROR "illegal types|incompatible|cannot"
c <- 0; // ok c <- 0; // ok
ok := c <- 0; // ok ok := c <- 0; // ok

View file

@ -65,15 +65,15 @@ var (
func f(int); func f(int);
func main() { func main() {
f(Int8); // ERROR "convert|wrong type" f(Int8); // ERROR "convert|wrong type|cannot"
f(Minus1); // ERROR "convert|wrong type" f(Minus1); // ERROR "convert|wrong type|cannot"
f(Uint8); // ERROR "convert|wrong type" f(Uint8); // ERROR "convert|wrong type|cannot"
f(Const); // OK f(Const); // OK
f(Float32); // ERROR "convert|wrong type" f(Float32); // ERROR "convert|wrong type|cannot"
f(Float); // ERROR "convert|wrong type" f(Float); // ERROR "convert|wrong type|cannot"
f(ConstFloat); // ERROR "truncate" f(ConstFloat); // ERROR "truncate"
f(ConstFloat - 0.5); // OK f(ConstFloat - 0.5); // OK
f(Big); // ERROR "convert|wrong type" f(Big); // ERROR "convert|wrong type|cannot"
f(String); // ERROR "convert|wrong type" f(String); // ERROR "convert|wrong type|cannot"
f(Bool); // ERROR "convert|wrong type" f(Bool); // ERROR "convert|wrong type|cannot"
} }

View file

@ -21,5 +21,5 @@ var g = []int(nil)
type H *[4]int type H *[4]int
type J []int type J []int
var h H var h H
var j1 J = h // ERROR "compat|illegal" var j1 J = h // ERROR "compat|illegal|cannot|cannot"
var j2 = J(h) var j2 = J(h)

View file

@ -19,11 +19,11 @@ var x7 = float(1e1000); // ERROR "overflow"
// implicit conversions merit scrutiny // implicit conversions merit scrutiny
var s string; var s string;
var bad1 string = 1; // ERROR "conver|incompatible" var bad1 string = 1; // ERROR "conver|incompatible|invalid|cannot"
var bad2 = s + 1; // ERROR "conver|incompatible" var bad2 = s + 1; // ERROR "conver|incompatible|invalid"
var bad3 = s + 'a'; // ERROR "conver|incompatible" var bad3 = s + 'a'; // ERROR "conver|incompatible|invalid"
var bad4 = "a" + 1; // ERROR "literals|incompatible|convert" var bad4 = "a" + 1; // ERROR "literals|incompatible|convert|invalid"
var bad5 = "a" + 'a'; // ERROR "literals|incompatible|convert" var bad5 = "a" + 'a'; // ERROR "literals|incompatible|convert|invalid"
var bad6 int = 1.5; // ERROR "convert|truncate" var bad6 int = 1.5; // ERROR "convert|truncate"
var bad7 int = 1e100; // ERROR "overflow" var bad7 int = 1e100; // ERROR "overflow"

View file

@ -6,12 +6,12 @@
package main package main
var a = []int { "a" }; // ERROR "conver|incompatible" var a = []int { "a" }; // ERROR "conver|incompatible|cannot"
var b = int { 1 }; // ERROR "compos" var b = int { 1 }; // ERROR "compos"
func f() int func f() int
func main() { func main() {
if f < 1 { } // ERROR "conver|incompatible" if f < 1 { } // ERROR "conver|incompatible|invalid"
} }

View file

@ -9,7 +9,7 @@ package main
func putint(digits *string) { func putint(digits *string) {
var i byte; var i byte;
i = (*digits)[7]; // compiles i = (*digits)[7]; // compiles
i = digits[7]; // ERROR "illegal|is not" i = digits[7]; // ERROR "illegal|is not|invalid"
} }
func main() { func main() {

View file

@ -7,5 +7,5 @@
package main package main
func main() { func main() {
var s string = nil; // ERROR "illegal|invalid" var s string = nil; // ERROR "illegal|invalid|cannot"
} }

View file

@ -38,9 +38,9 @@ func main() {
assert(i != f3div2, "i != f3div2"); // ERROR "truncate" assert(i != f3div2, "i != f3div2"); // ERROR "truncate"
const g float64 = 1.0; const g float64 = 1.0;
i = g; // ERROR "convert|incompatible" i = g; // ERROR "convert|incompatible|cannot"
const h float64 = 3.14; const h float64 = 3.14;
i = h; // ERROR "convert|incompatible" i = h; // ERROR "convert|incompatible|cannot"
i = int(h); // ERROR "truncate" i = int(h); // ERROR "truncate"
} }

View file

@ -10,16 +10,6 @@ type T func()
type I interface { type I interface {
f, g (); f, g ();
h T; // should only allow FunctionType here h T; // ERROR "syntax"
} }
type S struct {
}
func (s *S) f() {}
func (s *S) g() {}
func (s *S) h() {} // here we can't write (s *S) T either
func main() {
var i I = new(S);
}

View file

@ -8,5 +8,5 @@ package main
func main() { func main() {
const a uint64 = 10; const a uint64 = 10;
var b int64 = a; // ERROR "convert" var b int64 = a; // ERROR "convert|cannot"
} }

View file

@ -10,5 +10,5 @@ func main() {
type Slice []byte; type Slice []byte;
a := [...]byte{ 0 }; a := [...]byte{ 0 };
b := Slice(&a); // This should be OK. b := Slice(&a); // This should be OK.
c := Slice(a); // ERROR "invalid|illegal" c := Slice(a); // ERROR "invalid|illegal|cannot"
} }

View file

@ -5,9 +5,10 @@
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
package main package main
var v1 = ([10]int)(nil) // ERROR "illegal|nil|invalid" var v1 = ([10]int)(nil); // ERROR "illegal|nil|invalid"
var v2 [10]int = nil // ERROR "illegal|nil|incompatible" var v2 [10]int = nil; // ERROR "illegal|nil|incompatible"
var v3 [10]int var v3 [10]int;
var v4 = nil; // ERROR "nil"
func main() { func main() {
v3 = nil; // ERROR "illegal|nil|incompatible" v3 = nil; // ERROR "illegal|nil|incompatible"
} }

View file

@ -9,6 +9,6 @@ package main
var notmain func() var notmain func()
func main() { func main() {
var x = &main; // ERROR "address of function|invalid" var x = &main; // ERROR "address of|invalid"
main = notmain; // ERROR "assign to function|invalid" main = notmain; // ERROR "assign to|invalid"
} }

View file

@ -132,13 +132,6 @@ throw: interface conversion
panic PC=xxx panic PC=xxx
=========== fixedbugs/bug121.go
fixedbugs/bug121.go:9: syntax error near T
fixedbugs/bug121.go:20: incomplete type I
fixedbugs/bug121.go:20: illegal types for operand: AS
I
*S
=========== fixedbugs/bug148.go =========== fixedbugs/bug148.go
2 3 2 3
interface is main.T, not main.T·bug148·1 interface is main.T, not main.T·bug148·1

View file

@ -32,6 +32,6 @@ func AddInst(Inst) *Inst {
func main() { func main() {
re := new(Regexp); re := new(Regexp);
print("call addinst\n"); print("call addinst\n");
var x Inst = AddInst(new(Start)); // ERROR "illegal|incompatible" var x Inst = AddInst(new(Start)); // ERROR "illegal|incompatible|is not"
print("return from addinst\n"); print("return from addinst\n");
} }