1
0
mirror of https://github.com/golang/go synced 2024-11-13 14:10:22 -07:00

gc: better diagnosis of initialization loops

Fixes bug 292.

R=ken2
https://golang.org/cl/164093
This commit is contained in:
Russ Cox 2009-12-03 00:51:03 -08:00
parent e733766dda
commit 41861a8812
6 changed files with 88 additions and 8 deletions

View File

@ -152,9 +152,10 @@ walkclosure(Node *func, NodeList **init)
// create the function // create the function
xfunc = nod(ODCLFUNC, N, N); xfunc = nod(ODCLFUNC, N, N);
snprint(namebuf, sizeof namebuf, "_f%.3ld", ++closgen); snprint(namebuf, sizeof namebuf, "_func_%.3ld", ++closgen);
xfunc->nname = newname(lookup(namebuf)); xfunc->nname = newname(lookup(namebuf));
xfunc->nname->ntype = xtype; xfunc->nname->ntype = xtype;
xfunc->nname->defn = xfunc;
declare(xfunc->nname, PFUNC); declare(xfunc->nname, PFUNC);
xfunc->nname->funcdepth = func->funcdepth; xfunc->nname->funcdepth = func->funcdepth;
xfunc->funcdepth = func->funcdepth; xfunc->funcdepth = func->funcdepth;

View File

@ -167,6 +167,7 @@ declare(Node *n, int ctxt)
if(isblank(n)) if(isblank(n))
return; return;
n->lineno = parserline();
s = n->sym; s = n->sym;
gen = 0; gen = 0;
if(ctxt == PEXTERN) { if(ctxt == PEXTERN) {

View File

@ -351,7 +351,6 @@ enum
ODOT, ODOTPTR, ODOTMETH, ODOTINTER, OXDOT, ODOT, ODOTPTR, ODOTMETH, ODOTINTER, OXDOT,
ODOTTYPE, ODOTTYPE,
OEQ, ONE, OLT, OLE, OGE, OGT, OEQ, ONE, OLT, OLE, OGE, OGT,
OFUNC,
OIND, OIND,
OINDEX, OINDEXSTR, OINDEXMAP, OINDEX, OINDEXSTR, OINDEXMAP,
OKEY, OPARAM, OKEY, OPARAM,

View File

@ -8,6 +8,10 @@
#include "go.h" #include "go.h"
static NodeList *initlist;
static void init2(Node*, NodeList**);
static void init2list(NodeList*, NodeList**);
static void static void
init1(Node *n, NodeList **out) init1(Node *n, NodeList **out)
{ {
@ -34,20 +38,45 @@ init1(Node *n, NodeList **out)
if(n->initorder == 1) if(n->initorder == 1)
return; return;
if(n->initorder == 2) if(n->initorder == 2) {
fatal("init loop"); if(n->class == PFUNC)
return;
// if there have already been errors printed,
// those errors probably confused us and
// there might not be a loop. let the user
// fix those first.
flusherrors();
if(nerrors > 0)
errorexit();
print("initialization loop:\n");
for(l=initlist;; l=l->next) {
if(l->next == nil)
break;
l->next->end = l;
}
for(; l; l=l->end)
print("\t%L %S refers to\n", l->n->lineno, l->n->sym);
print("\t%L %S\n", n->lineno, n->sym);
errorexit();
}
n->initorder = 2;
l = malloc(sizeof *l);
l->next = initlist;
l->n = n;
l->end = nil;
initlist = l;
// make sure that everything n depends on is initialized. // make sure that everything n depends on is initialized.
// n->defn is an assignment to n // n->defn is an assignment to n
n->initorder = 2;
if(n->defn != N) { if(n->defn != N) {
switch(n->defn->op) { switch(n->defn->op) {
default: default:
goto bad; goto bad;
case ODCLFUNC: case ODCLFUNC:
for(l=n->defn->nbody; l; l=l->next) init2list(n->defn->nbody, out);
init1(l->n, out);
break; break;
case OAS: case OAS:
@ -67,6 +96,11 @@ init1(Node *n, NodeList **out)
break; break;
} }
} }
l = initlist;
initlist = l->next;
if(l->n != n)
fatal("bad initlist");
free(l);
n->initorder = 1; n->initorder = 1;
return; return;
@ -75,6 +109,31 @@ bad:
fatal("init1: bad defn"); fatal("init1: bad defn");
} }
// recurse over n, doing init1 everywhere.
static void
init2(Node *n, NodeList **out)
{
if(n == N || n->initorder == 1)
return;
init1(n, out);
init2(n->left, out);
init2(n->right, out);
init2(n->ntest, out);
init2list(n->ninit, out);
init2list(n->list, out);
init2list(n->rlist, out);
init2list(n->nbody, out);
init2list(n->nelse, out);
}
static void
init2list(NodeList *l, NodeList **out)
{
for(; l; l=l->next)
init2(l->n, out);
}
static void static void
initreorder(NodeList *l, NodeList **out) initreorder(NodeList *l, NodeList **out)
{ {

View File

@ -753,7 +753,6 @@ goopnames[] =
[OEQ] = "==", [OEQ] = "==",
[OFALL] = "fallthrough", [OFALL] = "fallthrough",
[OFOR] = "for", [OFOR] = "for",
[OFUNC] = "func",
[OGE] = ">=", [OGE] = ">=",
[OGOTO] = "goto", [OGOTO] = "goto",
[OGT] = ">", [OGT] = ">",

21
test/fixedbugs/bug223.go Normal file
View File

@ -0,0 +1,21 @@
// (! $G $D/$F.go) | grep 'initialization loop' >/dev/null || echo BUG: bug223
// 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.
// check that initialization loop is diagnosed
// and that closure cannot be used to hide it.
// error message is not standard format, so no errchk above.
package main
type F func()
func f() {
if true {
_ = func() { _ = m }
}
}
var m = map[string]F{"f": f}