commit 6819c2a98adebaea1a8d1b065364f3b3748072aa
parent 1dd8af67b6b1f1c970967b96b2f1b2edabe551c4
Author: Roberto Ierusalimschy <roberto@inf.puc-rio.br>
Date: Mon, 24 Oct 2011 12:51:20 -0200
silly bug in 5.2 beta: assignment conflict code did not test to check
whether variable was a table element
Diffstat:
M | lparser.c | | | 37 | ++++++++++++++++++++----------------- |
1 file changed, 20 insertions(+), 17 deletions(-)
diff --git a/lparser.c b/lparser.c
@@ -1,5 +1,5 @@
/*
-** $Id: lparser.c,v 2.119 2011/09/14 17:40:26 roberto Exp roberto $
+** $Id: lparser.c,v 2.120 2011/09/30 12:44:45 roberto Exp roberto $
** Lua Parser
** See Copyright Notice in lua.h
*/
@@ -1106,31 +1106,34 @@ struct LHS_assign {
/*
-** check whether, in an assignment to a local variable, the local variable
-** is needed in a previous assignment (to a table). If so, save original
-** local value in a safe place and use this safe copy in the previous
-** assignment.
+** check whether, in an assignment to an upvalue/local variable, the
+** upvalue/local variable is begin used in a previous assignment to a
+** table. If so, save original upvalue/local value in a safe place and
+** use this safe copy in the previous assignment.
*/
static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) {
FuncState *fs = ls->fs;
int extra = fs->freereg; /* eventual position to save local variable */
int conflict = 0;
- for (; lh; lh = lh->prev) {
- /* conflict in table 't'? */
- if (lh->v.u.ind.vt == v->k && lh->v.u.ind.t == v->u.info) {
- conflict = 1;
- lh->v.u.ind.vt = VLOCAL;
- lh->v.u.ind.t = extra; /* previous assignment will use safe copy */
- }
- /* conflict in index 'idx'? */
- if (v->k == VLOCAL && lh->v.u.ind.idx == v->u.info) {
- conflict = 1;
- lh->v.u.ind.idx = extra; /* previous assignment will use safe copy */
+ for (; lh; lh = lh->prev) { /* check all previous assignments */
+ if (lh->v.k == VINDEXED) { /* assigning to a table? */
+ /* table is the upvalue/local being assigned now? */
+ if (lh->v.u.ind.vt == v->k && lh->v.u.ind.t == v->u.info) {
+ conflict = 1;
+ lh->v.u.ind.vt = VLOCAL;
+ lh->v.u.ind.t = extra; /* previous assignment will use safe copy */
+ }
+ /* index is the local being assigned? (index cannot be upvalue) */
+ if (v->k == VLOCAL && lh->v.u.ind.idx == v->u.info) {
+ conflict = 1;
+ lh->v.u.ind.idx = extra; /* previous assignment will use safe copy */
+ }
}
}
if (conflict) {
+ /* copy upvalue/local value to a temporary (in position 'extra') */
OpCode op = (v->k == VLOCAL) ? OP_MOVE : OP_GETUPVAL;
- luaK_codeABC(fs, op, fs->freereg, v->u.info, 0); /* make copy */
+ luaK_codeABC(fs, op, extra, v->u.info, 0);
luaK_reserveregs(fs, 1);
}
}