diff options
| -rw-r--r-- | lparser.c | 21 | ||||
| -rw-r--r-- | testes/locals.lua | 23 |
2 files changed, 38 insertions, 6 deletions
| @@ -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 | */ | ||
| 422 | static 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 | ||
| 1706 | static void checktoclose (LexState *ls, int level) { | 1717 | static 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 | ||
diff --git a/testes/locals.lua b/testes/locals.lua index 2c67edbd..6aad5d25 100644 --- a/testes/locals.lua +++ b/testes/locals.lua | |||
| @@ -335,6 +335,29 @@ do | |||
| 335 | end | 335 | end |
| 336 | 336 | ||
| 337 | 337 | ||
| 338 | do | ||
| 339 | -- bug in 5.4.3: previous condition (calls cannot be tail in the | ||
| 340 | -- scope of to-be-closed variables) must be valid for tbc variables | ||
| 341 | -- created by 'for' loops. | ||
| 342 | |||
| 343 | local closed = false | ||
| 344 | |||
| 345 | local function foo () | ||
| 346 | return function () return true end, 0, 0, | ||
| 347 | func2close(function () closed = true end) | ||
| 348 | end | ||
| 349 | |||
| 350 | local function tail() return closed end | ||
| 351 | |||
| 352 | local function foo1 () | ||
| 353 | for k in foo() do return tail() end | ||
| 354 | end | ||
| 355 | |||
| 356 | assert(foo1() == false) | ||
| 357 | assert(closed == true) | ||
| 358 | end | ||
| 359 | |||
| 360 | |||
| 338 | do print("testing errors in __close") | 361 | do print("testing errors in __close") |
| 339 | 362 | ||
| 340 | -- original error is in __close | 363 | -- original error is in __close |
