Commit d6a98170 authored by Russ Cox's avatar Russ Cox

bug157

R=ken
OCL=29651
CL=29653
parent be63b6dc
...@@ -47,11 +47,11 @@ ...@@ -47,11 +47,11 @@
%type <node> common_dcl Acommon_dcl Bcommon_dcl %type <node> common_dcl Acommon_dcl Bcommon_dcl
%type <node> oarg_type_list arg_type_list_r arg_chunk arg_chunk_list_r arg_type_list %type <node> oarg_type_list arg_type_list_r arg_chunk arg_chunk_list_r arg_type_list
%type <node> Aelse_stmt Belse_stmt %type <node> Aelse_stmt Belse_stmt
%type <node> complex_stmt compound_stmt ostmt_list %type <node> complex_stmt compound_stmt switch_body ocaseblock_list ostmt_list
%type <node> stmt_list_r Astmt_list_r Bstmt_list_r %type <node> caseblock_list_r stmt_list_r Astmt_list_r Bstmt_list_r
%type <node> Astmt Bstmt %type <node> Astmt Bstmt
%type <node> for_stmt for_body for_header %type <node> for_stmt for_body for_header
%type <node> if_stmt if_body if_header select_stmt condition %type <node> if_stmt if_header select_stmt switch_stmt condition case caseblock
%type <node> simple_stmt osimple_stmt range_stmt semi_stmt %type <node> simple_stmt osimple_stmt range_stmt semi_stmt
%type <node> expr uexpr pexpr expr_list oexpr oexpr_list expr_list_r %type <node> expr uexpr pexpr expr_list oexpr oexpr_list expr_list_r
%type <node> exprsym3_list_r exprsym3 pseudocall %type <node> exprsym3_list_r exprsym3 pseudocall
...@@ -511,34 +511,23 @@ simple_stmt: ...@@ -511,34 +511,23 @@ simple_stmt:
} }
complex_stmt: complex_stmt:
LFOR for_stmt for_stmt
| switch_stmt
| select_stmt
| if_stmt
{ {
popdcl(); popdcl();
$$ = $2; $$ = $1;
}
| LSWITCH if_stmt
{
popdcl();
$$ = $2;
$$->op = OSWITCH;
}
| LIF if_stmt
{
popdcl();
$$ = $2;
}
| LIF if_stmt LELSE Aelse_stmt
{
popdcl();
$$ = $2;
$$->nelse = $4;
} }
| LSELECT select_stmt | if_stmt LELSE Aelse_stmt
{ {
popdcl(); popdcl();
$$ = $2; $$ = $1;
$$->nelse = $3;
} }
| LCASE expr_list ':'
case:
LCASE expr_list ':'
{ {
// will be converted to OCASE // will be converted to OCASE
// right will point to next case // right will point to next case
...@@ -620,11 +609,11 @@ semi_stmt: ...@@ -620,11 +609,11 @@ semi_stmt:
{ {
$$ = nod(ORETURN, $2, N); $$ = nod(ORETURN, $2, N);
} }
| LIF if_stmt LELSE Belse_stmt | if_stmt LELSE Belse_stmt
{ {
popdcl(); popdcl();
$$ = $2; $$ = $1;
$$->nelse = $4; $$->nelse = $3;
} }
compound_stmt: compound_stmt:
...@@ -639,6 +628,33 @@ compound_stmt: ...@@ -639,6 +628,33 @@ compound_stmt:
popdcl(); popdcl();
} }
switch_body:
'{'
{
markdcl();
}
ocaseblock_list '}'
{
$$ = $3;
if($$ == N)
$$ = nod(OEMPTY, N, N);
popdcl();
}
caseblock:
case ostmt_list
{
$$ = $1;
$$->nbody = $2;
}
caseblock_list_r:
caseblock
| caseblock_list_r caseblock
{
$$ = nod(OLIST, $1, $2);
}
range_stmt: range_stmt:
exprsym3_list_r '=' LRANGE expr exprsym3_list_r '=' LRANGE expr
{ {
...@@ -684,11 +700,14 @@ for_body: ...@@ -684,11 +700,14 @@ for_body:
} }
for_stmt: for_stmt:
LFOR
{ {
markdcl(); markdcl();
} for_body }
for_body
{ {
$$ = $2; $$ = $3;
popdcl();
} }
/* /*
...@@ -722,38 +741,51 @@ if_header: ...@@ -722,38 +741,51 @@ if_header:
$$->ntest = $3; $$->ntest = $3;
} }
if_body: if_stmt:
LIF
{
markdcl();
}
if_header compound_stmt
{
$$ = $3;
$$->nbody = $4;
// no popdcl; maybe there's an LELSE
}
switch_stmt:
LSWITCH
{
markdcl();
}
if_header if_header
{ {
Node *n; Node *n;
n = $1->ntest; n = $3->ntest;
if(n != N && n->op == OTYPESW) if(n != N && n->op == OTYPESW)
n = n->left; n = n->left;
else else
n = N; n = N;
typeswvar = nod(OLIST, typeswvar, n); typeswvar = nod(OLIST, typeswvar, n);
} compound_stmt
{
$$ = $1;
$$->nbody = $3;
typeswvar = typeswvar->left;
} }
switch_body
if_stmt:
{
markdcl();
} if_body
{ {
$$ = $2; $$ = $3;
$$->op = OSWITCH;
$$->nbody = $5;
typeswvar = typeswvar->left;
popdcl();
} }
select_stmt: select_stmt:
LSELECT
{ {
markdcl(); markdcl();
} }
compound_stmt switch_body
{ {
$$ = nod(OSELECT, $2, N); $$ = nod(OSELECT, $3, N);
popdcl();
} }
/* /*
...@@ -1849,6 +1881,15 @@ ostmt_list: ...@@ -1849,6 +1881,15 @@ ostmt_list:
$$ = rev($1); $$ = rev($1);
} }
ocaseblock_list:
{
$$ = N;
}
| caseblock_list_r
{
$$ = rev($1);
}
oxdcl_list: oxdcl_list:
{ {
$$ = N; $$ = N;
......
...@@ -348,8 +348,8 @@ newlabel() ...@@ -348,8 +348,8 @@ newlabel()
void void
casebody(Node *sw) casebody(Node *sw)
{ {
Iter save; Iter save, save1;
Node *os, *oc, *n, *c; Node *os, *oc, *n, *n1, *c;
Node *cas, *stat, *def; Node *cas, *stat, *def;
Node *go, *br; Node *go, *br;
int32 lno; int32 lno;
...@@ -368,70 +368,56 @@ casebody(Node *sw) ...@@ -368,70 +368,56 @@ casebody(Node *sw)
oc = N; // last case oc = N; // last case
br = nod(OBREAK, N, N); br = nod(OBREAK, N, N);
loop: for(; n != N; n = listnext(&save)) {
if(n == N) { lno = setlineno(n);
if(oc == N && os != N) if(n->op != OXCASE)
yyerror("first switch statement must be a case"); fatal("casebody %O", n->op);
n->op = OCASE;
stat = list(stat, br);
cas = list(cas, def); go = nod(OGOTO, newlabel(), N);
c = n->left;
sw->nbody = nod(OLIST, rev(cas), rev(stat)); if(c == N) {
//dump("case", sw->nbody->left); if(def != N)
//dump("stat", sw->nbody->right); yyerror("more than one default case");
lineno = lno; // reuse original default case
return; n->right = go;
} def = n;
}
lno = setlineno(n);
if(n->op != OXCASE) {
stat = list(stat, n);
os = n;
goto next;
}
n->op = OCASE;
if(oc == N && os != N)
yyerror("first switch statement must be a case");
// botch - shouldnt fall thru declaration // expand multi-valued cases
if(os != N && os->op == OXFALL) for(; c!=N; c=c->right) {
os->op = OFALL; if(c->op != OLIST) {
else // reuse original case
stat = list(stat, br); n->left = c;
n->right = go;
cas = list(cas, n);
break;
}
cas = list(cas, nod(OCASE, c->left, go));
}
go = nod(OGOTO, newlabel(), N); stat = list(stat, nod(OLABEL, go->left, N));
c = n->left; os = N;
if(c == N) { for(n1 = listfirst(&save1, &n->nbody); n1 != N; n1 = listnext(&save1)) {
if(def != N) os = n1;
yyerror("more than one default case"); stat = list(stat, n1);
}
// reuse original default case // botch - shouldnt fall thru declaration
n->right = go; if(os != N && os->op == OXFALL)
def = n; os->op = OFALL;
else
stat = list(stat, br);
} }
// expand multi-valued cases stat = list(stat, br);
for(; c!=N; c=c->right) { cas = list(cas, def);
if(c->op != OLIST) {
// reuse original case
n->left = c;
n->right = go;
cas = list(cas, n);
break;
}
cas = list(cas, nod(OCASE, c->left, go));
}
stat = list(stat, nod(OLABEL, go->left, N));
oc = n;
os = N;
goto next;
next: sw->nbody = nod(OLIST, rev(cas), rev(stat));
n = listnext(&save); //dump("case", sw->nbody->left);
goto loop; //dump("stat", sw->nbody->right);
lineno = lno;
} }
Case* Case*
......
...@@ -1539,8 +1539,8 @@ bad: ...@@ -1539,8 +1539,8 @@ bad:
void void
walkselect(Node *sel) walkselect(Node *sel)
{ {
Iter iter; Iter iter, iter1;
Node *n, *l, *oc, *on, *r; Node *n, *n1, *l, *oc, *on, *r;
Node *var, *bod, *nbod, *res, *def; Node *var, *bod, *nbod, *res, *def;
int count, op; int count, op;
int32 lno; int32 lno;
...@@ -1552,8 +1552,10 @@ walkselect(Node *sel) ...@@ -1552,8 +1552,10 @@ walkselect(Node *sel)
tempname(var, ptrto(types[TUINT8])); tempname(var, ptrto(types[TUINT8]));
n = listfirst(&iter, &sel->left); n = listfirst(&iter, &sel->left);
if(n == N || n->op != OXCASE) if(n == N || n->op == OEMPTY) {
yyerror("first select statement must be a case"); yyerror("empty select");
return;
}
count = 0; // number of cases count = 0; // number of cases
res = N; // entire select body res = N; // entire select body
...@@ -1563,72 +1565,67 @@ walkselect(Node *sel) ...@@ -1563,72 +1565,67 @@ walkselect(Node *sel)
for(; n!=N; n=listnext(&iter)) { for(; n!=N; n=listnext(&iter)) {
setlineno(n); setlineno(n);
if(n->op != OXCASE)
fatal("walkselect %O", n->op);
switch(n->op) { count++;
if(n->left == N) {
op = ORECV; // actual value not used
if(def != N)
yyerror("repeated default; first at %L", def->lineno);
def = n;
} else
op = n->left->op;
nbod = N;
switch(op) {
default: default:
bod = list(bod, n); yyerror("select cases must be send, recv or default");
break; continue;
case OXCASE: case OAS:
if(n->left == N) { // convert new syntax (a=recv(chan)) to (recv(a,chan))
op = ORECV; // actual value not used l = n->left;
if(def != N) if(l->right == N || l->right->op != ORECV) {
yyerror("only one default select allowed");
def = n;
} else
op = n->left->op;
nbod = N;
switch(op) {
default:
yyerror("select cases must be send, recv or default"); yyerror("select cases must be send, recv or default");
break; break;
case OAS:
// convert new syntax (a=recv(chan)) to (recv(a,chan))
l = n->left;
if(l->right == N || l->right->op != ORECV) {
yyerror("select cases must be send, recv or default");
break;
}
r = l->right; // rcv
r->right = r->left;
r->left = l->left;
n->left = r;
// convert case x := foo: body
// to case tmp := foo: x := tmp; body.
// if x escapes and must be allocated
// on the heap, this delays the allocation
// until after the select has chosen this branch.
if(n->ninit != N && n->ninit->op == ODCL) {
on = nod(OXXX, N, N);
tempname(on, l->left->type);
on->sym = lookup("!tmpselect!");
r->left = on;
nbod = nod(OAS, l->left, on);
nbod->ninit = n->ninit;
n->ninit = N;
}
// fall through
case OSEND:
case ORECV:
if(oc != N) {
bod = list(bod, nod(OBREAK, N, N));
oc->nbody = rev(bod);
}
oc = selcase(n, var);
res = list(res, oc);
break;
} }
bod = nbod; r = l->right; // rcv
count++; r->right = r->left;
r->left = l->left;
n->left = r;
// convert case x := foo: body
// to case tmp := foo: x := tmp; body.
// if x escapes and must be allocated
// on the heap, this delays the allocation
// until after the select has chosen this branch.
if(n->ninit != N && n->ninit->op == ODCL) {
on = nod(OXXX, N, N);
tempname(on, l->left->type);
on->sym = lookup("!tmpselect!");
r->left = on;
nbod = nod(OAS, l->left, on);
nbod->ninit = n->ninit;
n->ninit = N;
}
break;
case OSEND:
case ORECV:
break; break;
} }
}
if(oc != N) { for(n1 = listfirst(&iter1, &n->nbody); n1 != N; n1 = listnext(&iter1))
bod = list(bod, nod(OBREAK, N, N)); nbod = list(nbod, n1);
oc->nbody = rev(bod); nbod = list(nbod, nod(OBREAK, N, N));
n->nbody = N;
oc = selcase(n, var);
if(oc != N) {
oc->nbody = rev(nbod);
res = list(res, oc);
}
} }
setlineno(sel); setlineno(sel);
......
...@@ -104,11 +104,6 @@ BUG should compile ...@@ -104,11 +104,6 @@ BUG should compile
5 7 5 7
BUG: should crash BUG: should crash
=========== bugs/bug157.go
bugs/bug157.go:20: syntax error near default
bugs/bug157.go:20: first switch statement must be a case
BUG: should compile
=========== fixedbugs/bug016.go =========== fixedbugs/bug016.go
fixedbugs/bug016.go:7: constant -3 overflows uint fixedbugs/bug016.go:7: constant -3 overflows uint
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment