Commit 417a971f authored by Ken Thompson's avatar Ken Thompson

output args declared

arguments in first block for diagnostics
thomo return
better syntax error recovery

SVN=126045
parent ac5a887d
...@@ -106,6 +106,26 @@ allocparams(void) ...@@ -106,6 +106,26 @@ allocparams(void)
t = funcnext(&list); t = funcnext(&list);
} }
t = structfirst(&list, getoutarg(curfn->type));
while(t != T) {
if(t->nname != N && t->nname->sym->name[0] != '_') {
if(d == D)
fatal("allocparams: this nil");
if(d->op != ONAME) {
d = d->forw;
continue;
}
n = d->dnode;
if(n->class != PPARAM)
fatal("allocparams: this class");
n->xoffset = t->width;
d = d->forw;
}
t = structnext(&list);
}
/* /*
* allocate (set xoffset) the stack * allocate (set xoffset) the stack
* slots for all automatics. * slots for all automatics.
......
...@@ -353,7 +353,7 @@ funchdr(Node *n) ...@@ -353,7 +353,7 @@ funchdr(Node *n)
fatal("funchdr: dclcontext"); fatal("funchdr: dclcontext");
dclcontext = PAUTO; dclcontext = PAUTO;
markdcl("func"); markdcl();
funcargs(n->type); funcargs(n->type);
if(n->type->thistuple > 0) { if(n->type->thistuple > 0) {
...@@ -368,8 +368,9 @@ funcargs(Type *t) ...@@ -368,8 +368,9 @@ funcargs(Type *t)
{ {
Type *n1; Type *n1;
Iter save; Iter save;
int all;
// declare the this argument // declare the this/in arguments
n1 = funcfirst(&save, t); n1 = funcfirst(&save, t);
while(n1 != T) { while(n1 != T) {
if(n1->nname != N) if(n1->nname != N)
...@@ -378,13 +379,22 @@ funcargs(Type *t) ...@@ -378,13 +379,22 @@ funcargs(Type *t)
} }
// declare the outgoing arguments // declare the outgoing arguments
// n1 = structfirst(&save, getoutarg(t)); all = 0;
// while(n1 != T) { n1 = structfirst(&save, getoutarg(t));
// n1->left = newname(n1->sym); while(n1 != T) {
// if(n1->nname != N) if(n1->nname != N && n1->nname->sym->name[0] != '_') {
// addvar(n1->nname, n1->type, PPARAM); addvar(n1->nname, n1->type, PPARAM);
// n1 = structnext(&save); all |= 1;
// } } else
all |= 2;
n1 = structnext(&save);
}
if(all == 3)
yyerror("output parameters are all named or not named");
t->outnamed = 0;
if(all == 1)
t->outnamed = 1;
} }
/* /*
...@@ -401,7 +411,7 @@ funcbody(Node *n) ...@@ -401,7 +411,7 @@ funcbody(Node *n)
// change the declaration context from auto to extern // change the declaration context from auto to extern
if(dclcontext != PAUTO) if(dclcontext != PAUTO)
fatal("funcbody: dclcontext"); fatal("funcbody: dclcontext");
popdcl("func"); popdcl();
dclcontext = PEXTERN; dclcontext = PEXTERN;
} }
...@@ -515,7 +525,7 @@ pushdcl(Sym *s) ...@@ -515,7 +525,7 @@ pushdcl(Sym *s)
} }
void void
popdcl(char *why) popdcl(void)
{ {
Sym *d, *s; Sym *d, *s;
...@@ -532,8 +542,6 @@ popdcl(char *why) ...@@ -532,8 +542,6 @@ popdcl(char *why)
} }
if(d == S) if(d == S)
fatal("popdcl: no mark"); fatal("popdcl: no mark");
if(strcmp(why, d->package) != 0)
fatal("popdcl: pushed as %s popped as %s", d->package, why);
dclstack = d->link; dclstack = d->link;
block = d->vblock; block = d->vblock;
} }
...@@ -556,17 +564,17 @@ poptodcl(void) ...@@ -556,17 +564,17 @@ poptodcl(void)
} }
void void
markdcl(char *why) markdcl(void)
{ {
Sym *d; Sym *d;
d = push(); d = push();
d->name = nil; // used as a mark in fifo d->name = nil; // used as a mark in fifo
d->package = why; // diagnostic for unmatched
d->vblock = block; d->vblock = block;
blockgen++; blockgen++;
block = blockgen; block = blockgen;
// if(dflag()) // if(dflag())
// print("markdcl\n"); // print("markdcl\n");
} }
...@@ -576,7 +584,7 @@ markdclstack(void) ...@@ -576,7 +584,7 @@ markdclstack(void)
{ {
Sym *d, *s; Sym *d, *s;
markdcl("fnlit"); markdcl();
// copy the entire pop of the stack // copy the entire pop of the stack
// all the way back to block0. // all the way back to block0.
...@@ -639,8 +647,14 @@ addvar(Node *n, Type *t, int ctxt) ...@@ -639,8 +647,14 @@ addvar(Node *n, Type *t, int ctxt)
gen = 0; gen = 0;
} }
if(s->vblock == block) if(s->vblock == block) {
yyerror("var %S redeclared in this block %d", s, block); if(s->oname != N) {
yyerror("var %S redeclared in this block"
"\n previous declaration at %L",
s, s->oname->lineno);
} else
yyerror("var %S redeclared in this block", s);
}
if(ctxt != PEXTERN) if(ctxt != PEXTERN)
pushdcl(s); pushdcl(s);
......
...@@ -80,6 +80,7 @@ struct Type ...@@ -80,6 +80,7 @@ struct Type
uchar thistuple; uchar thistuple;
uchar outtuple; uchar outtuple;
uchar intuple; uchar intuple;
uchar outnamed;
Sym* sym; Sym* sym;
long vargen; // unique name for OTYPE/ONAME long vargen; // unique name for OTYPE/ONAME
...@@ -144,7 +145,7 @@ struct Node ...@@ -144,7 +145,7 @@ struct Node
Sym* psym; // import Sym* psym; // import
Sym* sym; // various Sym* sym; // various
long vargen; // unique name for OTYPE/ONAME long vargen; // unique name for OTYPE/ONAME
ulong lineno; long lineno;
vlong xoffset; vlong xoffset;
}; };
#define N ((Node*)0) #define N ((Node*)0)
...@@ -525,8 +526,8 @@ void funcbody(Node*); ...@@ -525,8 +526,8 @@ void funcbody(Node*);
Type* dostruct(Node*, int); Type* dostruct(Node*, int);
Type** stotype(Node*, Type**); Type** stotype(Node*, Type**);
Type* sortinter(Type*); Type* sortinter(Type*);
void markdcl(char*); void markdcl(void);
void popdcl(char*); void popdcl(void);
void poptodcl(void); void poptodcl(void);
void markdclstack(void); void markdclstack(void);
void testdclstack(void); void testdclstack(void);
...@@ -566,6 +567,7 @@ void doimport7(Node*, Node*); ...@@ -566,6 +567,7 @@ void doimport7(Node*, Node*);
*/ */
void walk(Node*); void walk(Node*);
void walktype(Node*, int); void walktype(Node*, int);
void walkbool(Node*);
Type* walkswitch(Node*, Type*(*)(Node*, Type*)); Type* walkswitch(Node*, Type*(*)(Node*, Type*));
int casebody(Node*); int casebody(Node*);
int whatis(Node*); int whatis(Node*);
......
...@@ -47,8 +47,7 @@ ...@@ -47,8 +47,7 @@
%type <node> export_list_r export %type <node> export_list_r export
%type <node> hidden_importsym_list_r ohidden_importsym_list hidden_importsym isym %type <node> hidden_importsym_list_r ohidden_importsym_list hidden_importsym isym
%type <node> hidden_importfield_list_r ohidden_importfield_list hidden_importfield %type <node> hidden_importfield_list_r ohidden_importfield_list hidden_importfield
%type <node> fnbody %type <node> fnres Afnres Bfnres fnliteral xfndcl fndcl fnbody
%type <node> fnres Afnres Bfnres fnliteral xfndcl fndcl
%type <node> keyval_list_r keyval %type <node> keyval_list_r keyval
%type <node> typedcl Atypedcl Btypedcl %type <node> typedcl Atypedcl Btypedcl
...@@ -148,13 +147,9 @@ xdcl: ...@@ -148,13 +147,9 @@ xdcl:
{ {
$$ = N; $$ = N;
} }
| error '}' | error xdcl
{ {
$$ = N; $$ = $2;
}
| error ';'
{
$$ = N;
} }
common_dcl: common_dcl:
...@@ -330,13 +325,12 @@ inc_stmt: ...@@ -330,13 +325,12 @@ inc_stmt:
complex_stmt: complex_stmt:
LFOR for_stmt LFOR for_stmt
{ {
/* FOR and WHILE are the same keyword */ popdcl();
popdcl("for/while");
$$ = $2; $$ = $2;
} }
| LSWITCH if_stmt | LSWITCH if_stmt
{ {
popdcl("if/switch"); popdcl();
if(!casebody($2->nbody)) if(!casebody($2->nbody))
yyerror("switch statement must have case labels"); yyerror("switch statement must have case labels");
$$ = $2; $$ = $2;
...@@ -346,14 +340,14 @@ complex_stmt: ...@@ -346,14 +340,14 @@ complex_stmt:
} }
| LIF if_stmt | LIF if_stmt
{ {
popdcl("if/switch"); popdcl();
$$ = $2; $$ = $2;
//if($$->ninit != N && $$->ntest == N) //if($$->ninit != N && $$->ntest == N)
// yyerror("if conditional should not be missing"); // yyerror("if conditional should not be missing");
} }
| LIF if_stmt LELSE else_stmt1 | LIF if_stmt LELSE else_stmt1
{ {
popdcl("if/switch"); popdcl();
$$ = $2; $$ = $2;
$$->nelse = $4; $$->nelse = $4;
//if($$->ninit != N && $$->ntest == N) //if($$->ninit != N && $$->ntest == N)
...@@ -361,7 +355,7 @@ complex_stmt: ...@@ -361,7 +355,7 @@ complex_stmt:
} }
| LRANGE range_stmt | LRANGE range_stmt
{ {
popdcl("range"); popdcl();
$$ = $2; $$ = $2;
} }
| LCASE expr_list ':' | LCASE expr_list ':'
...@@ -414,7 +408,7 @@ semi_stmt: ...@@ -414,7 +408,7 @@ semi_stmt:
} }
| LIF if_stmt LELSE else_stmt2 | LIF if_stmt LELSE else_stmt2
{ {
popdcl("if/switch"); popdcl();
$$ = $2; $$ = $2;
$$->nelse = $4; $$->nelse = $4;
//if($$->ninit != N && $$->ntest == N) //if($$->ninit != N && $$->ntest == N)
...@@ -424,13 +418,13 @@ semi_stmt: ...@@ -424,13 +418,13 @@ semi_stmt:
compound_stmt: compound_stmt:
'{' '{'
{ {
markdcl("compound"); markdcl();
} ostmt_list '}' } ostmt_list '}'
{ {
$$ = $3; $$ = $3;
if($$ == N) if($$ == N)
$$ = nod(OEMPTY, N, N); $$ = nod(OEMPTY, N, N);
popdcl("compound"); popdcl();
} }
for_header: for_header:
...@@ -460,7 +454,7 @@ for_body: ...@@ -460,7 +454,7 @@ for_body:
for_stmt: for_stmt:
{ {
markdcl("for/while"); markdcl();
} for_body } for_body
{ {
$$ = $2; $$ = $2;
...@@ -491,7 +485,7 @@ if_body: ...@@ -491,7 +485,7 @@ if_body:
if_stmt: if_stmt:
{ {
markdcl("if/switch"); markdcl();
} if_body } if_body
{ {
$$ = $2; $$ = $2;
...@@ -521,7 +515,7 @@ range_body: ...@@ -521,7 +515,7 @@ range_body:
range_stmt: range_stmt:
{ {
markdcl("range"); markdcl();
} range_body } range_body
{ {
$$ = $2; $$ = $2;
...@@ -1012,7 +1006,7 @@ fnlitdcl: ...@@ -1012,7 +1006,7 @@ fnlitdcl:
fnliteral: fnliteral:
fnlitdcl '{' ostmt_list '}' fnlitdcl '{' ostmt_list '}'
{ {
popdcl("fnlit"); popdcl();
vargen++; vargen++;
snprint(namebuf, sizeof(namebuf), "_f%.3ld", vargen); snprint(namebuf, sizeof(namebuf), "_f%.3ld", vargen);
...@@ -1036,16 +1030,17 @@ fnliteral: ...@@ -1036,16 +1030,17 @@ fnliteral:
} }
fnbody: fnbody:
compound_stmt '{' ostmt_list '}'
{ {
$$ = $1; $$ = $2;
if($$->op == OEMPTY) if($$ == N)
$$ = nod(ORETURN, N, N); $$ = nod(ORETURN, N, N);
} }
| ';' | ';'
{ {
$$ = N; $$ = N;
} }
fnres: fnres:
Afnres Afnres
| Bfnres | Bfnres
...@@ -1202,11 +1197,7 @@ Astmt: ...@@ -1202,11 +1197,7 @@ Astmt:
{ {
$$ = N; $$ = N;
} }
| error ';' | error Astmt
{
$$ = N;
}
| error '}'
{ {
$$ = N; $$ = N;
} }
...@@ -1218,6 +1209,10 @@ Astmt: ...@@ -1218,6 +1209,10 @@ Astmt:
Bstmt: Bstmt:
semi_stmt semi_stmt
| Bcommon_dcl | Bcommon_dcl
| error Bstmt
{
$$ = N;
}
/* /*
* need semi in front YES * need semi in front YES
......
...@@ -550,7 +550,7 @@ tnum: ...@@ -550,7 +550,7 @@ tnum:
} }
*cp++ = c; *cp++ = c;
c = getc(); c = getc();
if(c == 'x' || c == 'X') if(c == 'x' || c == 'X') {
for(;;) { for(;;) {
*cp++ = c; *cp++ = c;
c = getc(); c = getc();
...@@ -564,16 +564,24 @@ tnum: ...@@ -564,16 +564,24 @@ tnum:
yyerror("malformed hex constant"); yyerror("malformed hex constant");
goto ncu; goto ncu;
} }
if(c < '0' || c > '7') }
goto dc;
c1 = 0;
for(;;) { for(;;) {
if(c >= '0' && c <= '7') { if(!isdigit(c))
*cp++ = c; break;
c = getc(); if(c < '0' || c > '7')
continue; c1 = 1; // not octal
} *cp++ = c;
goto ncu; c = getc();
} }
if(c == '.')
goto casedot;
if(c == 'e' || c == 'E')
goto casee;
if(c1)
yyerror("malformed octal constant");
goto ncu;
dc: dc:
if(c == '.') if(c == '.')
......
...@@ -112,7 +112,7 @@ loop: ...@@ -112,7 +112,7 @@ loop:
if(top != Etop) if(top != Etop)
goto nottop; goto nottop;
walktype(n->ninit, Etop); walktype(n->ninit, Etop);
walktype(n->ntest, Erv); walkbool(n->ntest);
walktype(n->nincr, Etop); walktype(n->nincr, Etop);
n = n->nbody; n = n->nbody;
goto loop; goto loop;
...@@ -151,7 +151,7 @@ loop: ...@@ -151,7 +151,7 @@ loop:
if(top != Etop) if(top != Etop)
goto nottop; goto nottop;
walktype(n->ninit, Etop); walktype(n->ninit, Etop);
walktype(n->ntest, Erv); walkbool(n->ntest);
walktype(n->nelse, Etop); walktype(n->nelse, Etop);
n = n->nbody; n = n->nbody;
goto loop; goto loop;
...@@ -377,6 +377,10 @@ loop: ...@@ -377,6 +377,10 @@ loop:
if(top != Etop) if(top != Etop)
goto nottop; goto nottop;
walktype(n->left, Erv); walktype(n->left, Erv);
if(curfn->type->outnamed && n->left == N) {
// print("special return\n");
goto ret;
}
l = ascompatte(n->op, getoutarg(curfn->type), &n->left, 1); l = ascompatte(n->op, getoutarg(curfn->type), &n->left, 1);
if(l != N) if(l != N)
n->left = reorder4(l); n->left = reorder4(l);
...@@ -722,6 +726,15 @@ ret: ...@@ -722,6 +726,15 @@ ret:
lineno = lno; lineno = lno;
} }
void
walkbool(Node *n)
{
walktype(n, Erv);
if(n != N && n->type != T)
if(!eqtype(n->type, types[TBOOL], 0))
yyerror("IF and FOR require a boolean type");
}
/* /*
* return the first type * return the first type
*/ */
......
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