aboutsummaryrefslogtreecommitdiff
path: root/lparser.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2021-04-07 14:59:26 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2021-04-07 14:59:26 -0300
commit47cffdc723c2e0c6dfaf62b7775ca1c1d338c0a4 (patch)
tree54d46a0530aa2ee09db66d57c66bd313a5de530e /lparser.c
parent36de01d9885562444ae2e2a3e0b7e01b3fb8743b (diff)
downloadlua-47cffdc723c2e0c6dfaf62b7775ca1c1d338c0a4.tar.gz
lua-47cffdc723c2e0c6dfaf62b7775ca1c1d338c0a4.tar.bz2
lua-47cffdc723c2e0c6dfaf62b7775ca1c1d338c0a4.zip
Bug: tbc variables in "for" loops don't avoid tail calls
Diffstat (limited to 'lparser.c')
-rw-r--r--lparser.c21
1 files changed, 15 insertions, 6 deletions
diff --git a/lparser.c b/lparser.c
index 284ef1f0..df9473c2 100644
--- a/lparser.c
+++ b/lparser.c
@@ -417,6 +417,17 @@ static void markupval (FuncState *fs, int level) {
417 417
418 418
419/* 419/*
420** Mark that current block has a to-be-closed variable.
421*/
422static void marktobeclosed (FuncState *fs) {
423 BlockCnt *bl = fs->bl;
424 bl->upval = 1;
425 bl->insidetbc = 1;
426 fs->needclose = 1;
427}
428
429
430/*
420** Find a variable with the given name 'n'. If it is an upvalue, add 431** Find a variable with the given name 'n'. If it is an upvalue, add
421** this upvalue into all intermediate functions. If it is a global, set 432** this upvalue into all intermediate functions. If it is a global, set
422** 'var' as 'void' as a flag. 433** 'var' as 'void' as a flag.
@@ -1599,7 +1610,7 @@ static void forlist (LexState *ls, TString *indexname) {
1599 line = ls->linenumber; 1610 line = ls->linenumber;
1600 adjust_assign(ls, 4, explist(ls, &e), &e); 1611 adjust_assign(ls, 4, explist(ls, &e), &e);
1601 adjustlocalvars(ls, 4); /* control variables */ 1612 adjustlocalvars(ls, 4); /* control variables */
1602 markupval(fs, fs->nactvar); /* last control var. must be closed */ 1613 marktobeclosed(fs); /* last control var. must be closed */
1603 luaK_checkstack(fs, 3); /* extra space to call generator */ 1614 luaK_checkstack(fs, 3); /* extra space to call generator */
1604 forbody(ls, base, line, nvars - 4, 1); 1615 forbody(ls, base, line, nvars - 4, 1);
1605} 1616}
@@ -1703,11 +1714,9 @@ static int getlocalattribute (LexState *ls) {
1703} 1714}
1704 1715
1705 1716
1706static void checktoclose (LexState *ls, int level) { 1717static void checktoclose (FuncState *fs, int level) {
1707 if (level != -1) { /* is there a to-be-closed variable? */ 1718 if (level != -1) { /* is there a to-be-closed variable? */
1708 FuncState *fs = ls->fs; 1719 marktobeclosed(fs);
1709 markupval(fs, level + 1);
1710 fs->bl->insidetbc = 1; /* in the scope of a to-be-closed variable */
1711 luaK_codeABC(fs, OP_TBC, reglevel(fs, level), 0, 0); 1720 luaK_codeABC(fs, OP_TBC, reglevel(fs, level), 0, 0);
1712 } 1721 }
1713} 1722}
@@ -1751,7 +1760,7 @@ static void localstat (LexState *ls) {
1751 adjust_assign(ls, nvars, nexps, &e); 1760 adjust_assign(ls, nvars, nexps, &e);
1752 adjustlocalvars(ls, nvars); 1761 adjustlocalvars(ls, nvars);
1753 } 1762 }
1754 checktoclose(ls, toclose); 1763 checktoclose(fs, toclose);
1755} 1764}
1756 1765
1757 1766