From dbe004efe48fbdb4c911eaf1771664e0457c3288 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Tue, 4 Aug 2009 16:53:06 -0700 Subject: [PATCH] delayed evaluation of var blocks R=ken OCL=32750 CL=32753 --- src/cmd/gc/dcl.c | 95 +++++++++++++++++++++++++++------------------ src/cmd/gc/export.c | 2 + src/cmd/gc/gen.c | 9 +++-- src/cmd/gc/go.h | 1 + src/cmd/gc/go.y | 4 +- src/cmd/gc/walk.c | 34 ++++++++++++++-- test/declbad.go | 4 +- 7 files changed, 99 insertions(+), 50 deletions(-) diff --git a/src/cmd/gc/dcl.c b/src/cmd/gc/dcl.c index d1802c83d3e..3b8e67d15a9 100644 --- a/src/cmd/gc/dcl.c +++ b/src/cmd/gc/dcl.c @@ -1200,6 +1200,7 @@ oldname(Sym *s) // inner func is referring to var // in outer func. if(n->closure == N || n->closure->funcdepth != funcdepth) { + typecheck(&n, Erv); // create new closure var. c = nod(ONAME, N, N); c->sym = s; @@ -1640,21 +1641,15 @@ embedded(Sym *s) * new_name_list (type | [type] = expr_list) */ NodeList* -variter(NodeList *vl, Node *nt, NodeList *el) +variter(NodeList *vl, Node *t, NodeList *el) { - int doexpr, lno; - Node *v, *e, *a; - Type *tv; - NodeList *r; - Type *t; + int doexpr, gen; + Node *v, *e; + NodeList *init; + Sym *s; + Dcl *r, *d; - t = T; - if(nt) { - typecheck(&nt, Etype); - t = nt->type; - } - - r = nil; + init = nil; doexpr = el != nil; for(; vl; vl=vl->next) { if(doexpr) { @@ -1663,41 +1658,53 @@ variter(NodeList *vl, Node *nt, NodeList *el) break; } e = el->n; + el = el->next; } else e = N; v = vl->n; - tv = t; - if(e) { - lno = lineno; - lineno = v->lineno; - typecheck(&e, Erv); - defaultlit(&e, t); - 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; + s = v->sym; + if(dclcontext == PEXTERN || dclcontext == PFUNC) { + r = externdcl; + gen = 0; + } else { + r = autodcl; + gen = ++vargen; + pushdcl(s); } - a = N; - if((e != N && tv != T) || funcdepth > 0) - a = nod(OAS, v, e); - dodclvar(v, tv, &r); - if(a != N) - r = list(r, a); - if(el) { - el->n = e; - el = el->next; + redeclare("variable", s); + s->def = v; + // TODO: vargen + s->offset = 0; + s->block = block; + + v->op = ONAME; + v->class = dclcontext; + v->ntype = t; + v->funcdepth = funcdepth; + v->vargen = gen; + if(e != N || funcdepth > 0) { + if(funcdepth > 0) + init = list(init, nod(ODCL, v, N)); + e = nod(OAS, v, e); + init = list(init, e); + if(e->right != N) + v->defn = e; } + + d = dcl(); + d->dsym = s; + d->dnode = v; + d->op = ONAME; + r->back->forw = d; + r->back = d; + + autoexport(s); } if(el != nil) yyerror("extra expr in var dcl"); - return r; + return init; } /* @@ -1830,3 +1837,15 @@ yes: n->type = types[TINT]; return n; } + +void +dclchecks(void) +{ + Dcl *d; + + for(d=externdcl; d!=D; d=d->forw) { + if(d->op != ONAME) + continue; + typecheck(&d->dnode, Erv); + } +} diff --git a/src/cmd/gc/export.c b/src/cmd/gc/export.c index e7ff59bb5b8..74df553632a 100644 --- a/src/cmd/gc/export.c +++ b/src/cmd/gc/export.c @@ -101,6 +101,7 @@ dumpexportconst(Sym *s) Type *t; n = s->def; + typecheck(&n, Erv); if(n == N || n->op != OLITERAL) fatal("dumpexportconst: oconst nil: %S", s); @@ -142,6 +143,7 @@ dumpexportvar(Sym *s) Type *t; n = s->def; + typecheck(&n, Erv); if(n == N || n->type == T) { yyerror("variable exported but not defined: %S", s); return; diff --git a/src/cmd/gc/gen.c b/src/cmd/gc/gen.c index f87b70e95cb..5fab59cdfab 100644 --- a/src/cmd/gc/gen.c +++ b/src/cmd/gc/gen.c @@ -39,6 +39,7 @@ allocparams(void) if(n->class != PAUTO) continue; + typecheck(&n, Erv); dowidth(n->type); w = n->type->width; if(n->class & PHEAP) @@ -232,7 +233,7 @@ gen(Node *n) case OFOR: sbreak = breakpc; - p1 = gjmp(P); // goto test + p1 = gjmp(P); // goto test breakpc = gjmp(P); // break: goto done scontin = continpc; continpc = pc; @@ -263,7 +264,7 @@ gen(Node *n) if(n->ntest != N) if(n->ntest->ninit != nil) genlist(n->ntest->ninit); - bgen(n->ntest, 0, p2); // if(!test) goto p2 + bgen(n->ntest, 0, p2); // if(!test) goto p2 genlist(n->nbody); // then p3 = gjmp(P); // goto done patch(p2, pc); // else: @@ -273,7 +274,7 @@ gen(Node *n) case OSWITCH: sbreak = breakpc; - p1 = gjmp(P); // goto test + p1 = gjmp(P); // goto test breakpc = gjmp(P); // break: goto done // define break label @@ -288,7 +289,7 @@ gen(Node *n) case OSELECT: sbreak = breakpc; - p1 = gjmp(P); // goto test + p1 = gjmp(P); // goto test breakpc = gjmp(P); // break: goto done // define break label diff --git a/src/cmd/gc/go.h b/src/cmd/gc/go.h index 71d34682b61..db757fa4e77 100644 --- a/src/cmd/gc/go.h +++ b/src/cmd/gc/go.h @@ -933,6 +933,7 @@ NodeList* constiter(NodeList*, Node*, NodeList*); Node* funclit0(Node*); Node* funclit1(Node*, NodeList*); Node* unsafenmagic(Node*, NodeList*); +void dclchecks(void); /* * sinit.c diff --git a/src/cmd/gc/go.y b/src/cmd/gc/go.y index 4e280c17780..f048c29d146 100644 --- a/src/cmd/gc/go.y +++ b/src/cmd/gc/go.y @@ -123,10 +123,12 @@ file: { if(debug['f']) frame(1); + typechecklist($4, Etop); if(nerrors == 0) fninit($4); if(nsyntaxerrors == 0) testdclstack(); + dclchecks(); } package: @@ -290,13 +292,11 @@ common_dcl: $$ = $2; if(yylast == LSEMIBRACE) yyoptsemi(0); - // walkdeflist($2); } | LVAR '(' vardcl_list osemi ')' { $$ = $3; yyoptsemi(0); - // walkdeflist($3); } | LVAR '(' ')' { diff --git a/src/cmd/gc/walk.c b/src/cmd/gc/walk.c index a77163323c7..43cdcbb475a 100644 --- a/src/cmd/gc/walk.c +++ b/src/cmd/gc/walk.c @@ -176,6 +176,35 @@ walkdef(Node *n) n->val = e->val; n->type = e->type; break; + + case ONAME: + if(n->ntype != N) { + typecheck(&n->ntype, Etype); + n->type = n->ntype->type; + if(n->type == T) { + n->diag = 1; + goto ret; + } + n->ntype = N; + } + if(n->type != T) + break; + if(n->defn == N) + fatal("var without type, init: %S", n->sym); + switch(n->defn->op) { + default: + fatal("walkdef name defn"); + case OAS: + typecheck(&n->defn->right, Erv); + defaultlit(&n->defn->right, T); + if((t = n->defn->right->type) == T) { + n->diag = 1; + goto ret; + } + n->type = t; + break; + } + break; } ret: @@ -1754,11 +1783,8 @@ checkmixed(NodeList *nl, NodeList **init) if(!colasname(l)) goto allnew; - if(l->sym->block == block) { - if(!eqtype(l->type, t)) - goto allnew; + if(l->sym->block == block) nred++; - } ntot++; } diff --git a/test/declbad.go b/test/declbad.go index 7f6e56d7e44..78f8c8d5480 100644 --- a/test/declbad.go +++ b/test/declbad.go @@ -21,12 +21,12 @@ func main() { { // change of type for f i, f, s := f3(); // GCCGO_ERROR "previous" - f, g, t := f3(); // ERROR "redeclared|redefinition" + f, g, t := f3(); // ERROR "redeclared|redefinition|cannot assign" } { // change of type for i i, f, s := f3(); // GCCGO_ERROR "previous" - j, i, t := f3(); // ERROR "redeclared|redefinition" + j, i, t := f3(); // ERROR "redeclared|redefinition|cannot assign" } { // no new variables