From: Russ Cox Date: Thu, 15 Oct 2009 23:03:01 +0000 (-0700) Subject: do not migrate x to the heap because of *&x. X-Git-Tag: weekly.2009-11-06~293 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=a75e347a21e104a070b6516bc5adae402d424e45;p=gostls13.git do not migrate x to the heap because of *&x. R=ken OCL=35799 CL=35799 --- diff --git a/src/cmd/gc/go.h b/src/cmd/gc/go.h index 058f839cdd..2f23d63fd9 100644 --- a/src/cmd/gc/go.h +++ b/src/cmd/gc/go.h @@ -477,6 +477,8 @@ enum Efnstruct = 1<<5, // multivalue function returns are ok Eiota = 1<<6, // iota is ok Easgn = 1<<7, // assigning to expression + Eindir = 1<<8, // indirecting through expression + Eaddr = 1<<9, // taking address of expression }; #define BITS 5 diff --git a/src/cmd/gc/typecheck.c b/src/cmd/gc/typecheck.c index 826d740cc8..6c90004cfb 100644 --- a/src/cmd/gc/typecheck.c +++ b/src/cmd/gc/typecheck.c @@ -51,7 +51,7 @@ typecheck(Node **np, int top) int et, op; Node *n, *l, *r; NodeList *args; - int lno, ok; + int lno, ok, ntop; Type *t; // cannot type check until all the source has been parsed @@ -250,7 +250,10 @@ reswitch: * type or expr */ case OIND: - l = typecheck(&n->left, Erv | Etype); + ntop = Erv | Etype; + if(!(top & Eaddr)) + ntop |= Eindir; + l = typecheck(&n->left, ntop); if((t = l->type) == T) goto error; if(l->op == OTYPE) { @@ -409,7 +412,7 @@ reswitch: */ case OADDR: ok |= Erv; - typecheck(&n->left, Erv); + typecheck(&n->left, Erv | Eaddr); if(n->left->type == T) goto error; switch(n->left->op) { @@ -424,7 +427,8 @@ reswitch: l = n->left; if((t = l->type) == T) goto error; - addrescapes(n->left); + if(!(top & Eindir)) + addrescapes(n->left); n->type = ptrto(t); goto ret; @@ -642,16 +646,8 @@ reswitch: typecheck(&n->left, Erv | Etype | Ecall); defaultlit(&n->left, T); l = n->left; - if(count(n->list) == 1) - typecheck(&n->list->n, Erv | Efnstruct); - else - typechecklist(n->list, Erv); - if((t = l->type) == T) - goto error; - checkwidth(t); - - switch(l->op) { - case OTYPE: + if(l->op == OTYPE) { + // pick off before type-checking arguments ok |= Erv; // turn CALL(type, arg) into CONV(arg) w/ type n->left = N; @@ -660,7 +656,17 @@ reswitch: n->op = OCONV; n->type = l->type; goto doconv; + } + + if(count(n->list) == 1) + typecheck(&n->list->n, Erv | Efnstruct); + else + typechecklist(n->list, Erv); + if((t = l->type) == T) + goto error; + checkwidth(t); + switch(l->op) { case ODOTINTER: n->op = OCALLINTER; break; @@ -758,7 +764,7 @@ reswitch: case OCONV: doconv: ok |= Erv; - typecheck(&n->left, Erv); + typecheck(&n->left, Erv | (top & Eindir)); defaultlit(&n->left, n->type); if((t = n->left->type) == T || n->type == T) goto error;