From 28d829c86712ce5bc453feccc5129a32f78d80c0 Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Tue, 4 Dec 2018 15:01:42 -0200 Subject: Calls cannot be tail in the scope of a to-be-closed variable A to-be-closed variable must be closed when a block ends, so even a 'return foo()' cannot directly returns the results of 'foo'; the function must close the scope before returning. --- lparser.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'lparser.c') diff --git a/lparser.c b/lparser.c index e525e578..eed8bffd 100644 --- a/lparser.c +++ b/lparser.c @@ -53,6 +53,7 @@ typedef struct BlockCnt { lu_byte nactvar; /* # active locals outside the block */ lu_byte upval; /* true if some variable in the block is an upvalue */ lu_byte isloop; /* true if 'block' is a loop */ + lu_byte insidetbc; /* true if inside the scope of a to-be-closed var. */ } BlockCnt; @@ -510,6 +511,7 @@ static void enterblock (FuncState *fs, BlockCnt *bl, lu_byte isloop) { bl->firstlabel = fs->ls->dyd->label.n; bl->firstgoto = fs->ls->dyd->gt.n; bl->upval = 0; + bl->insidetbc = (fs->bl != NULL && fs->bl->insidetbc); bl->previous = fs->bl; fs->bl = bl; lua_assert(fs->freereg == fs->nactvar); @@ -1631,6 +1633,7 @@ static void tocloselocalstat (LexState *ls) { checknext(ls, '='); exp1(ls, 0); markupval(fs, fs->nactvar); + fs->bl->insidetbc = 1; /* in the scope of a to-be-closed variable */ adjustlocalvars(ls, 1); luaK_codeABC(fs, OP_TBC, fs->nactvar - 1, 0, 0); } @@ -1701,7 +1704,7 @@ static void retstat (LexState *ls) { nret = explist(ls, &e); /* optional return values */ if (hasmultret(e.k)) { luaK_setmultret(fs, &e); - if (e.k == VCALL && nret == 1) { /* tail call? */ + if (e.k == VCALL && nret == 1 && !fs->bl->insidetbc) { /* tail call? */ SET_OPCODE(getinstruction(fs,&e), OP_TAILCALL); lua_assert(GETARG_A(getinstruction(fs,&e)) == fs->nactvar); } -- cgit v1.2.3-55-g6feb