1
0
mirror of https://github.com/golang/go synced 2024-11-05 19:46:11 -07:00

detect recursive initialization

R=r
OCL=29544
CL=29544
This commit is contained in:
Ken Thompson 2009-05-28 16:00:55 -07:00
parent 3aa006b8cd
commit e2613711aa
5 changed files with 57 additions and 25 deletions

View File

@ -3,6 +3,7 @@ char *sysimport =
"func sys.mal (? int32) (? *any)\n" "func sys.mal (? int32) (? *any)\n"
"func sys.throwindex ()\n" "func sys.throwindex ()\n"
"func sys.throwreturn ()\n" "func sys.throwreturn ()\n"
"func sys.throwinit ()\n"
"func sys.panicl (? int32)\n" "func sys.panicl (? int32)\n"
"func sys.printbool (? bool)\n" "func sys.printbool (? bool)\n"
"func sys.printfloat (? float64)\n" "func sys.printfloat (? float64)\n"

View File

@ -1284,18 +1284,24 @@ mixed:
yyerror("cannot mix anonymous and named function arguments"); yyerror("cannot mix anonymous and named function arguments");
} }
// hand-craft the following initialization code /*
// var initdone·<file> bool (1) * hand-craft the following initialization code
// func Init·<file>() (2) * var initdone·<file> uint8 (1)
// if initdone·<file> { return } (3) * func Init·<file>() (2)
// initdone.<file> = true; (4) * if initdone·<file> { (3)
// // over all matching imported symbols * if initdone·<file> == 2 (4)
// <pkg>.init·<file>() (5) * return
// { <init stmts> } (6) * throw(); (5)
// init·<file>() // if any (7) * }
// return (8) * initdone.<file>++; (6)
// } * // over all matching imported symbols
* <pkg>.init·<file>() (7)
* { <init stmts> } (8)
* init·<file>() // if any (9)
* initdone.<file>++; (10)
* return (11)
* }
*/
int int
anyinit(Node *n) anyinit(Node *n)
{ {
@ -1333,8 +1339,8 @@ anyinit(Node *n)
void void
fninit(Node *n) fninit(Node *n)
{ {
Node *done; Node *gatevar;
Node *a, *fn, *r; Node *a, *b, *fn, *r;
uint32 h; uint32 h;
Sym *s, *initsym; Sym *s, *initsym;
@ -1350,8 +1356,8 @@ fninit(Node *n)
// (1) // (1)
snprint(namebuf, sizeof(namebuf), "initdone·%s", filename); snprint(namebuf, sizeof(namebuf), "initdone·%s", filename);
done = newname(lookup(namebuf)); gatevar = newname(lookup(namebuf));
addvar(done, types[TBOOL], PEXTERN); addvar(gatevar, types[TUINT8], PEXTERN);
// (2) // (2)
@ -1373,15 +1379,26 @@ fninit(Node *n)
// (3) // (3)
a = nod(OIF, N, N); a = nod(OIF, N, N);
a->ntest = done; a->ntest = nod(ONE, gatevar, nodintconst(0));
a->nbody = nod(ORETURN, N, N);
r = list(r, a); r = list(r, a);
// (4) // (4)
a = nod(OAS, done, nodbool(1)); b = nod(OIF, N, N);
r = list(r, a); b->ntest = nod(OEQ, gatevar, nodintconst(2));
b->nbody = nod(ORETURN, N, N);
a->nbody = b;
// (5) // (5)
b = syslook("throwinit", 0);
b = nod(OCALL, b, N);
a->nbody = list(a->nbody, b);
// (6)
a = nod(OASOP, gatevar, nodintconst(1));
a->etype = OADD;
r = list(r, a);
// (7)
for(h=0; h<NHASH; h++) for(h=0; h<NHASH; h++)
for(s = hash[h]; s != S; s = s->link) { for(s = hash[h]; s != S; s = s->link) {
if(s->name[0] != 'I' || strncmp(s->name, "Init·", 6) != 0) if(s->name[0] != 'I' || strncmp(s->name, "Init·", 6) != 0)
@ -1396,10 +1413,10 @@ fninit(Node *n)
r = list(r, a); r = list(r, a);
} }
// (6) // (8)
r = list(r, initfix(n)); r = list(r, initfix(n));
// (7) // (9)
// could check that it is fn of no args/returns // could check that it is fn of no args/returns
snprint(namebuf, sizeof(namebuf), "init·%s", filename); snprint(namebuf, sizeof(namebuf), "init·%s", filename);
s = lookup(namebuf); s = lookup(namebuf);
@ -1408,7 +1425,12 @@ fninit(Node *n)
r = list(r, a); r = list(r, a);
} }
// (8) // (10)
a = nod(OASOP, gatevar, nodintconst(1));
a->etype = OADD;
r = list(r, a);
// (11)
a = nod(ORETURN, N, N); a = nod(ORETURN, N, N);
r = list(r, a); r = list(r, a);

View File

@ -61,6 +61,8 @@ typeclass(Type *t)
void void
initlin(Node* n) initlin(Node* n)
{ {
loop:
if(n == N) if(n == N)
return; return;
initlin(n->ninit); initlin(n->ninit);
@ -84,8 +86,8 @@ initlin(Node* n)
case OLIST: case OLIST:
initlin(n->left); initlin(n->left);
initlin(n->right); n = n->right;
break; goto loop;
} }
} }

View File

@ -10,6 +10,7 @@ package PACKAGE
func mal(int32) *any; func mal(int32) *any;
func throwindex(); func throwindex();
func throwreturn(); func throwreturn();
func throwinit();
func panicl(int32); func panicl(int32);
func printbool(bool); func printbool(bool);

View File

@ -51,6 +51,12 @@ sys·throwreturn(void)
throw("no return at end of a typed function"); throw("no return at end of a typed function");
} }
void
sys·throwinit(void)
{
throw("recursive call during initialization");
}
void void
throw(int8 *s) throw(int8 *s)
{ {