diff options
| author | Russ Cox <rsc@golang.org> | 2009-12-03 00:51:03 -0800 | 
|---|---|---|
| committer | Russ Cox <rsc@golang.org> | 2009-12-03 00:51:03 -0800 | 
| commit | 785c8ab4276110f0aa8d53d704dff04c4d1996f1 (patch) | |
| tree | e57459052baa096e97cbc54bdb8b66954ad9e6e0 /src | |
| parent | 38ac3d99ff8f5ab90c2599f1104d6f0679d2550a (diff) | |
| download | golang-785c8ab4276110f0aa8d53d704dff04c4d1996f1.tar.gz | |
gc: better diagnosis of initialization loops
Fixes bug 292.
R=ken2
http://codereview.appspot.com/164093
Diffstat (limited to 'src')
| -rw-r--r-- | src/cmd/gc/closure.c | 3 | ||||
| -rw-r--r-- | src/cmd/gc/dcl.c | 1 | ||||
| -rw-r--r-- | src/cmd/gc/go.h | 1 | ||||
| -rw-r--r-- | src/cmd/gc/sinit.c | 69 | ||||
| -rw-r--r-- | src/cmd/gc/subr.c | 1 | 
5 files changed, 67 insertions, 8 deletions
| diff --git a/src/cmd/gc/closure.c b/src/cmd/gc/closure.c index 2f102993c..33c576c87 100644 --- a/src/cmd/gc/closure.c +++ b/src/cmd/gc/closure.c @@ -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; diff --git a/src/cmd/gc/dcl.c b/src/cmd/gc/dcl.c index ec386f3a0..338a6213a 100644 --- a/src/cmd/gc/dcl.c +++ b/src/cmd/gc/dcl.c @@ -167,6 +167,7 @@ declare(Node *n, int ctxt)  	if(isblank(n))  		return; +	n->lineno = parserline();  	s = n->sym;  	gen = 0;  	if(ctxt == PEXTERN) { diff --git a/src/cmd/gc/go.h b/src/cmd/gc/go.h index 595d7c8b8..87362156d 100644 --- a/src/cmd/gc/go.h +++ b/src/cmd/gc/go.h @@ -351,7 +351,6 @@ enum  	ODOT, ODOTPTR, ODOTMETH, ODOTINTER, OXDOT,  	ODOTTYPE,  	OEQ, ONE, OLT, OLE, OGE, OGT, -	OFUNC,  	OIND,  	OINDEX, OINDEXSTR, OINDEXMAP,  	OKEY, OPARAM, diff --git a/src/cmd/gc/sinit.c b/src/cmd/gc/sinit.c index dc95360ee..ade8426c0 100644 --- a/src/cmd/gc/sinit.c +++ b/src/cmd/gc/sinit.c @@ -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)  { diff --git a/src/cmd/gc/subr.c b/src/cmd/gc/subr.c index 22e59c5c8..6b73570e5 100644 --- a/src/cmd/gc/subr.c +++ b/src/cmd/gc/subr.c @@ -753,7 +753,6 @@ goopnames[] =  	[OEQ]		= "==",  	[OFALL]		= "fallthrough",  	[OFOR]		= "for", -	[OFUNC]		= "func",  	[OGE]		= ">=",  	[OGOTO]		= "goto",  	[OGT]		= ">", | 
