mirror of
https://github.com/golang/go
synced 2024-11-25 02:07:58 -07:00
gc: better diagnosis of initialization loops
Fixes bug 292. R=ken2 https://golang.org/cl/164093
This commit is contained in:
parent
e733766dda
commit
41861a8812
@ -152,9 +152,10 @@ walkclosure(Node *func, NodeList **init)
|
||||
|
||||
// create the function
|
||||
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->ntype = xtype;
|
||||
xfunc->nname->defn = xfunc;
|
||||
declare(xfunc->nname, PFUNC);
|
||||
xfunc->nname->funcdepth = func->funcdepth;
|
||||
xfunc->funcdepth = func->funcdepth;
|
||||
|
@ -167,6 +167,7 @@ declare(Node *n, int ctxt)
|
||||
if(isblank(n))
|
||||
return;
|
||||
|
||||
n->lineno = parserline();
|
||||
s = n->sym;
|
||||
gen = 0;
|
||||
if(ctxt == PEXTERN) {
|
||||
|
@ -351,7 +351,6 @@ enum
|
||||
ODOT, ODOTPTR, ODOTMETH, ODOTINTER, OXDOT,
|
||||
ODOTTYPE,
|
||||
OEQ, ONE, OLT, OLE, OGE, OGT,
|
||||
OFUNC,
|
||||
OIND,
|
||||
OINDEX, OINDEXSTR, OINDEXMAP,
|
||||
OKEY, OPARAM,
|
||||
|
@ -8,6 +8,10 @@
|
||||
|
||||
#include "go.h"
|
||||
|
||||
static NodeList *initlist;
|
||||
static void init2(Node*, NodeList**);
|
||||
static void init2list(NodeList*, NodeList**);
|
||||
|
||||
static void
|
||||
init1(Node *n, NodeList **out)
|
||||
{
|
||||
@ -34,20 +38,45 @@ init1(Node *n, NodeList **out)
|
||||
|
||||
if(n->initorder == 1)
|
||||
return;
|
||||
if(n->initorder == 2)
|
||||
fatal("init loop");
|
||||
if(n->initorder == 2) {
|
||||
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.
|
||||
// n->defn is an assignment to n
|
||||
n->initorder = 2;
|
||||
if(n->defn != N) {
|
||||
switch(n->defn->op) {
|
||||
default:
|
||||
goto bad;
|
||||
|
||||
case ODCLFUNC:
|
||||
for(l=n->defn->nbody; l; l=l->next)
|
||||
init1(l->n, out);
|
||||
init2list(n->defn->nbody, out);
|
||||
break;
|
||||
|
||||
case OAS:
|
||||
@ -67,6 +96,11 @@ init1(Node *n, NodeList **out)
|
||||
break;
|
||||
}
|
||||
}
|
||||
l = initlist;
|
||||
initlist = l->next;
|
||||
if(l->n != n)
|
||||
fatal("bad initlist");
|
||||
free(l);
|
||||
n->initorder = 1;
|
||||
return;
|
||||
|
||||
@ -75,6 +109,31 @@ bad:
|
||||
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
|
||||
initreorder(NodeList *l, NodeList **out)
|
||||
{
|
||||
|
@ -753,7 +753,6 @@ goopnames[] =
|
||||
[OEQ] = "==",
|
||||
[OFALL] = "fallthrough",
|
||||
[OFOR] = "for",
|
||||
[OFUNC] = "func",
|
||||
[OGE] = ">=",
|
||||
[OGOTO] = "goto",
|
||||
[OGT] = ">",
|
||||
|
21
test/fixedbugs/bug223.go
Normal file
21
test/fixedbugs/bug223.go
Normal 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}
|
Loading…
Reference in New Issue
Block a user