error for repeated label + jumps allowed to labels followed by
'no-op' statements
This commit is contained in:
62
lparser.c
62
lparser.c
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: lparser.c,v 2.104 2011/02/10 14:50:41 roberto Exp roberto $
|
** $Id: lparser.c,v 2.105 2011/02/14 14:59:28 roberto Exp roberto $
|
||||||
** Lua Parser
|
** Lua Parser
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@@ -339,8 +339,8 @@ static void enterlevel (LexState *ls) {
|
|||||||
static void closegoto (LexState *ls, int g, Labeldesc *label) {
|
static void closegoto (LexState *ls, int g, Labeldesc *label) {
|
||||||
int i;
|
int i;
|
||||||
FuncState *fs = ls->fs;
|
FuncState *fs = ls->fs;
|
||||||
Dyndata *dyd = ls->dyd;
|
Labellist *gl = &ls->dyd->gt;
|
||||||
Labeldesc *gt = &dyd->gt.arr[g];
|
Labeldesc *gt = &gl->arr[g];
|
||||||
lua_assert(eqstr(gt->name, label->name));
|
lua_assert(eqstr(gt->name, label->name));
|
||||||
if (gt->nactvar < label->nactvar) {
|
if (gt->nactvar < label->nactvar) {
|
||||||
const char *msg = luaO_pushfstring(ls->L,
|
const char *msg = luaO_pushfstring(ls->L,
|
||||||
@@ -350,9 +350,9 @@ static void closegoto (LexState *ls, int g, Labeldesc *label) {
|
|||||||
}
|
}
|
||||||
luaK_patchlist(fs, gt->pc, label->pc);
|
luaK_patchlist(fs, gt->pc, label->pc);
|
||||||
/* remove goto from pending list */
|
/* remove goto from pending list */
|
||||||
for (i = g; i < dyd->gt.n - 1; i++)
|
for (i = g; i < gl->n - 1; i++)
|
||||||
dyd->gt.arr[i] = dyd->gt.arr[i + 1];
|
gl->arr[i] = gl->arr[i + 1];
|
||||||
dyd->gt.n--;
|
gl->n--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -397,10 +397,10 @@ static int newlabelentry (LexState *ls, Labellist *l, TString *name,
|
|||||||
** block; solves forward jumps
|
** block; solves forward jumps
|
||||||
*/
|
*/
|
||||||
static void findgotos (LexState *ls, Labeldesc *lb) {
|
static void findgotos (LexState *ls, Labeldesc *lb) {
|
||||||
Dyndata *dyd = ls->dyd;
|
Labellist *gl = &ls->dyd->gt;
|
||||||
int i = ls->fs->bl->firstgoto;
|
int i = ls->fs->bl->firstgoto;
|
||||||
while (i < dyd->gt.n) {
|
while (i < gl->n) {
|
||||||
if (eqstr(dyd->gt.arr[i].name, lb->name))
|
if (eqstr(gl->arr[i].name, lb->name))
|
||||||
closegoto(ls, i, lb);
|
closegoto(ls, i, lb);
|
||||||
else
|
else
|
||||||
i++;
|
i++;
|
||||||
@@ -416,11 +416,11 @@ static void findgotos (LexState *ls, Labeldesc *lb) {
|
|||||||
*/
|
*/
|
||||||
static void movegotosout (FuncState *fs, BlockCnt *bl) {
|
static void movegotosout (FuncState *fs, BlockCnt *bl) {
|
||||||
int i = bl->firstgoto;
|
int i = bl->firstgoto;
|
||||||
Dyndata *dyd = fs->ls->dyd;
|
Labellist *gl = &fs->ls->dyd->gt;
|
||||||
/* correct pending gotos to current block and try to close it
|
/* correct pending gotos to current block and try to close it
|
||||||
with visible labels */
|
with visible labels */
|
||||||
while (i < dyd->gt.n) {
|
while (i < gl->n) {
|
||||||
Labeldesc *gt = &dyd->gt.arr[i];
|
Labeldesc *gt = &gl->arr[i];
|
||||||
if (gt->nactvar > bl->nactvar) {
|
if (gt->nactvar > bl->nactvar) {
|
||||||
if (bl->upval)
|
if (bl->upval)
|
||||||
luaK_patchclose(fs, gt->pc, bl->nactvar);
|
luaK_patchclose(fs, gt->pc, bl->nactvar);
|
||||||
@@ -1185,21 +1185,31 @@ static void gotostat (LexState *ls, TString *label, int line) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void labelstat (LexState *ls, TString *label) {
|
static void labelstat (LexState *ls, TString *label, int line) {
|
||||||
/* label -> '@' NAME ':' */
|
/* label -> '@' NAME ':' */
|
||||||
FuncState *fs = ls->fs;
|
FuncState *fs = ls->fs;
|
||||||
int l; /* index of new label being created */
|
Labellist *ll = &ls->dyd->label;
|
||||||
Labeldesc *lb;
|
int l, i; /* index of new label being created */
|
||||||
checknext(ls, ':');
|
/* check for repeated labels on the same block */
|
||||||
/* create new entry for this label */
|
for (i = ls->fs->bl->firstlabel; i < ll->n; i++) {
|
||||||
l = newlabelentry(ls, &ls->dyd->label, label, 0, fs->pc);
|
if (eqstr(label, ll->arr[i].name)) {
|
||||||
lb = &ls->dyd->label.arr[l];
|
const char *msg = luaO_pushfstring(ls->L,
|
||||||
while (testnext(ls, ';')) ; /* skip trailing semicolons */
|
"label " LUA_QS " already defined on line %d",
|
||||||
if (block_follow(ls, 0)) { /* label is last statement in the block? */
|
getstr(label), ll->arr[i].line);
|
||||||
/* assume that locals are already out of scope */
|
semerror(ls, msg);
|
||||||
lb->nactvar = fs->bl->nactvar;
|
}
|
||||||
}
|
}
|
||||||
findgotos(ls, lb);
|
checknext(ls, ':'); /* skip colon */
|
||||||
|
/* create new entry for this label */
|
||||||
|
l = newlabelentry(ls, ll, label, line, fs->pc);
|
||||||
|
/* skip other no-op statements */
|
||||||
|
while (ls->t.token == ';' || ls->t.token == '@')
|
||||||
|
statement(ls);
|
||||||
|
if (block_follow(ls, 0)) { /* label is last no-op statement in the block? */
|
||||||
|
/* assume that locals are already out of scope */
|
||||||
|
ll->arr[l].nactvar = fs->bl->nactvar;
|
||||||
|
}
|
||||||
|
findgotos(ls, &ll->arr[l]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1476,7 +1486,7 @@ static void retstat (LexState *ls) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
luaK_ret(fs, first, nret);
|
luaK_ret(fs, first, nret);
|
||||||
testnext(ls, ';'); /* skip optional semicollon */
|
testnext(ls, ';'); /* skip optional semicolon */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1524,7 +1534,7 @@ static void statement (LexState *ls) {
|
|||||||
}
|
}
|
||||||
case '@': { /* stat -> label */
|
case '@': { /* stat -> label */
|
||||||
luaX_next(ls); /* skip '@' */
|
luaX_next(ls); /* skip '@' */
|
||||||
labelstat(ls, str_checkname(ls));
|
labelstat(ls, str_checkname(ls), line);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TK_RETURN: { /* stat -> retstat */
|
case TK_RETURN: { /* stat -> retstat */
|
||||||
|
|||||||
Reference in New Issue
Block a user